# Tempo Zone proving and settlement

Tempo Zone settlement records commitments to private Zone execution on Tempo and queues accepted withdrawals for processing. The stateless proof function (SPF) replays batches against witnessed Zone and Tempo state to validate their execution.

## Implementation status

This page follows Zones source at [`ac49071f`](https://github.com/tempoxyz/zones/tree/ac49071f) and Tempo source at [`3c4db7f843`](https://github.com/tempoxyz/tempo/tree/3c4db7f843), reviewed September 23, 2026. Source support does not establish which runtime a deployed Zone uses.

The Zones Solidity reference verifier still returns `true` without checking execution. Tempo also implements a native Nitro attestation verifier activated by T13. At the reviewed commit, its approved enclave measurements are unset, so it rejects proofs. Check the network's active hardfork, verifier implementation, and approved measurements before relying on execution-proof enforcement.

The current sequencer can wait for a Nitro-attested batch before submitting it. This node-side requirement is separate from onchain enforcement. Forced exits remain unfinished.

## Batch submission

The sequencer calls `ZonePortal.submitBatch` on Tempo. Each batch covers one or more zone blocks and includes:

| Field | Description |
|-------|-------------|
| `tempoBlockNumber` | Tempo checkpoint committed by the zone |
| `recentTempoBlockNumber` | Recent anchor for ancestry mode (`0` for direct lookup) |
| `blockTransition` | Zone block hash transition (`prevBlockHash` → `nextBlockHash`) |
| `depositQueueTransition` | Previous and next deposit hashes and deposit numbers |
| `tokenEnablementTransition` | Previous and next processed enabled-token counts (T13) |
| `withdrawalQueueHash` | Hash chain of withdrawals for this batch (`0` if none) |
| `verifierConfig` | `0x01` for the Nitro verifier policy |
| `proof` | Nitro attestation when a settlement prover is configured; empty on the unconfigured compatibility path |
| `zoneHeight` | Height of the submitted zone tip |
| `signatures` | Distinct sequencer signatures forming the settlement certificate |

The portal checks continuity with its stored `blockHash`, an increasing zone height, deposit progress, processed token-enablement progress under T13, and the active sequencer quorum. The EIP-712 certificate binds the zone ID, sequencer-set version, batch index, verifier, Tempo anchor, state transitions, withdrawal hash, and verifier configuration. Replacing the sequencer set invalidates certificates from the old configuration.

The portal then calls the configured verifier. On acceptance it updates the zone tip, processed deposit and enabled-token counts, Tempo checkpoint, and withdrawal batch index, and enqueues any withdrawals. A signature quorum authenticates the submitted commitments; it does not independently prove correct execution.

The sequencer prepares a signed batch and waits for Nitro attestation when configured. The portal checks quorum and continuity, then calls the active verifier. The Solidity reference is a stub; the T13 native verifier checks attestations and requires approved enclave measurements.

## Verifier interface

The T13 portal calls its configured verifier through this interface. Earlier runtimes use older interfaces; use the ABI for your network:

```solidity
interface IVerifier {
    function verify(
        uint32 zoneId,
        uint64 tempoBlockNumber,
        uint64 anchorBlockNumber,
        bytes32 anchorBlockHash,
        uint64 expectedWithdrawalBatchIndex,
        uint256 nextZoneHeight,
        BlockTransition calldata blockTransition,
        DepositQueueTransition calldata depositQueueTransition,
        TokenEnablementTransition calldata tokenEnablementTransition,
        bytes32 withdrawalQueueHash,
        bytes calldata verifierConfig,
        bytes calldata proof
    ) external view returns (bool);
}
```

The native T13 verifier binds the attested result to the parent chain, canonical portal, Zone ID, verifier, and batch inputs. It checks the Nitro certificate chain, document signature, enclave measurements, and batch digest. The Solidity reference verifier does not perform these checks.

## State transition function

The SPF is implemented as a Rust verifier. It accepts trusted network configuration separately from the batch witness:

```rust
pub fn prove_zone_batch(
    config: &SpfConfig,
    witness: BatchWitness,
) -> Result<BatchOutput, Error>
```

### Execution flow

The stateless validator takes trusted configuration and a batch witness, checks and replays state, recomputes roots and queue commitments, validates the Tempo anchor, and returns BatchOutput or an error.

1. **Bind the starting state.** Validate the zone chain ID and portal against trusted configuration. Use the parent header’s state root for zone reads and verify that the initial Tempo witness matches the checkpoint stored in zone state.
2. **Replay blocks.** Check parent hashes, block numbers, and timestamps. Execute the supplied system and user transactions through the zone EVM, including deposit processing and withdrawal finalization when present.
3. **Recompute commitments.** Rebuild state roots and canonical Tempo-format zone headers, then read deposit progress, enabled-token progress, and withdrawal batch commitments from the resulting state.
4. **Validate the anchor.** Match the final Tempo checkpoint to the public inputs, directly or through the supplied ancestry headers.

The SPF can replay an open zone tip without withdrawal finalization. Settlement policy imposes its batch boundaries separately.

<span id="deployment-modes" />

### Validation deployment modes

On a sequencer, `--sequencer.enable-prover` requires `--sequencer.prover-address HOST:PORT`. The sequencer waits for the remote prover’s successful batch result and nonempty Nitro attestation before submission, while collecting the settlement certificate in parallel.

On an `rpc_only` follower, the same flag enables observational validation. Without a remote address, this runs in-process. A follower’s observational results do not control settlement. The unconfigured sequencer compatibility path submits empty proof bytes and cannot satisfy an enforcing verifier.

The remote service runs inside AWS Nitro Enclaves over AF\_VSOCK. After replay, it places the canonical batch digest in a Nitro attestation document’s `user_data` and returns `BatchOutput` with a proof bundle: `verifierConfig = 0x01` and the raw COSE/CBOR document as `proof`.

TCP mode supports local transport testing, but successful replay still requires the Nitro Secure Module. Outside an enclave, the service returns `attestation_unavailable` rather than an unattested success. ZK proof generation is not implemented.

## Ancestry proofs

Tempo’s EIP-2935 history exposes an 8,191-block lookup window. If a zone’s checkpoint is older, the submitter chooses a recent Tempo anchor and collects the intervening headers. The SPF validates their consecutive block numbers and parent hashes against that anchor.

| Mode | Condition | Behavior |
|------|-----------|----------|
| Direct | `recentTempoBlockNumber = 0` | Portal reads the `tempoBlockNumber` hash from EIP-2935 |
| Ancestry | `recentTempoBlockNumber > tempoBlockNumber` | Portal reads the recent hash; SPF checks the intervening header chain |

Both modes can carry the Nitro attestation. The SPF validates ancestry during replay; an enforcing verifier must authenticate the resulting attestation and bind it to the submitted anchor. The Solidity stub does not enforce that check.

## Tempo state access

The zone accesses its finalized Tempo checkpoint through the `TempoState` precompile (`0x1c00...0000`). During execution:

1. `ZoneInbox` calls `TempoState.finalizeTempo(headers)` when advancing the checkpoint.
2. Zone system execution reads Tempo state at that exact checkpoint.
3. SPF replay requires witnessed account and storage proofs for those reads.

The zone imports finalized Tempo headers in order. Policy updates become visible after the corresponding checkpoint is imported, rather than as unrestricted reads of the latest Tempo state.
