> ## 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 Architecture

> How commitments, Merkle roots, and compliance proofs are anchored on-chain so anyone can verify without trusting the sequencer.

# Set L2 Architecture

Set L2 anchors batch commitments and proof metadata on-chain, so a client can verify event
inclusion and policy compliance **without trusting the sequencer**. The chain becomes the source
of truth rather than the operator.

## The flow

```
 AI Agent ──▶ stateset-sequencer ──▶ stateset-stark ──▶ Set Chain
                    │                  (STARK prover)      (SetRegistry)
              orders events                  │                   │
              computes Merkle roots          │                   │
                    │                        ▼                   ▼
                    └──────────▶ compliance proofs      batch commitment
                                                        + proof hashes
                                                              │
                              Verifier ◀─────────────────────┘
                              recomputes locally, compares
```

1. The **sequencer** orders events and computes Merkle roots over payload hashes.
2. The **prover** generates zero-knowledge compliance proofs over encrypted payloads.
3. **SetRegistry** on-chain stores the batch commitment and proof hashes.
4. A **verifier** recomputes the root locally and compares it against the on-chain commitment.

Because step 4 needs only the commitment and a proof, verification requires no cooperation from
the sequencer.

## Batch commitments

Each batch anchors a state transition, not just a set of events:

```rust theme={null}
pub struct BatchCommitment {
    pub batch_id: Uuid,
    pub tenant_id: TenantId,
    pub store_id: StoreId,
    pub prev_state_root: Hash256,    // chains to the previous batch
    pub new_state_root: Hash256,
    pub events_root: Hash256,        // Merkle root of event leaves
    pub event_count: u32,
    pub sequence_range: (u64, u64),   // inclusive
    pub committed_at: DateTime<Utc>,
    pub chain_tx_hash: Option<Hash256>,
}
```

<Note>
  `prev_state_root` chaining is what makes gaps and forks detectable. **Strict mode verification**
  checks continuity across the chain of commitments, so a missing or rewritten batch fails
  verification rather than passing silently.
</Note>

Merkle trees are SHA-256 with **domain separation** at every level — `VES_LEAF_V1` for leaves,
`VES_NODE_V1` for internal nodes, and a `VES_PAD_LEAF_V1` constant padding the tree to a power of
two. A leaf commits to the stream identity and sequence number as well as the event, so a leaf
cannot be replayed into a different position. The engine can produce an inclusion proof for any
individual event.

## Compliance proofs

When payloads are encrypted — an order amount, say — a policy still needs checking without
revealing the data. That's what the STARK prover produces:

| Field                | Purpose                                                |
| -------------------- | ------------------------------------------------------ |
| `proof_type`         | e.g. `stark.compliance.v1`                             |
| `policy_id`          | e.g. `aml.threshold`                                   |
| `policy_params`      | e.g. `{"threshold": 10000}`                            |
| `policy_hash`        | SHA-256 of the policy — pins *which* policy was proven |
| `proof_hash`         | SHA-256 of the proof bytes                             |
| `proof_bytes`        | The full STARK proof                                   |
| `public_inputs`      | Canonical JCS format                                   |
| `witness_commitment` | Rescue hash of the private witness                     |

<Tip>
  `policy_hash` is the field that matters for audit. It proves the compliance check ran against a
  specific policy version, so a later policy change can't be passed off as having applied
  retroactively.
</Tip>

## Chain configuration

| Parameter     | Value                       |
| ------------- | --------------------------- |
| Chain ID      | `84532001`                  |
| Block time    | 2 seconds                   |
| Gas limit     | 30M per block               |
| L1 settlement | Ethereum Sepolia (11155111) |
| Native token  | ETH                         |
| EVM version   | Cancun                      |
| OP Contracts  | v1.8.0                      |

Multi-tenant isolation is per tenant and store, keyed by `keccak256(tenantId, storeId)`.
Merchants can sponsor user transactions through **SetPaymaster**.

## Why anchor at all

| Need                   | What anchoring gives you                                               |
| ---------------------- | ---------------------------------------------------------------------- |
| **Audit trails**       | Tamper-evident history — a rewritten event fails root recomputation    |
| **Compliance**         | A policy boundary provable to a third party, without exposing the data |
| **Trust minimisation** | Counterparties verify independently rather than trusting the operator  |

This is the same principle as [verified decisions](/stateset-nsr-decisions) and
[ICP receipts](/stateset-icp#receipts): the party relying on a claim can check it themselves.

## Related

* [Set L2 Overview](/set/set)
* [Set L2 Verification](/set/stateset-set-l2-verification) — how to actually verify
* [Sequencer Architecture](/stateset-sequencer-architecture)
