# Settle On-Chain

> From a base proof of hundreds of shards to one Groth16 proof that an Ethereum contract checks. The recursion tree, the decider's ceremony, the contract's interface, and what one deployment fixes.

A base proof is a block of shard proofs, each a GKR proof with its commitments: megabytes of data and hundreds of curve points, which no contract can check. Settlement compresses it in three stages, each run with `bench` from the repository root.

> Figure: Settlement. Each stage verifies the one before it. Nothing pairs before the contract: every Mercury check is deferred and folded into one accumulator that the contract discharges with two pairings. Figures are block 257,510's.

## 1. The recursion tree

A **node** is Apogee proving a verifier program. A **leaf** verifies a run of consecutive base shards; an internal node verifies two to four child proofs; the **root** covers every base shard. Each node also folds every Mercury check its shards and children defer into one pair of points, so the whole tree comes down to a single pairing claim at the top.

```sh
# the base proof as an archive: host::proof_archive::write_proof from your host
# program, or `bench prove ... --out <dir>` for the Ethereum guests
cargo run --release -p bench -- recurse <dir>/<stem> --out <out> --in-flight 4
```

`recurse` writes the two recursion programs' keys, builds the leaf and node binaries over them, fixes a plan before anything is proved (`<out>/tree.txt`: leaves of at most `--leaf` 64 base shards, then nodes of at most `--fan-in` 4 children), and proves node by node. Each node is its own process, which verifies its inputs natively before proving, so a bad input is refused by name. A stopped run resumes: proofs already in `<out>` are kept, and a run whose plan or programs differ is refused.

Base proving is untouched by any of this. A leaf verifies base shards exactly as they are.

## 2. The decider

The root is still a GKR proof and some hundreds of points. The **decider** is a Groth16 circuit that verifies the root as a node would, and folds nothing. Instead it binds, as wires whose values the contract supplies, the two recursion programs' identities, the base statement's exit status, its public input and journal byte by byte, and each point the root owes a pairing to, with its scalar. The Groth16 proof carries one commitment to all of those wires, and the contract checks it against the values it holds.

A Groth16 key needs a ceremony. Phase 1 is the same powers-of-tau file the tree's commitments are under. Phase 2 is the circuit's own and runs in two rounds of contributions:

```sh
cargo run --release -p bench -- ceremony <out> init          # once per root shape
cargo run --release -p bench -- ceremony <out> contribute    # round 1: alpha and beta, each contributor in turn
cargo run --release -p bench -- ceremony <out> seal
cargo run --release -p bench -- ceremony <out> contribute    # round 2: gamma, delta and eta
cargo run --release -p bench -- ceremony <out> key
cargo run --release -p bench -- decide <out>                 # the Groth16 proof, checked natively and in an EVM
```

Each contribution multiplies a trapdoor by a factor only its contributor knew, and records it with a Schnorr proof, so any state can be verified against the circuit and the ceremony file alone. A trapdoor is unknown while one contributor to it was honest. **The order of the rounds is part of soundness**: `alpha` and `beta` are finished before anything is divided by `delta` or `eta`.

> [!CAUTION]
> `bench decide --dev-key` derives every trapdoor from a public seed, for development and tests. Anyone can forge a proof under it, and its outputs are written as `development.*` so they cannot be mistaken for a ceremony's. A ceremony run on one machine is not a ceremony either: it needs one honest contributor per round.

`decide` writes `decision.constructor` and `decision.calldata`: the deployment arguments and the call, as hex.

## 3. The contract

`contracts/ApogeeVerifier.sol` has one entry point:

```solidity
function verify(
    bytes calldata input,        // the base program's public input
    bytes calldata output,       // its journal
    uint256 exitStatus,          // the status you require, normally 0
    uint256[10] calldata proof,  // Groth16 A, B, C and the bound wires' commitment D
    uint256[] calldata points    // x, y and scalar of each point, side [1]_2's then side [x]_2's
) external view returns (bool);
```

It rebuilds the bound values from the calldata, checks the Groth16 pairing equation, folds each side's points with `ecMul` and `ecAdd`, which also holds every point to the curve, and checks the folded claim `e(A, [1]_2) = e(B, [x]_2)`. An application contract calls it and then acts on the journal: see the [ledger sketch](https://apogee.gweb3networks.com/docs/blockchain-native#ledger-native).

## What one deployment fixes

The constructor takes the Groth16 key, the ceremony's two G2 points, the leaf and node programs' identities, the number of points on each side, and **the byte lengths of the public input and the journal**. So one deployed verifier serves:

- **One base program.** Its identity is a constant of the leaf program's image, which the leaf's identity binds.
- **One root shape.** The decider's circuit depends on the root's program, its shard counts and the public values' lengths, so a key and its ceremony are per shape.
- **Fixed-length public values.** `verify` refuses an input or journal of any other length. Design guests whose on-chain public values have a fixed size, such as a fixed record or a 32-byte digest.

The contract pays about 9,000 gas a point, because the circuit folds none of them.

## Measured

Block 257,510, with the tree on a 32-CPU, 247 GiB machine and the ceremony and decider on an 18-core laptop:

| Stage | Result |
| --- | --- |
| Base proof | 207 shards, 14.5 MB, 2,481 s |
| Tree | 4 leaves of at most 64 base shards and a root: 116 shards |
| Leaves, four at once | 21, 24, 23 and 27 shards; 2,157 s; 92 GiB peak |
| Root, four shards in flight | 21 shards, 460 s, 1.03 MB |
| Decider circuit | 7,896,686 constraints, a domain of `2^23` |
| Ceremony | `init` 65 s; a contribution 50–56 s; `key` 70 s and 12.7 GB; the key 2.65 GB |
| Decider proof | key read in 1 s, proof 18.5 s, 6.1 GB |
| Contract | 358 points; 3,620,026 gas; 34,980 bytes of calldata |

The specification of all of it is [Recursion and decider](https://apogee.gweb3networks.com/docs/auditors/spec/recursion).
