Makechain module and process architecture

Draft protocolSource at 169cbd2 ↗Source SHA-256 7da2719…bc6
Field Current value
Status P2 architecture definition; bounded FB-01–FB-12 primitive implementation exists; complete protocol and qualification remain NOT RUN
Updated 2026-09-22
Baseline Specification revision 15, 2026-09-25 (working tree); Commonware v2026.9.0; exoware 2026.9.0
Authority Informative architecture artifact; the specification and companions remain authoritative

This document defines responsibility, dependency direction, and process assembly before repository or crate layout. It preserves protocol-first development, the separate consuming application, and trusted permissioned operators. It introduces no generic blockchain framework, database framework, custom consensus, production hardware profile, or application/product scaffold.

Status labels used below: fixed by the current specification or an accepted owner decision; proposed for review; deferred with a named gate; open pending a decision or evidence.

1. Design rules

  1. Fixed: canonical protocol meaning is independent of processes, cloud services, and storage products. One Rust implementation produces native and wasm verification behavior.
  2. Fixed: one deterministic executor owns command semantics for proposal, verification, and application. Admission may call it for an advisory dry-run but never becomes validity authority.
  3. Fixed: Commonware owns Simplex, marshal, stateful orchestration, DKG progression, database-set barriers, pruning, and sync mechanics. Makechain supplies the exact application, membership, release, schema, mesh-set, and storage-adapter contracts those primitives require.
  4. Fixed: three authenticated database members have distinct proof and retention semantics. They are not hidden behind an all-purpose key/value repository or transaction abstraction.
  5. Fixed: finalized events, query tables, and status are derived views. Object availability is a separate external fact; it cannot be reconstructed from a chain commitment. Proof verification starts from caller trust material and authenticated headers, never a service claim.
  6. Accepted development direction: the first disposable devnet uses a fixed committee and one epoch, then resets to real DKG/reshare qualification. Its minimal process co-location is fixed in §5; production placement remains deferred. Correctness within the enabled profile is mandatory; production hardening follows its stated gates.

2. Domain modules and dependency direction

clients / external services
   └─ admission, proof, query, export adapters
process assembly
   ├─ Commonware actors ── runtime / mesh / storage / custody
   └─ Makechain application adapter
         ├─ application executor ── schema / release / command authentication
         │       └─ owned typed-state interface
         └─ three-member state adapter ── exact glue DatabaseSet / QMDB types
proof verifier ── schema / release profiles / Commonware crypto and proof types

Arrows point toward dependencies. Process composition is outside the modules; co-location does not permit a dependency to reverse.

Domain module Owned interface and behavior May depend on Must not own
Canonical schema Exact bounded types, domain tags, IDs, signing presentations, exact-consumption codec, header/body/proof shapes commonware-codec, pinned crypto primitives RPC framework, database handles, release activation, cloud configuration
Release evaluator rules_for(executing_parent_branch, target_height_time), resolving authenticated schedule/effective parameters through pending ancestors; price/work/profile lookup, activation installers and format support Canonical schema, owned typed-state view Finalized-head shortcuts, scattered height checks, process rollout, storage migration, fallback after activation
Command authentication Family-specific signatures, root witnesses, scoped-key/role decisions, replay context under supplied rules/state Schema, release evaluator, standard verifiers HTTP identity, gateway trust, sequence allocation policy
Application executor Ordered command evaluation, bounded overlay, resource accounting, ledger aggregation, membership appends, events, the ordered change set, trace records, and header derivation except member roots and targets, which MerkleizeBlock computes Schema, release evaluator, command authentication, settlement verifier, typed state interface Consensus rounds, mempool policy, durable writes, background jobs, query indexes
Three-member state adapter Typed reads/staged writes for validity state; ordered membership appends/floor; block-history append; targets and canonical roots Exact Commonware QMDB/glue contracts Generic repositories, a fourth consensus database, cross-member atomicity claims
Engine assembly Runtime lifecycle; Simplex/marshal/stateful/reshare composition; cancellation; readiness; shared application SyncPlan, separate DKG sync plan, database and custody wiring Executor, state adapter, mesh membership, Commonware Command semantics, protocol bytes, service queries
Mesh membership One tracked peer-set owner for current/scheduled/departing validators plus the exporter and its standby, all primary and all non-voting mesh peers where they do not vote; ceremony-only projection; channel quotas Chainspec/release view including the governed exporter roster, validator schedule, authenticated lookup mesh Voting membership inference, discovery gossip, command validity
Proof verifier Finality/release lineage, command BMT, publication receipt, membership and current-state verification from caller trust anchors Schema, release profiles, Commonware storage/crypto primitives Network fetch, status interpretation, object availability, query results as authority
Admission and fan-out Bounded pool, structural/signature/replay checks, optional isolated dry-run, rate limits, f+1 fan-out acknowledgements, advisory status Schema, finalized snapshot reader, executor as optional caller Validity, durability promises, validator-to-validator gossip, fresh-sequence retry decisions
Finalized export Idempotent bounded handoff, durable queue of blocks, certificates and operation-log slices, drain to the store and the mirror as one batch per block including the projected history-table rows, durable watermark, watermark sequencing and mirror height-index scan, event re-derivation Slices from the members' merkleized batches in capture, schema, executor replay Blocking any validator's consensus following on its own durability (at its queue bound the exporter holds back only its own marshal acknowledgement, R-12.25), consensus roots for events
Query projection Deterministic history-table rows under a versioned schema prefix, occurrence-preserving, projected inside the exporter's per-block upload batch, with object metadata and publisher assertions in a separate non-reproducible prefix written by the indexer's ingestion worker; watermark-bounded query answers and consumer cursors Certified blocks/logs, re-derived events, verified objects Consensus writes, cryptographic absence claims, singleton publisher inference
Service authentication Edge/service identities, ACLs, quotas, availability retrieval policy Deployment identity and verified chain facts under a freshness policy Account authorization, consensus validity, object availability claims from hashes
Client workflow Command preparation, durable signing-slot journal, submission/reconciliation, and complete-push composition Canonical schema, release/profile data, proof verifier, transport adapters Canonical encoding forks, proof interpretation, automatic fresh-sequence retries under uncertainty

Inner dependencies on the specifically selected Commonware codec, cryptography, BMT, and QMDB primitives are intentional. A broad trait wall around them would hide consensus-critical behavior without providing a second real adapter.

Forbidden edges

  • Schema, releases, authentication, execution, and proof verification → cloud SDKs, HTTP servers, object storage, query engines, or node configuration.
  • Executor → Simplex rounds, marshal archives, durable database handles, wall-clock time, admission pools, indexers, or availability reads.
  • Consensus/state → query tables, events as inputs, service “not found,” object presence, or gateway status.
  • Proof verifier → gateway trust, server-selected chain identity, unauthenticated header/format hints, or native-only code unavailable to wasm.
  • DKG/mesh transport → application authorization; transport membership never selects voters.
  • Any service → a second implementation of canonical encoding, signing, release rules, or command transitions.

3. Core domain interfaces

These are semantic interfaces, not Rust trait or crate prescriptions.

Interface Input Output / errors Owner
DecodeCanonical<T> Bounded bytes and authenticated format profile Exact value and consumed length; structural/unsupported-format error Canonical schema
ResolveRules Executing fork's authenticated parent branch, including pending ancestors, plus target height/time Immutable Rules, prices, limits, verifier profiles; unsupported release is fatal readiness, not fallback Release evaluator
ExecuteOrderedBlock Fork-scoped parent batches, authenticated block context/rules, exact ordered envelopes, and Proposal, Verify, or Replay mode Deterministic outcome: ordered change set per member, derived header fields other than member roots and targets, command root/count, resource totals, events, trace records; no roots or targets; typed invalid/pending/fatal-local result Application executor
EvaluateCommand Rules, block-local overlay, exact envelope Isolated CommandChangeSet or typed rejection; merge occurs only after complete success Application executor
OpenParentView Fork-scoped parent branch and authenticated target context Typed validity reads plus membership/history positions; corruption or unavailable target is never invalidity Executor owns the narrow read contract; state adapter implements it
MerkleizeBlock Final accumulated changes in stable order Exactly one batch/commit per member, canonical roots and targets, and the change-set digest of what was staged; no inference of fees/events from collapsed DB diffs State adapter
VerifyEvidence Caller trust anchor, authenticated header/lineage, exact proof bytes Typed verified fact or bounded verification/capability error Proof verifier
TrackPeerSet The governed chainspec exporter roster, which lists the active exporter and the standby, plus scheduled/effective validator views and a set id One deterministic all-primary tracked union plus ceremony-only projection Mesh membership
PublishFinalizedRange Durable source watermark and certified block range Idempotent artifacts/events and advanced durable watermark, or explicit gap/failure Finalized export

ExecuteOrderedBlock is shared by propose, verify, and apply. Proposal mode may discard an invalid candidate before fixing the body; verification rejects a body containing any invalid command; apply reconstructs ancestors/winners. Those control outcomes differ, but EvaluateCommand, overlay order, resource reservation, roots, and events do not. Verify is cancellable and side-effect free. Apply returns database operations to Commonware; it does not persist them itself.

3.1 Stateful application adapter

The Makechain adapter implements the pinned glue::stateful::Application interface directly. The following contract is fixed even though Rust module paths and canonical field layouts remain P3/P5 work.

Adapter call Makechain input and output Cancellation and ownership
sync_targets(block) Reads the three authenticated targets already committed by the decoded block; returns them in (current, membership, history) order Pure and synchronous; Stateful selects the certified anchor and owns sync progression
genesis() Returns the one canonical genesis block for the supplied chainspec/profile Engine assembly owns the chainspec for the process lifetime; mismatch is fatal-local
propose(context, ancestry, batches, input) input contains only a ProposalSource handle. The adapter asks it for candidate leases under explicit block-byte, block-work, new-record, and failed-attempt budgets, executes serially, drops invalid candidates, and returns Proposed { block, merkleized } Stateful owns and may drop the future. A candidate remains in the pool unless the returned lease is explicitly committed as included or dropped with a reason; cancellation commits neither. No durable effect occurs
verify(context, ancestry, batches) Takes the candidate block from the first entry of Stateful's candidate-first ancestry, re-executes its exact canonical body and every header commitment, and returns the three merkleized batches only on equality Stateful owns and may retry/drop the future. Transient ancestry/resource availability keeps the future pending; deterministic invalidity returns None; local corruption stops the process
apply(context, block, batches) Replays the exact block body, compares every header commitment including the canonical state_root (R-12.11, TE-6), and returns the same merkleized batches as verification. The comparison is the adapter's because glue checks only the ops target and commits an apply replay without re-checking block-specific commitments (glue/src/stateful/mod.rs:267-270, :298-304) Stateful owns lazy-recovery/finalized-winner reconstruction. Cancellation leaks no effect; deterministic failure, a commitment mismatch included, returns None, which rejects the dependents of an uncertified ancestor, and inability to reconstruct a finalized winner is fatal in the wrapper
capture(context, block, batches, readers) Copies FinalizedHint { chain_id, height, block_hash, targets, ruleset_id }; it does not derive events or retain readers. On an exporter it also extracts the block's membership-log and block-history slices from the two members' merkleized batches (operations, operation-range proof, pinned nodes; R-17.10) and returns them as owned data Runs on Stateful's serial mailbox; bounded by one small owned record, and on an exporter by the block's own slices. The batches are still unapplied, which the compact member's proof requires
finalized(context, block, hint, readers) On a validator, calls non-blocking EnqueueFinalized(hint) and records its outcome, returning without storage or network I/O. Production engine assembly installs DiscardSink, the no-op record sink defined with the RecordSink trait in makechain-execution, and makechain-node never depends on makechain-trace; under glue::simulate only, the StashSink of the tests/trace-sim harness additionally reads the block's state back through readers (trace design record docs/execution/design/vp-02-trace-emission.md, TE-19). On an exporter it additionally appends one durable queue entry holding the slices capture returned, since it receives no batch and the compact history member keeps no operations; it still performs no network I/O Redelivery is allowed. On a validator, Full or Closed marks a scan-needed metric but is success for this observer because the certified block store is the recovery source. On an exporter the queue append is its only storage effect and the queue entry is the only slice source (R-17.10): an upload failure grows the queue, and at the queue bound the hook waits, holding back the block's marshal acknowledgement

ExecuteOrderedBlock and its overlay are one implementation used by the first three execution calls. Adapter control flow may differ, but command evaluation, reservations, MerkleizeBlock root construction, and header comparison may not. Commonware owns ancestry reconstruction, pending-branch lifetime, database application, barriers, pruning, and marshal acknowledgement.

Genesis database handoff

Pinned Stateful does not call Application::apply for genesis. On the marshal-start path it opens the database set, treats genesis as the already-processed anchor, and compares the committed targets with sync_targets(genesis); a mismatch enters rewind recovery, which cannot advance a fresh database to a post-bootstrap genesis target. A redelivered genesis is acknowledged without running the application hooks. Makechain therefore owns one pre-Stateful bootstrap task; no second component may seed genesis records.

The task first derives the complete chainspec, chain_id, body, and every genesis-header input that does not depend on application state. It opens only the current-state member at its native bootstrap target and builds one bounded batch containing the canonical protocol-genesis records in increasing state-key order. Merkleization is speculative: the task uses its canonical root and sync target to construct and verify the complete genesis block and hash before applying any current-state operation. It then applies the exact batch, starts and awaits that member's durability handle, drops the handle, reopens the member, and requires both canonical root and sync target to equal the genesis reference before Stateful or a network actor starts. Mutation failure consumes the owned database handle and is fatal-local; recovery reopens the partition rather than continuing with an in-memory object.

Membership and history remain at their pinned native bootstrap commitments for genesis. The task does not merkleize an empty batch for them because a keyless empty batch still appends a commit operation. The expected current root and target are the idempotence marker: native bootstrap means the task may build and apply once, exact genesis means it must not apply again, and any other target or root is fatal-local. No separate local marker or database initialization flag selects this path. When the application SyncPlan has a selected or persisted peer-sync floor, the task skips genesis seeding and state sync reconstructs the certified operations in fresh members. Ordinary restart also skips seeding because its committed current member already equals or advances from the genesis anchor.

Source basis at v2026.9.0: glue/src/stateful/actor/syncer/mod.rs:380-451 opens and reconciles the marshal anchor; glue/src/stateful/actor/core/processing.rs:425-445 treats that anchor's redelivery as a no-op; and the current, standard-keyless, and compact-keyless ManagedDb::initial_sync_target implementations use the native bootstrap commitment at operation size one. This source behavior is the reason genesis seeding is an engine-assembly responsibility rather than an executor transition.

3.2 Admission and proposal interfaces

Admission and proposal deliberately use separate state and work adapters.

Interface Contract Owner
OpenAdmissionSnapshot Returns one immutable, finalized AdmissionSnapshot { checkpoint, rules, bounded_records } for the explicitly requested read set. Unavailable or an over-budget read yields NotReady; it never falls back to speculative batches Gateway or validator admission adapter; production may use an authenticated follower/read replica, while the first devnet uses the local finalized projection
Admit Takes exact envelope bytes, snapshot, ingress identity, and admission budget. Returns the specification admission class plus checkpoint, intent/command IDs, and optional conflict detail Admission task; structural/signature/chain/replay work is mandatory, dry-run is off by default
DryRun Calls EvaluateCommand against a disposable overlay made from the admission snapshot, under a dedicated semaphore and CPU/work budget Admission worker pool; timeout/cancellation returns advisory NotReady/StateConflict only and never consumes proposal permits
InsertCandidate Atomically applies same-slot replacement, count/byte bounds, and drop-oldest eviction; returns the inserted/known/replaced/evicted identities Each validator's pool task; status is local and finite
SelectForProposal Takes ruleset plus remaining block and attempt budgets; returns an ordered CandidateLease batch and charges every selected attempt until commit, defer, or drop(reason) Consensus proposal path owns the lease; selection never calls admission dry-run
FanOut Sends an admitted envelope concurrently to the fixed validator set with one bounded in-flight queue per validator; returns per-target outcomes and Accepted after f+1 acknowledgements Gateway fan-out task; cancellation closes unsent work and preserves received outcomes

The snapshot interface is separate from OpenParentView: advisory admission sees one finalized cut; proposal, verification, and replay receive branch-scoped Commonware batches. They share canonical schema, authentication, and EvaluateCommand, but no mutable view, semaphore, queue, or work budget. This resolves A3 without relying on a generic repository interface.

In the first devnet, OpenAdmissionSnapshot reads a separately owned derived projection updated by certified sequential block replay. The projection commits its explicit admission records and checkpoint together, then atomically swaps the readable snapshot. It may lag and return NotReady; it never reads the live QMDB batches. A later production adapter may use an authenticated follower or proof-backed snapshot without changing callers.

3.3 Finalized export interface

EnqueueFinalized is a count-and-byte-bounded in-memory hint channel. It is deliberately lossy: Queued, Coalesced, Full, and Closed are observable outcomes, and neither Full nor process exit blocks Stateful. The exporter owns one durable at-least-once staging queue and one durable ExportWatermark { chain_id, next_height, predecessor_hash }.

The exporter enforces its durable queue bound before Commonware enqueue using tip - ack_floor plus the encoded bytes of non-pruned entries, recomputed during restart replay. At the bound the finalized hook waits for space instead of skipping the append, which holds back the block's marshal acknowledgement until the drain frees an entry (R-17.10); no height is left unstaged. Commonware supplies durable FIFO positions and restart redelivery, while Makechain owns this admission bound and never treats queue presence as exported progress.

The worker always computes work from the watermark and the queue, never from a hint; the queue entry is the only source of a height's material (R-17.10):

  1. Select exactly next_height, take its canonical body/header/finality evidence and both operation-log ranges, each with its operation-range proof and pinned nodes, from its queue entry, and verify continuity from predecessor_hash.
  2. Upload the operation ranges, the block, the certificate, and the projected history rows to the exoware store in one batch, and publish the same per-block object to the mirror with create-if-absent semantics; an existing different digest is fatal-local. Re-derived event inputs are built from the same material. Uploads are idempotent and may overlap or arrive out of order, so a retry repeats the identical range.
  3. Verify the uploaded rows and the published mirror object, then atomically persist the next watermark. Only afterward acknowledge/prune the staging entry.
  4. Repeat until the highest staged height. A hint can wake or coalesce work, but can never skip a height.

On restart the Commonware queue re-delivers every non-pruned item and the drain resumes from the watermark; marshal redelivers every block above the processed height, whose hooks stage it again. If the queue is unavailable after an interrupted mutation, reopen it from its partition; a height above the watermark and at or below the highest returned hook with no queue entry, outside a state-synced range, is a fatal publication gap: stop publication and alert (R-17.10). The scan keeps only watermark sequencing and the mirror height-index comparison. This resolves A4 without making exporter durability part of any validator's consensus acknowledgement; the wait at the queue bound holds back only the exporter's own marshal acknowledgement (R-12.25).

4. Commonware assembly and ownership

Fixed production baseline: Tokio runtime; authenticated lookup mesh; Simplex with Random V1 rotating terms; marshal::standard::Deferred; dkg::reshare::Application; stateful::Stateful; the Makechain application; a three-tuple DatabaseSet; one shared application SyncPlan; one injected parallel strategy; and the separate DKG sync plan/fence/gate. Coding marshal and stable terms require later release decisions; an upstream Commonware fork is prohibited.

Commonware seam Makechain supplies Commonware owns Required check
Stateful application canonical block context, propose/verify/apply/finalized/capture behavior, all header checks including state_root fork-scoped execution lifecycle, ancestry reconstruction, cancellation APP parity, cancellation, late invalidity, finalized-winner reconstruction
Database set exact current-unordered-variable, membership-keyless-fixed, history-keyless role adapters and chainspec root parameters per-member finalize handles, durability barrier, pruning dispatch, target reconciliation roots/targets agree after crash; no cross-member atomicity claim
Marshal block codec/limits, retention coupling and the per-role block-store choice deferred proposal verification/persistence, certificates, backfill largest legal body fits p2p; retained history covers selected recovery envelope
Reshare/DKG immutable epoch participant/directory provider, schedule policy, payload attachment, durable SecretStore adapter ceremony progression, carry-over, epoch output, DKG sync plan and startup gates set-change plus DkgFailed, restart, share handoff/erasure policy
Mesh the single all-primary tracked union, including the exporter and the standby as non-voting mesh peers from the governed roster, and the channel plan authenticated transport and peer-set mechanics the exporter and standby peers survive ceremony projections; bounds cover largest union
Sync source certified targets, untrusted bulk/tail sources, role-specific retained operations strictly advancing state sync and persisted plan all three targets/root match one certified header before voting

The canonical header carries history as CompactTarget { root, size }. Every node role, validator and exporter alike, runs the compact history adapter and consumes that target directly, and every role supplies inactivity floor zero when merkleizing a history batch, so all roles execute the same encoded operation stream and obtain the same root. The full operation history lives in the store, rebuilt from the slices the exporter uploads, and the full target Target { root, range: 0..size } is derived there as a proof-service reconstruction step rather than by any node's startup check. That reconstruction must not use Commonware's native TryFrom<&CompactTarget>: at the pinned revision it deliberately creates size - 1..size, which retains only the last operation. Commonware's compact keyless implementation documents that compact and full databases compute the same root when they receive the identical encoded operation stream and inactivity floor (storage/src/qmdb/keyless/compact.rs; conversion in storage/src/qmdb/sync/target.rs:112-128, revision pinned below).

Background work and fault ownership

Work Queue/backpressure owner Cancellation and safe outcome
Admission and fan-out Admission adapter; bounded count/bytes, dedicated dry-run permits, and bounded per-validator in-flight sends Eviction/replacement/rejection is an explicit advisory outcome; shutdown/release change cancels sends, never invents inclusion
Proposal/verification/apply Commonware actors own fork jobs; executor accounts local work Dead-fork verification is cancellable; apply ancestry follows Commonware recovery; no partial executor effects escape
Finalized handoff Makechain application adapter offers one small hint to a bounded in-memory channel Full/Closed records scan-needed and returns; the durable watermark, not the hint, finds every gap
Export/query The exporter owns the single-reader durable staging queue, retry state, and the upload batch; consumers own their own cursors and backpressure Restart reopens/replays the queue and resumes from watermark; lag affects service freshness, not validity
State/DKG sync Stateful/reshare actors own plans and gates; SecretStore owns custody-write completion Cancellation cannot expose readiness; transient lack stays pending, corruption stops the role
Fault category Meaning and owner response
Invalid Deterministic protocol failure. Proposal may discard a candidate; verification rejects a block; no effects merge
Pending Transient local inability such as missing ancestry/history or bounded future-time wait. Keep pending or abstain; never vote invalid
Fatal-local Corruption, failed finalized-winner reconstruction, unsupported active release, or irrecoverable local contract failure. Stop readiness and recover
Service outcome Rate limit, unavailable proof/object/query, stale view, or unsupported capability. Report explicitly; never convert it into a consensus result

The finalized application hook sees readable state before the database-set durability barrier and may be redelivered or skipped by state sync. It hands off bounded owned data promptly. Exporters and indexers advance their own watermarks only after durable publication; an exporter publishes only from its queue entries (R-17.10), and an indexer fills gaps from the stored blocks. A finalized event is never a receipt; proof availability is a separate milestone.

Pinned source basis, not Makechain qualification evidence: Commonware v2026.9.0 (d476a2361ce6840d2b9d0aa6fb30a924429046d4), especially glue::stateful, glue::dkg::{bootstrap,reshare}, consensus::marshal::standard::Deferred, and the QMDB adapters.

The exact primitive mapping at that revision is: application calls and cancellation from glue/src/stateful/mod.rs:124-390; tuple member batches/barriers/readers from glue/src/stateful/db/mod.rs:210-435,966-1084; staged current-state reads from glue/src/stateful/db/current.rs; and the export staging buffer from storage/src/queue/{mod,shared,storage}.rs. The queue is durable and at least once, exposes cloned writers and one reader, and persists pruning only on sync; it does not provide Makechain's byte limit, certified gap choice, artifact idempotence, or exporter watermark, so those remain in the Finalized export module rather than being attributed to Commonware.

5. Process assemblies

Logical roles remain distinct even when one process hosts several adapters.

Assembly Modules hosted Persistent authority / serving rule
Validator Engine, executor, state adapter, mesh, local admission pool, diagnostics Votes; three databases, marshal window, journal and DKG custody; serves no public reads or historical proofs
Exporter Non-voting Stateful/executor follower on the same binary and a non-voting mesh peer from the governed roster; the same three-member tuple and marshal block store with validator-shaped retention, capture-time slice extraction, the durable publication queue, and the drain to the store and the mirror Holds no vote; publishes every finalized block, certificate, and operation-log slice, and serves current-state proofs with activeness plus within-window membership proofs from its live databases. One active exporter publishes; one standby follows with publication off, keeps its own durable queue of every finalized block, and releases an entry only on an observed store and mirror watermark past it. Either state-syncs at its first installation only, recording its sync anchor A durably with queue coverage from A + 1, permitted only while every height in (W, A] is durable elsewhere, and with a certificate-verified sync-target finalization
Proof service The exoware operation-log service over the store, plus the Makechain checker Serves membership inclusion at any location against the root at any size, and block-history ancestry proofs; the checker verifies each block's finalization certificate from its own trust anchor and then asserts the store's root at the ingested size against that verified header's membership_target and history_target, and a mismatch fails ingestion rather than a proof request
Gateway/admission Admission, bounded fan-out/status, proof/query pass-through with query answers cached by (query, watermark height), service authentication No consensus authority; Accepted is f+1 acknowledgement, never durability/finality
Indexer/query A service over the store: the query API over the history tables, the event subscription, "not found" and dedup, the query facade, and command-inclusion proofs and publication receipts built from stored blocks. It owns no database of its own, and the exporter projects every block-derived row; its one writer is an object-fetching ingestion worker that fills the two non-reproducible tables, object metadata and publisher assertions, in a separate schema prefix, because neither object bytes nor off-chain signed messages travel in a block Rebuildable; every answer is bounded by the published watermark and exposes it with its evidence class; the BMT is stateless, so a receipt needs the stored block and nothing else; the ingestion prefix is outside the rebuild-from-mirror equality check
Settlement relayer Tempo evidence acquisition/verification and IMPORT_CREDITS submission No credit authority beyond exact proof accepted by execution
Availability layer (several per project) mkit object verification/storage, chain-authorized writes, per-layer disclosure and retrieval policy External content custody; no consensus fact or chain-credit debit; obligations are in availability profile
Native/wasm verifier Canonical schema and proof verifier only Caller-selected trust anchor; no node/cloud runtime, live storage handles, network I/O, status interpretation, or workflow journal; selected Commonware proof types remain dependencies
Later SDK/CLI Client workflow plus generated transport bindings around the native/wasm verifier Deferred until its consumed contracts pass their gates; it is not part of the first implementation slice

Minimal development composition (fixed design): run each of the seven validator identities as a separate engine process, and co-locate its local admission adapter only. One exporter process may also host the store and the proof service for the first slice; gateway, indexer/query, settlement fixture tool, and the availability-layer test adapter remain separate processes only when their scenario is exercised. Preserve interfaces, separate durable partitions/watermarks, and proof trust boundaries. Use the real three-member database set and executor from the first end-to-end slice. Deterministic-runtime test adapters may replay captured authentic Tempo evidence and replace availability/object-storage transport, while using the real codec/verifier contracts. No adapter may synthesize a positive Tempo certificate or bypass import verification. Devnets/testnets require Moderato proofs; mainnet requires Tempo mainnet proofs. No genesis credit allocations or Makechain faucet bypass are permitted. The first funded slice imports credits before account initialization; see operations.

Co-location is a process-count choice only. Seven identities in one project, cluster, region, or administrative team are not claimed as independent trust or failure domains. SDK, CLI, explorer, website, and the separate consuming application are deferred consumers; no early scaffold is part of this architecture definition.

Production composition (fixed responsibilities, open placement): separate validator identities; one active exporter and one standby, failure-isolated from each other so their durable queues cannot be lost in one event; two failure-isolated store copies, the exoware store and the mirror bucket; independently scalable admission, export/query, and relayer processes, plus the availability layers described below. Low/medium/high workload and machine counts remain operating-envelope/P4 inputs; module boundaries do not change with size.

Availability is not one service. A project may be served by several availability layers, each with its own authentication, disclosure and retrieval policy, and the chain records no locator for any of them: a project's layers are announced off chain by messages signed with the project's keys. No protocol role depends on a particular layer, and object unavailability never changes the validity of a finalized publication. The nine obligations a layer takes on when it serves a Makechain project are in availability profile.

For the accepted first shared devnet, the mirror's per-block objects use the GCS adapter defined in operations. That decision excludes repository objects, does not authenticate protocol bytes, and does not select production replication or store placement.

5.1 Exporter, store, and proof service

An exporter is a real non-voting Stateful node on the same binary, not a file mirror. It executes every finalized block with the production executor, uses the same three-member tuple and root parameters, and prunes exactly as a validator does: validity state at active size, the membership log windowed to [floor, size), and the block-history accumulator compact. It checks all three targets plus canonical state_root at each certified cut. Its marshal block store prunes after retained_marshal_blocks like a validator's; a block it has not yet published stays readable from its durable queue, which releases an entry only after the store and the mirror both accepted it. Proof workers receive read-only handles; they never mutate the live databases.

An exporter state-syncs at its first installation and never again; afterwards it follows marshal, which is glue's own rule for a node whose sync has completed. Under R-17.21 state sync installs a height range without running the finalized hook, so nothing that range contains reaches the installing node's queue. On completion the node records its sync anchor A durably, and its own queue coverage begins at A + 1. From the start of the installation until A is recorded, the node re-evaluates at every retargeting of its sync that every height in (W, current target] is durable elsewhere, W being the publication watermark observed in both the store and the mirror at the start of the installation: either the publication watermark has reached the current target, or the other roster member is healthy, meaning its queue coverage is at least the current target and its publication watermark has advanced within the exporter publish-lag bound. If neither holds at any evaluation, the node aborts the installation and alerts; an installation that completes anyway loses (W, A] under the first cause of the history-range-loss risk in specification section 4.4 (R-17.21). Because that coverage carries the safety, the sync target is free, which is what lets a fresh installation, including a replacement standby, sync to a recent target and start with an empty queue. The finalization the plan pins as that target is read from the store's finalized-by-height record and is certificate-verified before the plan adopts it, since the store authenticates no writer. An exporter for which max(own queue coverage, publication watermark) lies below the validators' retained window has no source for the missing range, so it stops and alerts instead of syncing. The same rule binds the standby.

Publication starts in the capture hook, which runs before apply, and continues in the finalized hook, which runs after apply and before pruning (R-17.10). In capture the exporter extracts the block's slices of the membership-log and block-history operation logs from the two members' merkleized batches: the raw canonical operation bytes of each range together with that range's Commonware operation-range proof and pinned nodes, which are exactly the inputs the exoware writer authenticates against a caller-supplied root. It cannot do this later, because a compact batch proves its operations only until it is applied and the compact member keeps no history (storage/src/qmdb/keyless/compact.rs:1-8), and finalized receives readers but no batch (glue/src/stateful/actor/processor/mod.rs:939-962). In finalized it appends the block, its finalization certificate, and those two ranges to a local durable queue (commonware_storage::queue) and returns. A drain task uploads each entry to the store and to the mirror, retries forever, and acknowledges the queue position only after both have accepted it. An outage grows the local queue; only at the queue bound does the hook wait, holding back the block's marshal acknowledgement. Uploads are idempotent, so a retry repeats the identical range rather than reconstructing one.

The drain commits block batches to the store strictly in height order, one at a time, because a query bounded by a published watermark H would otherwise miss the rows of a lower height whose batch had not landed yet. Concurrency is admitted in two places that cannot reorder a height: the qmdb node rows staged ahead of the ordered batch, and the mirror uploads, which are content-addressed per block and carry their own watermark advanced only after the per-block object and its height-index entry are both readable.

The store is two copies of the same history, and either is rebuildable from the other.

  • The exoware store: exoware-simplex for blocks and certificates, keyed by digest for headers and blocks, by epoch and view for Notarized and Finalized records, with a finalized-by-height index; exoware-qmdb for both operation logs, which persists Merkle nodes as ranges arrive and answers historical roots and proofs at any caller-chosen size; and exoware-sql for the history tables, which is the query tier described in history-query.md. The exporter projects each block's rows for those tables inside the same upload batch, so the rows land atomically with the block, its certificate, and both slices. All three sit behind exoware-server, a backend-agnostic ConnectRPC router over the Sequence, Ingest, Query, Prune, Log, and Retention capability traits, on a RocksDB backend hardened from the simulator implementation and placed on a persistent disk with snapshots. exoware ships no replication, snapshot, or backup of its own, and its server carries no authentication, so the disk snapshots, the mirror, and the private-network placement in section 3.3 of operations.md are all Makechain's.
  • The mirror: one raw object per block, holding the block, the certificate, and both slices, content-addressed by block_hash, with a height index and a durable watermark, on an object-storage bucket under a retention lock, kept forever. A second provider may be added later by replaying the mirror.

The proof service is the exoware operation-log service plus the Makechain checker. exoware answers membership inclusion for any location against the operation-log root at any size, and block-history ancestry, from its persisted Merkle nodes; Makechain writes no prover. exoware verifies a proof's internal consistency but never compares it against an external commitment, because the trusted root is the caller's input. The checker supplies that comparison: at every ingested block it asserts that the store's root at that size equals the header's membership_target and history_target, and a mismatch fails ingestion loudly rather than failing a proof request later.

The checker takes those targets from certificate-verified headers only. It verifies each header's finalization certificate against its own trust anchor before it compares anything, because the store authenticates no writer and performs no certificate verification of its own, so a header and a log read back from the store are self-consistent whoever wrote them. Reading the comparand from the store would therefore compare the store against itself. The checker is detective rather than preventive, since proofs are servable from the moment a watermark is published, and its unique value is detecting a foreign write or corruption; the periodic replay job verifies certificates the same way. Stopping ingestion is a concrete act: the checker signals the active exporter's drain to halt, so nothing further enters the store, while the store keeps serving the range it already holds.

The proof service maps the header's compact (root, size) to the full target Target { root, range: 0..size } from the store's published operation logs, requiring exact root equality and a nonzero valid size. That reconstruction happens in the proof service alone, never in a node's readiness check, and it must not use the library's compact-to-full convenience conversion, which retains only the last operation.

Historical current-state proofs are not offered. The exporter serves current-state proofs, with activeness, and within-window membership proofs from its live databases behind a read lock. A later release may add proofs at an older height by batch replay of stored blocks into a fresh instance; the live current database is never rewound for a request. Validators join and restart by state sync from validators, so no bootstrap artifact is on the startup path and the tiled bootstrap format is deferred.

One active exporter publishes and one standby follower runs with publication off, resuming from the store watermark when it takes over. That is a Makechain simplicity choice, not an exoware constraint: uploads may come from several workers concurrently, and only the publication watermark has one logical owner. This closes A5's assembly choice while keeping an unmeasured interval out of the protocol.

Publication off does not mean queue off. Under R-17.22 the standby follows every finalized block and appends the same durable queue entry the active appends, holding the block, its certificate, both operation-log slices, and the projected rows. It uploads nothing; it releases an entry only when it observes the store and the mirror watermark past that height. Its queue therefore holds exactly the range the active exporter has not yet made durable in both copies, which is what makes it the third recovery source when an active exporter loses its disk with an undrained queue. That value exists only if the two fail separately, so R-17.15 requires the standby to be failure-isolated from the active, sharing no host, no disk, and no power or network failure domain.

6. Reset-bound fixed-committee profile

Accepted owner policy: disposable pre-mainnet networks may be reset explicitly to a new genesis and chain_id; a reset makes no history or credit preservation promise.

Accepted by the owner, 2026-09-19: the first disposable devnet uses seven fixed validators in epoch zero with pre-generated threshold output/shares, threshold VRF, a constant signing-scheme provider, an effectively unbounded fixed epocher, and no continuous reshare actor. This follows the simpler fixed assembly demonstrated by Constantinople, while Commonware itself separates one-shot bootstrap from continuous reshare. The material is trusted-dealer custody, not trustless genesis. Removing reshare simplifies orchestration; it promises no intrinsic latency or throughput improvement. The constant scheme provider is not epoch authorization: engine, block-context, and proof checks must enforce epoch zero. See the source evidence (external site) for exact pinned mechanisms.

The specification binds FixedEpochZeroV1 or DynamicReshareV1 in the genesis chainspec (specification section 5.4). Canonical bytes remain to freeze. The fixed profile deterministically rejects validator-set schedule commands and consensus-critical release scheduling in both admission and execution. It may not accept them as no-ops, hide them behind a local feature flag, or claim all seventeen production commands work. Epoch length and the group identity cannot be changed in place under the current specification. The accepted development path moves from the fixed profile to DKG/reshare qualification by an explicit reset/new chain_id, with no history or credit migration promise. It does not require every pre-mainnet configuration change to reset.

Source basis, not qualification: Commonware glue/src/dkg/mod.rs:1-15, bootstrap/mod.rs:1-10, and reshare/mod.rs:18-165 at the pinned tag separate one-shot bootstrap from continuous reshare. Constantinople 42d0b3a demonstrates a fixed epoch-zero assembly with pre-generated output/share; it does not establish production custody or Makechain conformance.

Profile Useful evidence Cannot qualify
Fixed development Codec/vectors, executor parity, three-member roots, crash/cancellation, receipts, native/wasm, admission contention, indicative latency DKG bootstrap/reshare, membership scheduling, custody handoff/erasure, consensus-critical release handoff, late join, production recovery/topology
Fixed qualification testnet Heavy-agent workload, exporter/store/proof service, window/retry behavior, service contracts at realistic history Any gate depending on dynamic epochs or production failure domains
Dynamic fixed-committee staging Continuous reshare across boundaries, carry-over, custody restart and sync while participants stay fixed Validator set-change scheduling, joining/departing transport union, production membership governance
Dynamic qualification testnet Complete production assembly, set change/carry-over, release activation, bootstrap/recovery and topology faults Mainnet capacity until target environment/workload acceptance is met
Mainnet Current dynamic specification after all gates and explicit readiness approval No deferred surface is implied safe by earlier-profile results

Every pre-mainnet reset gets a new genesis and chain identity. Stable-leader experiments are a separate consensus choice and gain no approval from this simplification; Random/rotating remains the production baseline until an explicit specification decision and qualification.

7. Workflow ownership

Workflow Required path and authority
Publication Client stores closure separately → gateway admission/fan-out → executor orders PUSH → Commonware finalizes → database barrier makes progress durable → the exporter publishes the block, its certificate, and both slices to the store and the mirror → client verifies receipt; storage and chain outcomes stay separate
Authority change Canonical intent → command authentication under parent/overlay state → executor changes counters/generations atomically → derived event; gateway dry-run is advisory
Proof serving Membership and ancestry proofs come from the proof service over the store's operation logs, current-state and within-window membership proofs from the exporter's live databases, command proofs and receipts from the indexer's stored blocks → reference verifier authenticates from caller trust anchor; gateway only transports
Startup/recovery Operator trust material → shared application SyncPlan verifies bulk target/tail → reconcile three targets and state_root → separate DKG sync/readiness gates → own live vote above journal ceiling
Export/query capture extracts the slices and the finalized hook stages them in the durable queue → the drain takes each height from its queue entry → the block, the certificate, both slices and the projected history-table rows commit as one batch and advance the watermark → a query reads the watermark first, bounds itself to it, and discloses it

8. Deferred work and validation gates

Gate Acceptance evidence Blocked or deferred until it passes
G1 Canonical contract Cross-release vectors; native/wasm decode, signing and proof parity Public SDK/CLI and receipt compatibility
G2 Executor parity Profile-applicable APP scenarios plus propose/verify/apply, rollback, cancellation, duplicate keys and deposit conservation; fixed profile runs APP-01–13, APP-15–19, APP-20's fixed-genesis cases, and APP-14's installer/state-sync portions, while its dynamic schedule case moves to G5a/G5b/G6 Claiming executor conformance or allowing dependent product contracts to stabilize; integration tests themselves remain allowed
G3 Persistence/recovery Crash at each member/barrier point by the crash-cut tests of validation 7.1, which stop the process or abort storage handles at the named barrier; glue::simulate reaches a barrier only through recorded seed sweeps over height windows or storage-fault injection (validation 7.1); root/target reconciliation; ordinary restart and deliberate rebootstrap Continuing testnet and production validator operation
G4 Fixed-profile conformance Profile identity, APP-15–20 as applicable, and deterministic rejection of unavailable schedule transitions Any claim that simplified networks implement their declared rules
G5a Continuous reshare APP-20 dynamic-genesis payload projection, fixed-committee boundaries, DkgFailed carry-over, custody restart/handoff/erasure and DKG sync Set-change qualification and mainnet
G5b Dynamic membership Schedule/lock, add/remove, transport union, late join, departure and carry-over under a changed set Dynamic qualification testnet completion and mainnet
G6 Release handoff Rules/installers and every consensus-critical surface across the handoff at the boundary into the first block of the activating epoch, with restart and catch-up Continuing chain activation of a new ruleset
G7 Proof/export API-01–20, checker root agreement at every ingested block, authenticated gap rebuild from either store copy, duplicate occurrences, receipt substitution failures Public proof claims, store independence, query freshness claims
G8 Workload/topology Heavy-agent expected/burst/stress mix; latency/backpressure/retry distributions; selected cost/latency placement failures Numeric capacity/SLO claims and mainnet topology approval

Deferred product SDK, CLI, explorer, website, and broad service work may begin only when the contract it consumes has the corresponding gate evidence. Fixed-profile evidence remains useful but is never credited to a blocked dynamic-profile gate.

9. Architecture decision disposition

ID Disposition Remaining gate, if any
A1 Accepted: fixed seven, epoch zero, real pre-generated test shares, explicit reset to the dynamic profile P3 freezes bytes and G4 supplies vectors; G5a/G5b qualify real DKG/reshare before mainnet
A2 Resolved for P2: canonical Rust schema/release types are the source; the executor consumes those owned types; the Stateful adapter alone maps them to pinned Commonware types. Transport schemas and TypeScript declarations are generated later from versioned schema inputs and are never authoritative. Native and wasm use the same Rust verifier. Client workflow owns journals and reconciliation, not proof interpretation P3 freezes exact layouts/discriminants and vector manifests; P5 chooses physical crate/package paths. Coding may begin behind the semantic interfaces before vectors exist, but no conformance claim may
A3 Resolved: admission receives a finalized immutable AdmissionSnapshot; proposal receives branch-scoped Commonware batches. Dry-run uses separate permits and is off by default; proposal attempt budget is never shared Contention/cancellation qualification is part of G2/G8, not an interface decision
A4 Resolved: non-blocking lossy hint channel, single-reader Commonware durable staging queue as the only slice source, watermark-sequenced drain with a mirror height-index scan, create-if-absent artifacts, and watermark-after-verification Queue sizes/retry timings are deployment calibration; C5-C8 and G7 qualify crash/redelivery behavior
A5 Resolved: a non-voting Stateful exporter with validator-shaped retention publishes each finalized block, certificate, and operation-log slice from its finalized hook through a durable queue into two store copies, the exoware store and the mirror bucket; the exoware operation-log service plus the Makechain checker is the proof service, the exporter serves current-state proofs from its live head, and validators bootstrap by state sync from validators Store growth, ingestion lag, and recovery from either copy are measured at the platform-owned G8 recovery target; historical current-state proofs wait for a later release
A6 Deferred: low/medium/high process sizing and scaling Platform lead owns workload/topology/cost research at G8; no architecture split by machine size
A7 Deferred: stable terms or coding marshal Explicit later release decision and workload/failure qualification; neither is part of early simplification

P2 now has an owner and implementable semantic interface for every responsibility and process. Review does not change protocol validity, authorize deployment, or mark any qualification result as measured. P3 byte freeze and runtime qualification are downstream gates, not reasons to leave module ownership undecided.

10. Commonware primitive map and storage decisions

This section holds material formerly stated in the specification and is not normative: the specification and its companions remain authoritative for every rule. It supports specification chapter 2 (system overview), chapter 6 (encoding and digests), chapter 9 (state and record lifecycle), chapter 11 (blocks and headers), and chapter 17 (node roles and the database set).

Section 4 of this document already carries an equivalent table at a different granularity: it maps each Commonware seam to what Makechain supplies, what Commonware owns, and the required check. The table in section 10.1 maps each component to the primitive it uses and that primitive's stability. The two are read together; neither replaces the other. The fixed production baseline paragraph in section 4 states the same assembly in prose.

10.1 Primitive map

Every component uses the Commonware primitive that fits, ALPHA included. Where no primitive exists, the component is named in section 10.4 so that nothing is assumed. Stability is recorded at v2026.9.0. Bumping an ALPHA dependency is presumed to need a release, classified by the specification's storage-and-dependency-change rules, and re-runs the ALPHA parity set in section 11 of validation.md.

Component Primitive Stability
Runtime runtime::tokio in production, runtime::deterministic in tests BETA / ALPHA
Mesh p2p::authenticated::lookup with one all-primary tracked peer set BETA
Consensus consensus::simplex with elector::Random V1 and rotating terms; profile-selected fixed or orchestrated assembly BETA
Ordering and backfill consensus::marshal::standard::Deferred, broadcast::buffered, resolver::p2p BETA (coding marshal ALPHA, unused)
Execution host glue::stateful::Application with a three-tuple DatabaseSet, SyncPlan, db::p2p sync source ALPHA
Validity state storage::qmdb::current::unordered::variable through glue's variable-value adapter, merkleized with Makechain's local Keccak256 implementation of the pinned commonware_cryptography::Hasher (follow-up F13) ALPHA
Membership log storage::qmdb::keyless::fixed full variant, merkleized with Makechain's local Keccak256 implementation of the pinned commonware_cryptography::Hasher (follow-up F13) ALPHA
Block-history accumulator storage::qmdb::keyless, compact on validators and the exporter, reconstructed in full by the proof service, merkleized with Makechain's local Keccak256 implementation of the pinned commonware_cryptography::Hasher (follow-up F13) ALPHA
Command root storage::bmt with Makechain's local Keccak256 implementation of the pinned commonware_cryptography::Hasher (follow-up F13) ALPHA
Threshold identity FixedEpochZeroV1: trusted feldman_desmedt::deal fixture, threshold-VRF signer validation, FixedEpocher, and ConstantProvider with independent epoch guards; DynamicReshareV1: glue::dkg bootstrap, reshare::Application wrapper, probe, DKG state-sync plan with fence and gate; both use AttributableReporter and cryptography::bls12381 ALPHA / BETA
Certificates and blocks marshal::store::Certificates over storage::archive::prunable (validators and the exporter) BETA
Watermarks storage::metadata BETA
Parallelism one parallel::Rayon strategy injected everywhere ungated
Signatures cryptography::ed25519 and bls12381 for consensus, DKG, and governance; account families use external standard verifiers over the same curve crates BETA
Encoding and vectors commonware-codec, commonware-conformance BETA-equivalent
Assurance glue::simulate, invariants::minifuzz, per-crate fuzz targets ALPHA
Browser verifier the Rust verifier compiled to wasm32, as Commonware's own CI builds consensus, storage, and cryptography build target

Two notes on the hasher rows:

  • The proof-path members and the command root use Makechain's local Keccak256 implementation of the pinned commonware_cryptography::Hasher (follow-up F13). The proof path is everything a verifier hashes between a finalization certificate and a proven fact: block_hash, the merkleization of the three authenticated databases, the membership leaf, the block-history leaf, and command_root. The two leaves a contract must bind to an outside fact are Keccak256 over the fact itself: the command-tree leaf is Keccak256(canonical SignedCommand bytes) and the membership leaf is Keccak256(project_id || scheme_id || native_id), so neither binding needs a BLAKE3 step on the target chain. BLAKE3 remains everywhere else, including content identity, command_id, CommitmentId, state keys, and every domain-separated preimage.
  • The Keccak256 hasher is Makechain's own implementation of the pinned commonware_cryptography::Hasher trait, follow-up F13, cross-checked against the library's post-tag implementation once that ships. Neither a Commonware pin move nor a git submodule is used: a main-branch pin would split the dependency graph from exoware 2026.9.0, which pins the commonware-* crates at 2026.9.0. The Solidity verifiers for threshold certificates, QMDB, MMR, and BMT proofs are consumed separately from the pinned tag and do not require the Rust pin to move. Merkleization cost under Keccak256 at the target throughput is a calibration item, and the choice is final only when that measurement passes. The re-measurement is section 11.7 of validation.md.
  • Code structure keeps the choice reversible: each proof-path tree names its hasher through one alias in makechain-protocol (block hash, command root, membership log, block-history accumulator, validity state), every proof-path site imports the alias, conformance vectors are generated from it, and a lint forbids naming a concrete hasher on the proof path. Moving one tree or the whole path to BLAKE3 is then a type change plus regenerated vectors, decided at SB-15's decision point in implementation-second-batch.md (external site).

The block-history accumulator has its own row above so that all three merkleized members appear together; the specification's own primitive map states its primitive in the database-set subsection rather than in the map table.

10.2 Two scoped constraints

Two rules from the specification's design principles are scoped here so they are not misread.

Hash maps on consensus paths. The rule governs Makechain-owned code, where iteration order could reach an encoding or a root. Commonware's internal unordered collections never determine consensus order: where one is iterated, its indices are sorted and deduplicated before any ordered work, and the resulting roots are pinned by conformance vectors. Those internals are therefore compliant.

Truncated identifiers. The rule governs stored, routed, and hashed values. The index translator shortens keys only to choose a bucket, and every read compares the full key before returning. Translation is not truncation, and the per-key memory figures stand.

10.3 External projects

Two projects are depended on that are neither Commonware nor Makechain-owned.

Project Supplies Pinning
mkit (alpha) object identity, attestation format, transport protocol, wasm verifier pinned by version in the chainspec format identifiers; bumped only by release
Tempo settlement source; the configurable-account derivation and the configuration bounds of the TIP-1107 cluster, at a pinned specification commit pinned by version in the chainspec format identifiers; bumped only by release

Dependency and pin policy is owned by repository.md.

10.4 Makechain-owned, with no Commonware primitive

  • secp256k1 signing and recovery, through an external crate.
  • SSHSIG, WebAuthn, and P256-direct verification, through external standard verifiers, because Commonware's public verifiers always prepend a namespace.
  • EIP-712 framing.
  • The mempool, admission, and gateway fan-out.
  • Write forwarding.
  • Object-store publication.
  • The tiled bootstrap artifact format, which is deferred.
  • The deterministic projection of history-table rows, which exoware stores and queries but does not derive.
  • Ethereum MPT proof verification and Tempo certificate decoding.
  • The Ed25519 governance multisig.
  • P256 batch verification, if it is ever wanted.
  • The multi-consumer event outbox.

The owning modules for these are already named in section 2; this list is the negative view, stating which of them cannot be delegated to a primitive.

10.5 Three wiring choices

Choice Taken Reason
Mesh mode lookup, not discovery Every peer address is already chain state, genesis data, or chainspec data, so address gossip has nothing to solve
Exporter operator API gRPC, not stream::encrypted The API needs service framing, reflection, and browser clients
storage::queue Single-reader durable queue behind the exporter's publication drain and the event outbox Per-consumer cursors are kept by consumers against the re-derivable stored log

The queue choice is already covered in section 3.3 and section 4, which assign the byte bound, the certified gap choice, artifact idempotence, and the exporter watermark to the Finalized export module rather than to Commonware. The mesh choice is expanded, with the channel plan and peer-set ownership, in section 8 of operations.md.

10.6 Storage decision table

Each store was chosen for one job. This table is the decision; the specification carries the rules. It is new to this document: section 2 assigns module ownership and section 4 assigns Commonware seams, but neither records why a store was chosen or what was rejected.

Store Holds Backing Why this one Rejected
Validity state every record execution reads or writes: accounts, keys, projects, slug claims, refs, roles, offers, usernames, credit frontiers, schedules QMDB current::unordered::variable, header state_root plus state_target authenticated key-value store with a bitmap of active operations, so current-state inclusion and activeness are provable; unordered because no validity rule needs an exclusion proof and the ordered variant adds a next-key link per active key; variable values avoid padding every small record to the largest metadata or schedule record ordered QMDB, whose cost has no consumer; a fourth database for query indexes, because derived views do not enter a root
Permanent membership log one leaf per commitment published to a project, forever QMDB keyless::fixed full variant, header membership_target append-only, keyless, fixed 32-byte leaves, constant RAM at any size; a location in the log is a stable witness a client can cite; one committed floor, so all roles share one root while nodes prune bytes below it and the store keeps them keeping memberships in validity state, because the index grows without bound; merging with block history, because the lifetimes and proof shapes differ
Block-history accumulator one leaf per block, linking parent height and hash QMDB keyless, compact on every node role, reconstructed in full in the store, header history_target gives a logarithmic ancestry proof, so a client can prove finality of any height from one later certificate; the compact form keeps every node's cost constant and moves the full log off the nodes entirely header-chain walks, which have no worst-case bound under Simplex's transitive finalization
Command root one leaf per command of one block, in execution order, each the Keccak256 of that command's canonical signed envelope stateless BMT over Keccak256, header command_root inclusion proof for "these bytes were finalized at this height" with no database folding commands into a persistent log, which the membership log and the store already cover
Blocks and certificates bodies, profile-permitted DKG payloads, finalization certificates marshal store::Certificates over archive::prunable on validators and the exporter, bounded by retained_marshal_blocks Commonware's own ordering store; every node keeps a bounded window, and the exporter's durable queue holds a block until the store and the mirror have it validators as long-term block servers, whose disk use is unbounded
Watermarks and crash recovery per-member commit metadata, publication watermarks storage::metadata, glue's per-member durability barriers, and SyncPlan target reconciliation recovery is owned by glue, not by an application journal an application-level commit journal
Stored blocks and operation logs every finalized block, its certificate, and that block's slices of both operation logs two copies written from the exporter's queue: the exoware store (exoware-simplex, exoware-qmdb, exoware-sql behind exoware-server on a RocksDB backend), and a mirror bucket of raw per-block objects content-addressed by block_hash with a height index, a watermark, and a retention lock exoware persists the Merkle nodes as ranges arrive and serves historical roots and proofs at any size, so no Makechain prover exists; either copy rebuilds the other; anyone can mirror a Makechain-written prover over a bucket alone, which would have to reproduce the keyless operation encoding byte for byte
History query tier append-only history tables of blocks, commands, events, publications, memberships, commits, refs, roles, keys, usernames, credits and the validator schedule exoware-sql in the same store, keyed tables with native secondary indexes under a versioned schema prefix, written by the exporter in each block's upload batch one SQL surface over rows that arrive atomically with the block they describe, so an answer bounded by the published watermark is consistent without snapshot isolation; off the validators entirely, and rebuildable from the mirror by a deterministic projection a bespoke read RPC surface on gateways; an indexer with its own database and pipeline, which would need a second durable copy and its own recovery; a columnar dataset built for analytics at launch, which is deferred until a product needs it
Objects the bytes a commitment names mkit stores behind a project's availability layers, addressed by (scheme_id, native_id) out of consensus by design: the chain commits identities and the layers hold bytes under the stated obligations of availability-profile.md; a project may have several layers, announced off chain storing objects on chain

Two consequences follow.

  • A validator's history retention is bounded, while its footprint grows with funded resident state. Ordinary account-created records are paid for at creation, deposited families carry a deposit that deletion returns, state creation is rate-limited per block, the membership log is windowed, block bodies are pruned, and the accumulator is compact.
  • Every service outside the core is a projection. Gateways, indexers, and query engines can be wrong or malicious without affecting what the chain attests, which is why the specification defines proof kinds for the facts that matter. This restates design rule 5 in section 1 from the storage side.

The selected object-store backend for the first shared devnet, and its create-if-absent adapter contract, remain in section 3.2 of operations.md; the table above states the store class, not the vendor.

10.7 Execution-host adapter contracts

Three contracts sit between the executor and the pinned Commonware adapters. They are implementation guidance in form, and the first two are root-affecting or liveness-affecting in effect, so they are recorded rather than left to reading the adapter source.

Staged current-state reads. CurrentStaged::expand neither deduplicates earlier keys nor observes values computed for staged slots but not yet passed to merkleize. The Makechain overlay therefore owns both deduplication and command-visible writes, and expands staging only for previously unread keys. Its stable staged indices and final writes are submitted together at block merkleization. Violating either half changes which operations reach merkleize, and therefore the committed state_root. Sections 2 and 3 already assign typed reads and staged writes for validity state to the state adapter, and section 4 names glue/src/stateful/db/current.rs; the expansion rule itself is new to this document.

Lock discipline. No code holds a shared read guard across a batch operation that reacquires the same database, because the write-preferring lock deadlocks when finalization intervenes. New to this document.

Bootstrap handles. Bootstrap handles are dropped before the execution host opens the members. Already covered in section 3.1, whose genesis database handoff applies the batch, awaits the durability handle, drops the handle, and reopens the member before Stateful or a network actor starts.

10.8 Fixed-profile stack composition

Section 6 already covers the accepted fixed-profile decision, its epoch-zero guards, and the absence of a continuous reshare actor. The component inventory below completes it by naming what FixedEpochZeroV1 does not assemble.

FixedEpochZeroV1 retains Random V1 with rotating terms, marshal::standard::Deferred, stateful::Stateful, the same three-member database set, executor, journal, durability barriers, proofs, the exporter, and recovery paths. It has none of:

  • a bootstrap DKG chain;
  • an epoch orchestrator;
  • a reshare wrapper or actor;
  • a DKG probe or DKG state-sync plan;
  • a dynamic registrar;
  • a dealer or reveal channel;
  • future-player activation;
  • a DKG SecretStore.

The DKG state-sync plan, the fence, and the gate exist only under DynamicReshareV1, where they are separate from the application SyncPlan so that a state-synced node keeps certified epoch information the application sync may skip. Already covered in section 4 (the reshare and DKG seam) and section 5 (the DKG custody partition, via operations.md section 2.1). The absence list is new to this document.