A ledger rebuilding itself from a seed beside a great hourglass ← All research
Architecture Negative result

The present that doesn't prove itself

We reached for recursive proofs to kill a sixteen-minute miner warmup. An adversarial review took the idea apart. The lesson is a clean line between a cache and a proof — and knowing which problem you actually have.

12 min TSN core Open · fix in progress

A TSN miner that restarts is not immediately useful. For roughly sixteen minutes it accepts, gossips, and validates — but it cannot yet produce a block. From the outside it looks like a hang. It is not. It is a node rebuilding, from genesis, state it had a minute ago.

Where the sixteen minutes go

TSN keeps two derived structures in memory that a producer needs before it can assemble a block. Neither is written to disk; both are reconstructed from the chain at boot.

The dominant one is the nullifier index — the anti-double-spend set that answers "has this note already been spent?". At startup it begins empty, with no watermark, and no load path. So the catch-up sees a gap from height 0 to the tip and replays the entire chain: on the order of twenty-four thousand scattered reads into a multi-gigabyte body store, with all the random-access amplification that implies. That is where most of the sixteen minutes live.

The second is the note-accumulator, the commitment tree the miner folds to compute a block's commitment_root. Its first post-restart mining round walks genesis-to-parent — tens of seconds, not minutes — and then stays warm, one read per round. It is the minor cost, and it is already persisted since an earlier release. So the residual problem is the nullifier index, and only the nullifier index.

The measurable claim

Boot with an empty index and the catch-up applies every height between genesis and the tip. Boot from a persisted watermark and it applies one — the delta since the last checkpoint. The resulting set is identical either way. Persistence changes only the cost, never the verdict. That is the whole fix, and it is boring on purpose.

The tempting wrong idea

There is a beautiful idea in the air right now — a neighbouring chain builds its whole thesis on it: the present proves itself. Each block carries a recursive proof that the current state descends validly from genesis, so a joining node authenticates the tip without replaying history, and the proof never grows with height. It is real, established science (Mina has shipped incrementally-verifiable computation since 2020).

So the reach is obvious: if the present proves itself, a restarting miner just checks a proof instead of rebuilding for sixteen minutes. We wrote that down. Then we handed it to an adversarial reviewer whose only job was to break it.

The correction

A recursive proof does not speed up a restart. You don't prove your own disk to yourself. A restarting node already holds the whole chain locally and already trusts it — the sixteen minutes are pure re-derivation cost, not a trust problem. The fix is to persist the derived state and reload it. A proof buys you nothing a fsync doesn't buy cheaper.

Cache versus proof

The correction survives because two things that share a word are not the same thing.

A trust cache is a local artifact: you serialize state you already computed and trust, and reload it to skip the recompute. It is fast, it is private, and it convinces no one but you. That is exactly right for a restart.

A proof-carried checkpoint is a public artifact: a third party who trusts nothing can verify that your claimed state is the valid descendant of genesis. That is what solves a fresh join — a new node, or a light client, that will not replay the chain and should not have to trust you. The two may even share a snapshot format. They do not share a guarantee.

RESTART — a trust problem you don't have your node already has the chain local cache load + apply Δ → seconds ✓ FRESH JOIN — a trust problem you do have new node trusts nothing proof-carried verify vs genesis → verifiable ✓ same snapshot format, different guarantee.
Fig 1. The mistake was using one word — "persist the state" — for both columns. Only the right column needs a proof.

Where TSN is actually well placed

Killing the warmup is a cache fix with zero consensus surface — the nullifier index is a runtime guard and never enters the genesis hash or chain id. But the review surfaced something with a real deadline: TSN already commits state roots in its block headers. Its commitment_root has been the true note-tree root since v4. That is most of the scaffolding a future proof-carried fast-join would stand on.

Two gaps stand between "we commit roots" and "a newcomer can trust them":

  • the nullifier_root in the header is a rolling hash — it cannot be checked without replaying the chain, which defeats the point of committing it;
  • on every receive path, check_commitment_root is off — only the block's own producer verifies it. A root nobody on the receiving side checks is decoration.

Both are cheap to close, and both are only cleanly closeable before mainnet genesis, because a header-semantics change after launch is a hard fork. That, not the warmup, is the item with a clock on it.

The cheaper 80%

Even the fast-join doesn't need recursion first. A root-verified snapshot sync — the shape Ethereum shipped in 2015 — lets a new node accept a snapshot whose root it checks against the header chain, capturing most of the value with none of the proof machinery. Recursion is the last mile, and it should arrive audited, not first.

Crediting the idea honestly

The chain that inspired this — parano1d — deserves precision, not a swipe and not a hug. Its "O(1)" is a headline: their own docs put header validation as linear in height and state transfer as linear in live state; only proof verification is constant. The 127-bit soundness figure is theirs and is argued in the classical model. Their NIST Category-1 claim, though, rests on two assumed premises with a margin of about 3.27 bits, on an idealised protocol whose circuit correctness is explicitly outside the theorem — and it ships from a four-day-old mainnet, single pseudonymous author, no external audit. The concept is sound and implemented. The instantiation is credible and unproven. Borrow the principle; don't borrow the certainty.

What we're actually doing

Persist the nullifier index to a crash-safe store in the data directory, alongside its watermark and the height-to-hash map a rewind needs; reload at boot; apply the delta. Restart drops from sixteen minutes to seconds, with no change visible on-chain. Separately, before genesis, make nullifier_root a real set root and turn on root checking at admission. The recursive-proof fast-join stays on the roadmap, behind an audit, as the thing that finally lets a stranger trust our present without replaying our past.

Filed under architecture · a negative result kept on purpose. The fix that survived review is the unglamorous one.