> ## Documentation Index
> Fetch the complete documentation index at: https://docs.notareum.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Verification engine

# Verification Engine

The Verification Engine is the decentralized consensus layer of Notareum. When a resource owner wants cryptographic proof that their resource is genuine, they request verification from the engine. A staked validator committee submits attestations, and once quorum is reached, the resource is marked `VERIFIED` in the registry. This page documents the full lifecycle, the three verification levels, quorum rules, attestation mechanics, and fee settlement.

## Why on-chain verification

A signature proves that the issuer controls the signing key. Verification additionally proves that independent validators with economic skin in the game have attested that the resource is genuine. Verified resources are the highest level of trust Notareum offers, and they anchor on-chain so any party can check them with a read-only RPC call.

## The three verification levels

Three levels scale quorum size, approval threshold, and fee with resource sensitivity.

| Level           | Quorum        | Approval Threshold | Fee        |
| --------------- | ------------- | ------------------ | ---------- |
| `BASIC`         | 3 validators  | 67% (6700 bps)     | 100 NOTA   |
| `ENHANCED`      | 7 validators  | 75% (7500 bps)     | 500 NOTA   |
| `INSTITUTIONAL` | 15 validators | 75% (7500 bps)     | 2,000 NOTA |

These are immutable constants in `NotareumVerificationEngine`: `QUORUM_BASIC`, `QUORUM_ENHANCED`, `QUORUM_INSTITUTIONAL`, `THRESHOLD_BASIC`, `THRESHOLD_ENHANCED`, `THRESHOLD_INSTITUTIONAL`, `FEE_BASIC`, `FEE_ENHANCED`, `FEE_INSTITUTIONAL`.

## Verification sequence

```mermaid theme={"system"}
sequenceDiagram
    participant R as Requester
    participant E as VerificationEngine
    participant G as NotaRegistry
    participant V as Validators

    R->>E: requestVerification(resourceId, level)
    E->>E: transfer fee from requester
    E->>G: setVerificationStatus(PENDING)
    E-->>V: VerificationRequested event
    loop Until quorum reached
        V->>E: submitAttestation(resourceId, approved)
        E->>E: increment approvals or rejections
    end
    E->>E: resolve if total >= quorum
    alt Verified
        E->>G: setVerificationStatus(VERIFIED)
        E->>V: distribute fee to approvers
    else Rejected
        E->>G: setVerificationStatus(UNVERIFIED)
        E->>R: refund 50% of fee
        E->>E: forward 50% to FeeManager
    end
    E-->>R: VerificationResolved event
```

## Request submission

The requester calls:

```solidity theme={"system"}
function requestVerification(
    bytes32 resourceId,
    VerificationLevel level
) external returns (uint256 requestId);
```

Effects:

* Transfers `feeForLevel(level)` NOTA from requester to the engine.
* Creates a `VerificationRequest` record with zero tallies.
* Sets registry status to `PENDING`.
* Emits `VerificationRequested(requestId, resourceId, level, requester, fee)`.

Only one active request per resource. Attempting a second while one is active reverts with `AlreadyPendingVerification`.

## Attestation submission

Active validators call:

```solidity theme={"system"}
function submitAttestation(bytes32 resourceId, bool approved) external;
```

Rules:

* Caller MUST be an active validator (`stakedAmount >= 10,000 NOTA`).
* Each validator votes once per request; duplicates revert with `AlreadyVoted`.
* Daily verification count is incremented via `staking.recordVerification(msg.sender)`.
* Approvals and rejections tally independently.

After each attestation, the engine attempts resolution.

## Resolution logic

Resolution triggers when `total = approvals + rejections >= quorumForLevel(level)`. Once quorum is reached:

```
verified = (approvals * 10000) / total >= thresholdForLevel(level)
```

**Verified path:**

* Registry status becomes `VERIFIED`.
* Full fee is distributed equally among approving validators.
* Active request is cleared.

**Rejected path:**

* Registry status reverts to `UNVERIFIED`.
* 50% of fee (`REJECTION_REFUND_BPS = 5000`) is refunded to the requester.
* Remaining 50% is forwarded to the fee manager.
* Active request is cleared.

## Consensus model

Consensus is a binary classifier. Let `C(v_i, n_j) ∈ {0, 1}` where `C = 1` denotes approval by validator `v_i` for resource `n_j`. Consensus:

```
sum(w_i * C(v_i, n_j)) / sum(w_i) >= Q
```

Where `w_i` is stake-weighted influence and `Q ∈ [0.67, 0.75]`. In v1.0, `w_i = 1` for every active validator. Future versions may introduce stake-proportional weighting.

## Byzantine fault tolerance

For `n` validators with independent failure probability `p`:

```
P_fail = p^n
```

At `p = 0.05` and `n = 15`, `P_fail = 3.05e-20`, effectively negligible.

## VerificationRequest struct

```solidity theme={"system"}
struct VerificationRequest {
    bytes32 resourceId;
    VerificationLevel level;
    address requester;
    uint256 feeDeposited;
    uint256 approvals;
    uint256 rejections;
    bool resolved;
}
```

## Querying state

```solidity theme={"system"}
function getAttestations(bytes32 resourceId)
    returns (uint256 requestId, uint256 approvals, uint256 rejections, bool resolved);

function getRequest(uint256 requestId) returns (VerificationRequest memory);
```

## Example code

**Requester (TypeScript):**

```typescript theme={"system"}
const resourceId = ntm.registry.computeResourceId(0, 1n, address);
const level = 1;  // ENHANCED

await ntm.fee.approveNotaForVerification(level);  // approve 500 NOTA
const tx = await ntm.verification.requestVerification(resourceId, level);

const attestations = await ntm.verification.getAttestations(resourceId);
console.log("approvals:", attestations.approvals);
```

**Validator (Python):**

```python theme={"system"}
# Validator submits an approval after reviewing evidence off-chain
ntm.verification.submit_attestation(resource_id=rid, approved=True)
```

## Security considerations

**Sybil attacks.** Validators must stake 10,000 NOTA minimum. For `INSTITUTIONAL` level requiring 15 approvals, an attacker must control at least 150,000 NOTA of committed stake plus absorb slashing losses.

**Collusion.** Colluding validators risk slashing via the dispute mechanism. Higher-tier slash rates (up to 75%) make collusion expensive relative to gains.

**Front-running.** Attestations are visible in the mempool. A malicious actor could submit rejections to prevent verification. The quorum threshold requires controlling multiple validators to succeed.

**Fee griefing.** Daily limits (100 to unlimited per tier) constrain griefing impact. Per-request fees (100 to 2,000 NOTA) make griefing campaigns expensive.

## Related pages

* [Resource Registry](resource-registry.md) for pre-verification registration
* [Staking and Tiers](staking-and-tiers.md) for validator economics
* [Dispute Resolution](dispute-resolution.md) for challenging verified resources
* [Fee Model](fee-model.md) for fee flow
* [VerificationEngine contract](../smart-contracts/verification-engine.md)
