pub trait DerivedStateAgreesWithCertifiedPrefix:
AdmissionChecksTheValidityProof
+ StorageAtomicity
+ MaxByzantineWeight { }Expand description
Invariant (Derived state agrees with the certified prefix). The parts of a chain’s state that are not certified — the block-height indexes, the outbox counters and queues, the inbox cursors — are functions of that chain’s committed blocks, and equal the value that recomputing them from those blocks would give.
This is the class with no validity proof. A wrong index or a wrong counter is not detectable by rehashing or by re-verifying signatures, because nobody attested it and nothing determines it but the computation that produced it. It can only be recomputed. That is why this is stated as an invariant over transitions rather than as a property a reader can check.
Proof. Each is written only by the transition that commits a block, under the exclusive access
of SequentialChainState and the atomicity of StorageAtomicity, so the sequence of values
it takes follows the sequence of committed blocks; and by
linera_chain::manager::proof::safety::UniqueChain that sequence is unique. The base case is an
empty chain, where every one of these is empty or zero. ∎
Detection is partial, late, and by assertion. Because there is no proof to check, the
implementation catches violations only where a reader happens to require an entry that should be
there. ChainError::CorruptedChainState is raised at seven sites in linera_chain::chain,
including:
"message counter should be present"— an outbox counter missing for a queue entry;"Missing outboxes"— anonempty_outboxesentry with no outbox behind it;"missing entry in block_hashes", at three separate call sites — the height index short of the tip.
Each fires at the point of use, which may be arbitrarily long after the write that broke the invariant, and none of them fires for a value that is present but wrong. A counter that is merely too small is not detected at all until the queue drains past it.
Recovery is by recomputation, which is the only option available. reconcile_tracked_outboxes
rebuilds the outbox index, and ChainStateView::restore_outboxes_from_unfinalized rebuilds
outboxes, outbox_counters and nonempty_outboxes from the on-chain
unfinalized_message_blocks after a checkpoint bootstrap. Both are re-derivations from data that
does have a validity proof, which is what makes them trustworthy where the derived state was
not.
Not covered here. Fields with no invariant at all, because they are legitimately local and
may differ between correct validators or be dropped without fault: pending_proposed_blobs and
pending_validated_blobs (cleared when the manager is reset), pre_checkpoint_block_trust
(transient, emptied as the certificates arrive), and received_log, whose order depends on when
certificates were received rather than on what was committed.