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

# Set L2 Verification

> Verify event inclusion and policy compliance yourself — the sequencer's cooperation is not required.

# Set L2 Verification

Verification is the point of anchoring. A third party can confirm that an event happened and that
a policy held, using on-chain commitments and proof metadata — **without trusting the sequencer
and without its cooperation.**

## Verify event inclusion

You need three things: the on-chain commitment, a Merkle proof, and the event payload.

**1. Retrieve the batch commitment from Set L2.** Read `SetRegistry` for the batch covering your
event's sequence number. You get the `events_root`, the state roots, and the `sequence_range`.

**2. Obtain the Merkle proof.** From the sequencer's gRPC v2 service:

| RPC                 | Returns                                  |
| ------------------- | ---------------------------------------- |
| `GetInclusionProof` | The Merkle inclusion proof for one event |
| `GetCommitment`     | The batch commitment                     |

**3. Recompute and compare.** Hash the event payload, walk the proof path to a root, and compare
that root against the `events_root` you read on-chain.

```
SHA-256(payload) ──▶ walk proof path ──▶ computed root
                                              │
                        on-chain events_root ─┴─▶ equal? included.
```

<Warning>
  Compare against the root **read from the chain**, not one returned by the API. Recomputing a root
  and comparing it to a root from the same source proves nothing — the on-chain value is what makes
  this trust-minimised.
</Warning>

## Verify state continuity

Inclusion alone doesn't prove nothing was *removed*. Each commitment carries `prev_state_root`,
chaining it to its predecessor.

**Strict mode verification** walks that chain and checks continuity, so a gap or a fork is
detected rather than passing silently. Run it when you care that the history is complete, not
just that a specific event is in it.

## Verify policy compliance

Compliance proofs are anchored alongside batch commitments, so you can confirm a rule held over
data you were never shown.

**1. Retrieve the proof metadata** from Set L2 — `policy_id`, `policy_hash`, `proof_hash`,
`public_inputs`.

**2. Validate the hashes.** Check `policy_hash` matches the policy you expect, and `proof_hash`
matches the proof bytes you were given.

**3. Verify the proof** with the STARK verifier against the `public_inputs` in canonical JCS
form.

| Field                | What it pins                                 |
| -------------------- | -------------------------------------------- |
| `policy_id`          | Which rule, e.g. `aml.threshold`             |
| `policy_params`      | Its parameters, e.g. `{"threshold": 10000}`  |
| `policy_hash`        | The exact policy **version** that was proven |
| `witness_commitment` | Rescue hash of the private witness           |

<Note>
  Step 2 is the one people skip. A valid proof of the *wrong policy* tells you nothing — check
  `policy_hash` against the policy you actually care about before trusting the verdict.
</Note>

## What each check buys you

| Check                    | Establishes                                          |
| ------------------------ | ---------------------------------------------------- |
| Inclusion                | This event is in the anchored history                |
| Continuity (strict mode) | Nothing was removed or forked around it              |
| Compliance proof         | A policy held, without revealing the underlying data |

All three together mean you don't have to take the operator's word for anything.

## When to verify

* **External auditors** validating an event trail end to end.
* **Partners** confirming a policy boundary — an AML threshold, a spend cap — without receiving
  the sensitive values.
* **Agents coordinating across systems** with no shared trust, where each side needs to check the
  other's claims independently.

## Related

* [Set L2 Architecture](/set/stateset-set-l2-architecture) — the commitment and proof structures
* [Verification example](/set/stateset-set-l2-verification-example)
* [Compliance proof](/set/stateset-set-l2-compliance-proof)
* [Sequencer Architecture](/stateset-sequencer-architecture) — the gRPC surface
