feat(state): authenticate VCT-fast blocks from the successor header#355
feat(state): authenticate VCT-fast blocks from the successor header#355p0mvn wants to merge 1 commit into
Conversation
And one more auto-invalidated finding. Analyzed 21 files, diff |
The finalized committer authenticates a verified-commitment-trees fast block's peer-supplied note-commitment roots against its successor's header commitment. Previously it waited for the successor block *body* to be buffered; since header sync runs far ahead of the body frontier, that coupled the committer to the body-download pipeline and could deadlock at a checkpoint/VCT boundary (the writer holds block N awaiting N+1's body, while N+1's body cannot be applied until N commits). Authenticate against the already-committed successor *header* instead. At NU5+ the successor's `hashBlockCommitments` binds the MMR root together with the successor's own ZIP-244 auth-data root, so that auth-data root is carried per-height over header sync and stored in the serving index, letting the committer verify without the successor body. Propagation: - carry `auth_data_root` in `BlockCommitmentRoots` (wire) and the `commitment_roots_by_height` serving-index value (64->96 bytes, backward compatible), consolidated under state DB format 27.3.0; - bump the Zakura header-sync stream format to v5 (breaking wire change). Consumption: - extract a header-driven `header_commitment_is_valid_for_chain_history` core; the block-based check delegates to it (behavior preserved); - `CommitmentRootVerification::header_only` becomes body-free (header + height + auth-data root); - the writer sources the successor from the buffered look-ahead or the committed header chain, and only waits at the genuine header tip.
9c7e198 to
cbc7d22
Compare
Motivation
The Zakura finalized-block committer deadlocks at a checkpoint / verified-commitment-trees (VCT) boundary. A VCT-fast block's peer-supplied note-commitment roots are authenticated against the next block's header commitment, but the committer waited for the successor block body to be buffered. Since header sync runs far ahead of the body frontier, this coupled the committer to the body-download pipeline: the writer holds block N awaiting N+1's body, while N+1's body cannot be applied until N commits — a circular wait (observed frozen for hours at height 1,709,217 on a benchmark node).
Solution
Authenticate against the already-committed successor header instead of its body.
At NU5+ the successor's
hashBlockCommitmentsbinds the chain-history (MMR) root together with the successor's own ZIP-244auth_data_root, so that root is needed as a co-input. It is now:BlockCommitmentRootsover header sync, and stored in thecommitment_roots_by_heightserving-index value (64→96 bytes, backward compatible — old rows decode with a zero root and fall back to the body-wait path). Consolidated under state DB format27.3.0(no version bump). Carrying it bumps the Zakura header-sync stream format to v5 — a breaking wire change (all peers must run the new format).header_commitment_is_valid_for_chain_historycore is extracted (the block-based check delegates to it, behavior preserved);CommitmentRootVerification::header_onlyis now body-free; the writer sources the successor from the buffered look-ahead or the committed header chain (successor_header_auth_for), and only waits at the genuine header tip.Test evidence
cargo check --workspace --testsclean; clippy + fmt clean on touched crates.header_only_successor_confirms_and_rejects_wrong_rootproves the body-free path confirms real roots and rejects wrong ones from the successor header alone.zebra-chainserialization round-trip (non-zero auth-data root) + 85header_syncwire tests + rollback/serve-index tests pass.verifies_real_nu5_range_over_synced_forkscan be run against 1.7M snapshot forks (VCT_SEED_DB/VCT_ARCHIVE_DB) for real-data confidence before deploy.Merge plan
This is the full feature branch. The network-breaking auth-root propagation (the data-model/wire/storage/serve half, without the consensus-bearing committer/verifier changes) is split into a separate PR to merge first; this PR should then be rebased down to just the consensus consumption.
AI disclosure
Implemented with Claude Code (Opus). Scope: the deadlock investigation, the design, and the full implementation + tests in this PR. The contributor is the responsible author.