Skip to content

feat(committed): committed-state migration — verifiable calc-state root into the currency snapshot#164

Merged
scasplte2 merged 6 commits into
mainfrom
feat/committed-state-migration
Jun 15, 2026
Merged

feat(committed): committed-state migration — verifiable calc-state root into the currency snapshot#164
scasplte2 merged 6 commits into
mainfrom
feat/committed-state-migration

Conversation

@ottobot-ai

Copy link
Copy Markdown
Collaborator

Draft / WIP. Unifies and supersedes #117 (hand-rolled state roots) and #158 (committed-state adapter) into one workstream. Plan of record: docs/proposals/committed-state-migration.md.

The reframe

Tessellation already roots hashCalculatedState into the signed currency snapshot (DataApplicationPart.calculatedStateProof) and transitively into the global GL0 proof. So the groundwork is just making that hash a verifiable tree root — exactly what metakit CommittedApp.makeL0 produces — with no tessellation change. (Promoting it to a typed Option[MerkleRoot] field on DataApplicationPart is an optional later phase.)

What's here so far

  • Plan of record doc.
  • CommittedView[CalculatedState] — projects all 4 fields (stateMachines/scripts/registry/reverseNames) into lowercase slash-namespaced CommitKeys. Registry keying is total (registry/<name>, with a registry/h/<sha256> fallback for names that overflow a 64-char segment). CommittedViewSuite green.

Depends on

metakit Constellation-Labs/metakit#48 (fix(committed): require CatalogJournal) — the required-journal fix that removes the seed→BreadcrumbUnresolvable stall that parked #158. Held un-tagged for now; ottochain builds it from source until merged.

Still to come (this PR)

🤖 Generated with Claude Code

Plan of record for adopting metakit committed-state (Approach B) as
hashCalculatedState, salvaging #117's field-level proof endpoint on top.
Records the key reframe: tessellation already roots calculatedStateProof
into the signed currency snapshot + global proof, so a structured root
needs no framework change. The prior roadblock was the journal=Option
stall (seeded cell -> BreadcrumbUnresolvable), not the rooting.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ottobot-ai and others added 5 commits June 15, 2026 04:26
First slice of the committed-state migration: project the FULL
calculated state (all 4 fields) into metakit's committed dictionary so
the two-tier committed root commits to it, ready to become the currency
snapshot's calculatedStateProof.

Keys are lowercase slash-namespaced CommitKeys: fiber/<uuid>,
script/<uuid>, registry/<name>, reverse/<uuid>. Key derivation is TOTAL
(entries has no error channel; a non-total key would halt combine):
UUIDs always fit a 64-char segment, and an over-long registry name
(render up to 253) falls back to registry/h/<sha256>.

CommittedViewSuite covers the registry readable/hashed-overflow keys,
namespacing, totality, determinism, and empty genesis.

Refs docs/proposals/committed-state-migration.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ML0Service now assembles the data application via CommittedApp.makeL0, so
the snapshot's calculatedStateProof becomes the two-tier committed root
(MPT state-dict + SMT epoch catalog) — a verifiable calculated-state root
in the signed currency snapshot, no tessellation change required.

- ML0Service: makeL0 with orderedCombiner (total-order sort + latestLogs
  reset before folding) and rejectionNotifyingValidator (per-update
  rejection webhooks); the new onConsensusResult hook refreshes the
  notification-side checkpoint cache + dispatches the snapshot webhook
  (replaces the hand-rolled onSnapshotConsensusResult); extraRoutes keeps
  the existing ML0Routes handlers.
- Main: acquire a LevelDB CatalogJournal Resource (required — without it a
  seeded/restarted node stalls).
- DL1: makeL0 commits CommittedOnChain[OnChain]; the validator's on-chain
  cache and the /onchain route decode the wrapper and read .inner, so the
  fiber sequence checks and the client-facing shape are unchanged.
- Mock fixture serializes the same CommittedOnChain shape.

Depends on metakit Constellation-Labs/metakit#48 (required journal +
onConsensusResult + extraRoutes context). sharedData 358/358 green; full
build compiles. e2e validation pending.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adopt #158's total signing order: OttochainMessage.signedOrdering now
tiebreaks on the proof signatures, completing the partial message order
to a TOTAL one (pure — no Hasher). The combiner drops the per-combiner
content-digest tiebreak and just sorts by signedOrdering, so every node
folds the identical sequence (greenfield — no coordination needed).

Bump the metakit pin to 1.8.0-rc.3 (committed-state changes: required
journal + onConsensusResult/extraRoutes hooks + genesis-combine fix).
Until rc.3 lands on Central the metakit-from-source action builds the
v1.8.0-rc.3 tag; the tessellation rc.10 jar fallback is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-homes #117's field-level state proof onto the real committed root.
GET /v1/state-machines/:id/state-proof[?field=] and
GET /v1/scripts/:id/state-proof[?field=] return a Merkle-Patricia
inclusion proof for the fiber/script record (committed at fiber/<id> /
script/<id>) against the MPT root whose combined hash IS the snapshot's
calculatedStateProof. A client verifies the proof against the
consensus-signed root, then reads any field off the proven record —
#117's two-level field->fiberRoot->metagraphRoot collapses to one level,
anchored to a real consensus root instead of an off-chain one. ?field=
also surfaces the named stateData field of the proven record.

StateProofHandler delegates to CommittedReader.committed.proveKey (no
hand-rolled tries); wired via makeL0 extraRoutes (now passed the reader).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
metakit 1.8.0-rc.4 is published to Maven Central with all the
committed-state changes (required journal, onConsensusResult / extraRoutes
hooks, and the genesis-combine fix) — verified in the published jar. So
the temporary metakit-from-source action is no longer needed: removed it
and its callers (ci.yml x2, e2e.yml), and e2e.yml now resolves the
tessellation-sdk version straight from the Central metakit POM again. The
tessellation rc.10 hypergraph-jar fallback is untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ottobot-ai ottobot-ai marked this pull request as ready for review June 15, 2026 09:26
@ottobot-ai ottobot-ai force-pushed the feat/committed-state-migration branch from 3c15649 to 8f2fe6b Compare June 15, 2026 09:26
@scasplte2 scasplte2 merged commit 4f80285 into main Jun 15, 2026
5 checks passed
@scasplte2 scasplte2 deleted the feat/committed-state-migration branch June 15, 2026 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants