12. Execution and block validity
This chapter states what decides whether a block is valid: the order its commands execute in, what a failed command contributes, which header fields a verifier re-derives, and which inputs may reach that decision at all. It also fixes the three outcomes a node may produce, so that a local failure is never mistaken for a verdict about the chain.
Admission and mempool policy, sync and recovery procedure, and readiness reporting are local policy and are specified in operations. The assurance layers are specified in validation.
12.1 Definitions
A rules executor is the single component that executes a block's commands, used unchanged by proposing, verifying, and applying. A candidate is one command a proposer or verifier executes. A change set is the isolated set of writes, ledger deltas, membership appends, and event data a candidate produces. The block overlay is the block-local ordered view that accumulates the change sets of successful candidates. Flat order is the strict per-block sequence of commands that defines the result of executing a block.
12.2 Flat order and the block overlay
R-12.1. Flat-order semantics define the result of executing a block, and launch execution is serial.
R-12.2. One rules executor serves propose, verify, and apply, and reads through the block overlay, so each command observes the effects of earlier successful commands in the same block.
R-12.3. A candidate's change set merges into the block overlay only after all of that candidate's checks succeed, and a failed candidate contributes no writes, no ledger deltas, no membership appends, and no event data.
R-12.4. Resource reservations for included commands never shrink, and a proposer's local work budget still accounts for failed attempts.
R-12.5. Membership locations are assigned in final flat execution order, excluding discarded candidates.
R-12.6. Each database member is merkleized once per block after command execution, with one commit operation and the prescribed metadata and floor (section 9).
R-12.7. Gross record creations, charges, deposit locks, deposit discharges, and event data are accumulated from the logical command transitions and MUST NOT be inferred from the final database diff, because the database may collapse repeated writes to a key to its final value.
A create and delete pair within one block therefore leaves no resident key and still consumes a creation reservation and a creation fee (section 10).
12.3 What makes a block valid
R-12.8. A block is valid only if every command in it is valid, and one deterministically invalid command makes its block invalid.
R-12.9. A proposer executes candidates while building the block, an honest proposer excludes an invalid candidate rather than proposing it, and a proposer MAY discard a failed candidate and continue building.
R-12.10. A verifier re-executes the block rather than trusting the proposer's result, and MUST reject the whole block if any command in it fails.
R-12.11. The shared execution path used by propose, verify, and apply checks every Makechain
commitment, including the canonical state_root, because the glue wrapper's own check covers only
the ops target.
R-12.12. Validity is derived from the canonical bytes, the parent state, chain_id, the active
release, and finalized settlement inputs, and from no other input.
R-12.13. An invalid command changes nothing, emits nothing, and charges nothing, while a finalized command applies its complete transition.
A verifier also re-derives every header field and rejects any mismatch (section 11). Three further
properties of a valid block are stated where they are defined: INV-STATE-11 and INV-STATE-07 in
section 9, and INV-CONS-04 in section 10.
INV-CONS-01. Every validator derives identical validity from canonical bytes, parent state,
chain_id, the active release, and finalized settlement inputs.
INV-CONS-03. A finalized command applies its complete transition; an invalid command changes, emits, and charges nothing and invalidates its block.
12.4 Fault outcomes and inputs that are not validity
Every failure a node encounters while handling a block is exactly one of three outcomes.
| Outcome | Meaning | Node behaviour |
|---|---|---|
| Permanent invalidity | the block or command is invalid under the rules at this height | reject |
| Transient local inability | this node cannot decide now, for example because an eligible source is momentarily unreadable | stay pending rather than vote |
| Fatal local corruption | this node's own storage or state is unusable | stop and recover |
R-12.14. A node MUST classify every failure as exactly one of those three outcomes, and a storage or dependency failure MUST NOT become a vote.
R-12.15. The availability of the bytes an object names MUST NOT be an input to command or block validity, and object unavailability after publication changes nothing about a finalized fact (section 15).
A wrong witness is permanent invalidity and an unavailable eligible source is transient inability, and neither is ever nonmembership (section 8).
INV-FAULT-01. Every failure is exactly one of permanent invalidity, transient inability, or fatal corruption; a storage or dependency failure is never a vote.
INV-FAULT-04. Object unavailability never changes validity after publication.
12.5 Bounded read and write sets
A command's read and write set is bounded by its payload limits plus the state-derived expansions below, so worst-case work is known before execution.
| Source | Additional records that may be read or written |
|---|---|
| Actor and root witness | actor ledger, AccountRoot, delegated key |
| Project operation | Project and its counters, ProjectMetadata, actor's current role, target role, ref, and offer records |
| Slug rename or transfer | old and proposed SlugClaim keys derived from current metadata and the destination, and the named offer destination |
| Deposited record deletion or replacement | each raw record's stored deposit-payer AccountLedger, even when different from the signer |
| Username operation | requested and current name leases, and the actor's and prior owner's AccountUsername pointers, counters, and cooldown metadata |
| Reclaim | the raw target, its parent AccountRoot or Project for the stale predicate, any matching old username pointer, and the stored payer ledger |
| Settlement or governance | SettlementAnchor, the proved beneficiary ledger, the protocol schedule and parameters, and the bounded entries named by the transition |
R-12.16. Every expansion is charged at its worst-case multiplicity before execution (section 10).
R-12.17. Repeated keys share one overlay entry and accumulate all deltas rather than overwriting
an earlier command's effects, and a read-then-write path uses the current adapter's staged reads,
so a key is resolved once from the underlying branch view.
R-12.18. The block overlay owns both deduplication and command-visible writes, expands staging
only for previously unread keys, and submits its stable staged indices and final writes together at
block merkleization, because CurrentStaged::expand neither deduplicates earlier keys nor observes
values computed for staged slots but not yet passed to merkleize.
R-12.19. A raw resident read preserves the record's deposit metadata and incarnation, and an effective read interprets time, control generation, and delegation epoch without mutating a record.
R-12.20. No handler may add a scan or an unbounded dependency.
R-12.21. Parallel lanes are permitted only where this set proves independence, including for shared refund ledgers and parent allocation counters, and must be result-equivalent to flat order (section 4).
The state machine companion provides the exact per-variant keys, multiplicities, guards, and write order for these categories.
12.6 The application contract
The application implements the execution host's contract. Only the parts that constrain agreement are stated here.
R-12.22. verify is concurrent, fork-scoped, and cancellable, has no durable side effects, and
stays pending for a transient inability (section 12.4).
R-12.23. apply reconstructs both uncertified ancestors during lazy recovery and finalized
winners, has no durable side effects, and returns None for a deterministic execution or commitment
failure, which makes the execution host reject the dependent ancestry.
R-12.24. Storage corruption during apply is fatal-local rather than a None result, and failure
to reconstruct a finalized winner is fatal.
R-12.25. capture stays cheap, and finalized is idempotent under redelivery, returns promptly
after handing off bounded owned data, and MUST NOT wait on its own height's acknowledgement, which
is released only after the hook resolves. The one exception to returning promptly is an exporter's
finalized hook at its publication-queue bound, which waits for queue space under R-17.10; that
wait MUST depend only on the drain releasing lower heights, never on the execution host's serial
path or on any marshal acknowledgement, and it holds back only that exporter's own following.
R-12.26. Every applied height is covered by a successful database-set durability barrier before its ordering acknowledgement is released, and one barrier may cover several heights (section 17).
R-12.27. 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.
12.7 Admission, the vote gate, and recovery
R-12.28. Admission is local policy and never changes validity, and block execution is the only authority on validity.
R-12.29. A validator MUST NOT vote before the readiness checklist holds:
a. chainspec and namespace agreement;
b. release support;
c. clock bound;
d. the profile-required threshold share;
e. all three member targets equal at one certified anchor and the canonical state_root equal to
the header's;
f. p2p ceiling;
g. journal integrity.
R-12.30. Recovery MUST NOT edit the consensus journal.
A state-invalid command that reaches a block is rejected there, so an admission error is advisory. Admission responses, pool policy, gateway fan-out and acknowledgement, startup and bootstrap procedure, the two supported recovery procedures, and the observability surface are specified in operations.
12.8 Rationale
This subsection is informative.
The proposer executes while building and the verifier re-executes rather than trusting, so nothing admission decides can affect validity, and admission work is kept off the consensus executor because competing with voting is the failure mode that appears under load. Failures are split into three outcomes because a storage read error that became a vote would convert one node's local problem into a claim about the chain.
Accounting is taken from logical transitions rather than from the final database diff because the store may collapse repeated writes, which would hide a create and delete pair that consumed a creation reservation. Flat order defines the result, and parallel lanes are an implementation strategy that must produce the same result.