Skip to content

feat(committed): committed-state adoption enablers (required journal + L0 hooks)#48

Merged
scasplte2 merged 3 commits into
Constellation-Labs:devfrom
ottobot-ai:fix/committed-required-journal
Jun 15, 2026
Merged

feat(committed): committed-state adoption enablers (required journal + L0 hooks)#48
scasplte2 merged 3 commits into
Constellation-Labs:devfrom
ottobot-ai:fix/committed-required-journal

Conversation

@ottobot-ai

@ottobot-ai ottobot-ai commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Three small, related changes that make the committed lifecycle module actually adoptable by a downstream metagraph L0 (ottochain). All scoped to lifecycle/committed; full suite green (1111/1111).

1. Require the catalog journal (the load-bearing fix)

CommittedApp.makeL0 / CommittedState.make took journal: Option[CatalogJournal[F]] = None. The journal is load-bearing: a node that seeds (restart or download-to-join) with no journal lands in a SeededCatalog, and the next combine raises BreadcrumbUnresolvable → the metagraph stalls. Now a required CatalogJournal[F], with inMemory/levelDb the explicit opt-outs. Also documents that breadcrumb resolution is by roots, not the claimed ordinal (the catalog root commits the full ordinal history).

2. onConsensusResult hook on makeL0

makeL0 returns an erased BaseDataApplicationL0Service, so a metagraph needing onSnapshotConsensusResult (webhook dispatch, a notification-side state cache) otherwise had to wrap it in a ~20-method delegating service. Added an optional onConsensusResult: (CommittedReader, Hashed[CurrencyIncrementalSnapshot]) => F[Unit] the service forwards, handing the dev the committed reader for current-state reads.

3. Pass L0NodeContext to extraRoutes

The extra-routes callback received only the CommittedReader; pass the L0NodeContext alongside so extra routes can read node-context state (e.g. the on-chain snapshot). Default extraRoutes (None) unaffected.

Downstream consumer: ottochain committed-state migration (scasplte2/ottochain#164).

🤖 Generated with Claude Code

CommittedApp.makeL0 / CommittedState.make took journal:
Option[CatalogJournal[F]] = None. The journal is load-bearing: a node
that seeds (restart or download-to-join) with no journal lands in a
SeededCatalog and the next combine raises BreadcrumbUnresolvable, so the
metagraph stalls. Make journal a required CatalogJournal[F] (reordered
before the defaulted params) with inMemory/levelDb as the explicit
opt-outs, and drop the now-dead Option plumbing
(flatTraverse/traverse_). This was the roadblock that parked the
ottochain committed-state adapter.

Also document that breadcrumb resolution is by ROOTS, not the claimed
ordinal (the catalog root commits the full ordinal history); honest
callers always pass a consensus-signed, ordinal-bound breadcrumb. Test
updated to assert unresolvability with roots the chain never produced.

Full suite green: 1111/1111.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
scasplte2 and others added 2 commits June 15, 2026 00:38
makeL0 produces an erased BaseDataApplicationL0Service, so a metagraph
that needs onSnapshotConsensusResult (e.g. webhook dispatch + a
notification-side calculated-state cache) previously had to wrap it in a
~20-method delegating service. Add an optional onConsensusResult hook —
(CommittedReader, Hashed[CurrencyIncrementalSnapshot]) => F[Unit] — that
the service forwards from onSnapshotConsensusResult, handing the dev the
committed reader for current-state reads. Kills the wrapper.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The extra-routes callback previously received only the CommittedReader,
so a metagraph whose extra routes read node-context state (e.g. the
on-chain snapshot via getOnChainState) could not be wired through it.
Pass the L0NodeContext alongside the reader. Default extraRoutes (None)
is unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ottobot-ai added a commit to scasplte2/ottochain that referenced this pull request Jun 15, 2026
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>
@ottobot-ai ottobot-ai changed the title fix(committed): require CatalogJournal (no silent journal=None) feat(committed): committed-state adoption enablers (required journal + L0 hooks) Jun 15, 2026
@scasplte2 scasplte2 merged commit c754201 into Constellation-Labs:dev Jun 15, 2026
1 check passed
@scasplte2 scasplte2 deleted the fix/committed-required-journal branch June 15, 2026 06:55
ottobot-ai added a commit to scasplte2/ottochain that referenced this pull request Jun 15, 2026
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>
scasplte2 pushed a commit to scasplte2/ottochain that referenced this pull request Jun 15, 2026
…ot into the currency snapshot (#164)

* docs: committed-state migration plan (unify #117/#158)

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>

* feat(committed): add CommittedView[CalculatedState] projection (Phase 1)

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>

* feat(committed): wire makeL0 into ML0Service (Phase 1)

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>

* feat(committed): total signedOrdering + bump metakit rc.3

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>

* feat(committed): state-proof endpoint on the committed MPT (Phase 2)

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>

* chore(deps): bump metakit to rc.4; drop source-build patch

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>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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