Correctness invariants
The node-level claims that still hold on the node runtime. Each entry names
the check that enforces it after every simulated step (Sources/LatticeNodeSim)
or the test that pins it. The consensus invariants (weighed graph, executed
set, GHOST, continuity) are the architecture doc’s and are checked by
Invariants.checkTree and LevelInvariants.checkLevel.
NODE-SEMANTICS-003 — availability is retriable, not punishable
Section titled “NODE-SEMANTICS-003 — availability is retriable, not punishable”- NODE-SEMANTICS-003.a — Content that cannot be resolved is no verdict:
the block parks and its body is asked for again after a backoff; it is
never excluded. Enforced by
Invariants.checkTree(“excludes …, ground truth …”: only invalid bodies are excluded) andSimBodies.checkBodies(every window block is asked for or parked, a parked body has a wake). - NODE-SEMANTICS-003.b — A missing body, header or proof blames no peer;
a stall frees the slot. Enforced by the simulators’ “disconnected honest
peer” check (
Simulator,LevelSimulator), with withholders and lossy links in every run. - NODE-SEMANTICS-003.c — A child block whose parent state its parent
level has not executed waits, unvalidated, and wakes when it is.
Enforced by
LevelInvariants.checkExecutionStop(a stop is only at a block awaiting a fact its parent lacks; a held fact is a lost wake). - NODE-SEMANTICS-003.d — A node-local failure while executing is
retriable, never an exclusion. Pinned by
ChainCoreBodyTests.testALocalFailureIsNeverAnExclusion.
NODE-SEMANTICS-005 — only obtained invalid evidence is punishable
Section titled “NODE-SEMANTICS-005 — only obtained invalid evidence is punishable”- NODE-SEMANTICS-005.a — Only a proof-of-work failure blames: a header
whose own work fails, or a peer-sent child proof that does not verify.
Enforced by the simulators’ “disconnected honest peer” check and the
liar scripts (
LevelSimulationTests.testAZeroWorkProofIsNeverWeighedAndItsSenderIsBlamed). - NODE-SEMANTICS-005.b — Everything else malformed is dropped without
blame, including a child genesis spec that is not the one it names and a
proof check the shell cannot run. Pinned by
ChildGenesisSpecTests.
NODE-STORAGE-002 — content is stored before the facts that name it, and a fact never depends on it being held
Section titled “NODE-STORAGE-002 — content is stored before the facts that name it, and a fact never depends on it being held”- NODE-STORAGE-002.a — A step’s content (headers, post-states, specs)
is stored and retained before the facts that name it. Enforced by
SimBodies.checkStatesStoredandInvariants.checkTree(“weighed block … has no durable content”). - NODE-STORAGE-002.b — Nothing is published, served, relayed or
streamed before it is durable. Enforced by
SimulatorandLevelSimulator(“published tip … is not durable”, “served … before it was durable”, “relayed … before it was durable”). - NODE-STORAGE-002.c — Content stays because a scope names it, and a
start leaves pins as it finds them: nothing is rebuilt from the journal.
A block’s body is named by that block on its chain, what executions read
and create by the chain. A start sweeps what no scope names. Pinned by
RetentionRulesTests,ChildLevelRestartTests.testAStartKeepsWhatAScopeNamesAndDropsTheRest,ChildLevelRestartTests.testAWeighedUnexecutedChildGenesisSurvivesARestartandNodeRuntimeTests.testJoinerSyncsHeadersAndExecutesBodiesOverLoopbackIvy. - NODE-STORAGE-002.f — Content a fact names and the store lacks is no
fault. The node starts on its facts, with the Nexus genesis block stored
again; executing a block and building on one read this store, a block’s
header record, then peers, checked against the CID; what peers served
reaches the Volume store only as the Volumes this node derives when it
stores a block, and only once the block’s execution found it valid (a
fetched body is read into memory until then, and read again whole from
peers if memory let it go); retaining a root that is gone retains the rest. The checks anyone
can cause (a submitted transaction, a public read) read this store alone.
Pinned by
AbsentContentTestsandSafetyNetCorruptStoreTests.testBootOpensAStoreWhoseVolumesAreGone. - NODE-STORAGE-002.g — With
blockBodies: nonethe node lets go of a body it executed once another block is its chain’s tip, and never of a genesis block. A tip the chain moves back onto after its body went is not fetched again. Transactions of the blocks a move leaves are returned to the pool from this store, and from peers for a body it let go of; one no peer serves is not returned. State and facts are untouched, and the node builds on a block whose body is gone. Pinned byBlockBodiesTests. - NODE-STORAGE-002.h — With
state: tipthe node keeps the state each chain’s tip is made of. A node of the state is named by its content and can be named from several places: the node counts, for each, the nodes of the tip’s state that name it, walking the new tip’s state down to what is already counted and the last one down to what is still named, and lets go of a node nothing names. The walk reads this store alone and runs in the step that stored the tip; what that step’s executions stored is named by its own scope until then. The state scope names exactly what is counted. A node of the tip’s state the store lacks is not counted. A run on another setting drops the counts, and the next run ontipcounts afresh and lets go of what an earlier one left pinned. Pinned byStateTipTests. - NODE-STORAGE-002.i — With
state: tipornonewhat a stored block reads is named by that block until it executes or is found invalid (a start lets go of what an executed block’s scope still names); withnonethe state scope names only what the last execution of its chain touched. Pinned byStateTipTests.testANodeOnNoneSyncsAndKeepsValidatingHoldingNoState. - NODE-STORAGE-002.j — A Volume the operator pins is named by the
operator scope until it is unpinned, whatever the other rules keep. Pinned
by
OperatorPinTestsandDaemonHTTPTests.testOperatorPinRoutes. - NODE-STORAGE-002.d — Levels write parent before child; a crash
between them restores with the child behind, never ahead. Pinned by
ChildLevelRestartTests.testACrashBetweenLevelWritesRestoresTheParentAhead. - NODE-STORAGE-002.e — Replaying the store reproduces the trees.
Enforced by
Simulator.checkReplayandLevelSimulator.checkReplay.
NODE-MEMPOOL-001 — the mempool is tip-relative, not consensus
Section titled “NODE-MEMPOOL-001 — the mempool is tip-relative, not consensus”- NODE-MEMPOOL-001.a — Templates and preflights build on the executed
tip, never a heavier weighed one. Enforced by
TxWorkload.checkInvariants(“mining builds on a tip that is not the executed tip”) and the template check (“template issued off the executed tip”). - NODE-MEMPOOL-001.b — A pool entry already on the executed chain is
removed. Enforced by
TxWorkload.checkInvariants(“pool holds …, already on the executed chain”). - NODE-MEMPOOL-001.c — The pool holds one transaction per first signer’s nonce
and stays within its limits. Enforced by
TxWorkload.checkInvariants. - NODE-MEMPOOL-001.d — The local journal is the pool’s local set, and a
pool change is durable before any later effect. Enforced by
TxWorkload.checkOrderandTxWorkload.checkInvariants(“journal … diverged”). - NODE-MEMPOOL-001.e — A transaction goes to the pool of the chain it
names. Pinned by
MergedMiningTests.testOneGrindAdvancesNexusAndItsHostedChild.
Source: lattice-node/docs/correctness-invariants.md at 9abd15b1bb05