Commit-First, Repair-If-Needed
SYNC BLOCK BUILT · ATTEMPT REGISTERED · SYNC_HEIGHT 8,241
composer builds the attested Sync block
→
optimistic.begin(…)
→
optimistic.rs:199 · returns AttemptId
OptimisticallyIncluded
Mutex<AttemptState> — one ledger per cross-chain rollup
gen 40 · 8,235
→
2 users
Terminal
reconciled · kept until finality
gen 41 · 8,241
→
3 users
AwaitingEvidence
← just registered
begin() refuses while another attempt still owns unresolved users (optimistic.rs:227) — one unresolved attempt at a time.
The ledger holds attempts; the state machine is per user — UserLocation: Queued, Composing, AwaitingEvidence, Terminal (optimistic.rs:86). The block is committed to L2 right after (composer.rs:5354).
PROTOCOL RESEARCHERS
How L1 stays the source of truth
An L2 commits first: the attested Sync block is committed, and begin() registers its attempt in a ledger — every user AwaitingEvidence — before L1 has confirmed anything.
Only canonical derivation from L1 resolves those users, or repairs the block — and until finality a reorg can still reopen them.
WHAT YOU'LL LEARN
- 01 · THE LEDGERbegin() registers one attempt per Sync block; its users wait as AwaitingEvidence. One unresolved attempt at a time, one ledger per cross-chain rollup.
- 02 · OBSERVATION ≠ EVIDENCEThe observer only records what happened to the submission. resolve() moves users on canonical source outcomes — Terminal, or back to the queue.
- 03 · TERMINAL IS NOT PERMANENTAn L1 reorg reopens canonical outcomes above the common ancestor. Attempts leave clean only at finality, after their L1 block is re-checked.
Verified against eez-rollupX Git commit 2c19e36; interfaces may move.