feat: validated chunk cache#16070
Draft
viviveevee wants to merge 24 commits into
Draft
Conversation
added 24 commits
July 13, 2026 09:19
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #16070 +/- ##
==========================================
+ Coverage 73.19% 73.25% +0.05%
==========================================
Files 856 856
Lines 188394 188682 +288
Branches 188394 188682 +288
==========================================
+ Hits 137904 138212 +308
+ Misses 46070 46050 -20
Partials 4420 4420
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Today a partial encoded chunk cannot have its header signature verified when it arrives, because resolving the chunk producer requires the chunk's parent block, which frequently hasn't been processed yet (chunk parts routinely beat their block through the network). The pipeline copes with a two-stage validation:
validate_chunk_header_preliminaryat arrival checks onlyshard_id/protocol_versionand skips the signature, thenvalidate_chunk_header_fullchecks the signature later once the parent lands.This PR verifies the signature by carrying the grandparent block hash (the "anchor", offset 2) and the chunk's own
epoch_idin a new chunk-header version, so the producer can be resolved and the signature verified at arrival without the parent — mirroring the existing state-witness V2 design (PartialEncodedStateWitnessV2already carriesprev_prev_block_hashand verifies viaresolve_anchored_producer/verify_anchored_chunk_key).All of this gates on the existing
EarlyKickoutprotocol feature (v152, nightly).What changed
New chunk header version (V7)
ShardChunkHeaderInnerV7=ShardChunkHeaderInnerV5fields plusprev_prev_block_hash: CryptoHashandepoch_id: EpochId(core/primitives/src/sharding/shard_chunk_header_inner.rs).V7(...) = 6, all accessor match arms, and two newOption-returning accessorsprev_prev_block_hash()/epoch_id()(Nonefor V1–V6). OuterShardChunkHeadergets matching accessors.EarlyKickoutinShardChunkHeaderV3::new;grandparent_hash+epoch_idare threaded throughShardChunkWithEncoding::new(5 call sites; genesis/tests pass defaults).validate_versiongains the V7 arm.Arrival-time verification (
chain/chunks/src/shards_manager_actor.rs)validate_chunk_header_preliminary: for V7 headers, resolve the producer from the header's anchor +epoch_id, run theverify_anchored_chunk_keycross-check, and verify the signature at arrival — before caching or forwarding parts. If the anchor is unprocessed, the chunk is dropped (not cached, not forwarded), making the effective front horizon 2 whileMAX_HEIGHTS_AHEADstays 5.epoch_idis not trusted — it is an index disciplined by the signature: a forgedepoch_idresolves the wrong producer, whose key the sender doesn't hold, so the signature fails and the chunk is dropped. As hardening, the header'sepoch_idis additionally bounded to the plausible epochs for its height (possible_epochs_of_height_around_tip), matching the witness path, to prevent a validator assigned in another epoch from racing out the real chunk via height/shard dedup near a boundary.validate_chunk_header_fullis left as-is: it already re-resolves from the now-processed parent and is a genuine no-op re-check for V7 (and remains the authoritative backstop).Shared anchored-producer helpers
resolve_anchored_producer,verify_anchored_chunk_key, and theresolve_and_verify_anchored_producerwrapper moved fromchain/client/src/stateless_validation/validate.rs(witness-only) tochain/chain/src/signature_verification.rsso chunks and witnesses share one implementation. They take amsg_labelfor caller-named errors; theANCHORED_CHUNK_PRODUCER_LOOKUP_TOTALmetric moved to chain metrics.RPC / view surface (
core/primitives/src/views.rs)ChunkHeaderViewgainsprev_prev_block_hashandepoch_idasOption+#[serde(default)]fields (byte-identical for pre-V7). ForwardFrompopulates them from the new accessors; the reverseFromgets a V7 arm keyed on their presence, placed before the V5 arm (V5 and V7 share the same field-presence tuple — without it the reverse impl would silently downgrade V7 to V5 with a differentchunk_hash).openapi.json,openrpc.json) and the protocol-schema snapshot regenerated.Tests
test_bad_signature_chunk_rejected_at_arrival— a pushed V7 chunk with an invalid producer signature is rejected in preliminary validation and never cached.test_v7_mismatched_height_rejected_at_arrival— a validly-signed V7 chunk whose height ≠parent.height + 1is rejected by the anchored key cross-check.test_cached_bad_chunk_evicted_by_full_validation— a chunk with a misstatedepoch_iddeposited directly into the cache is evicted by full validation (the backstop).early_kickout_boundary(test-loop, nightly) — a live 3-producer/3-shard chain upgrades across theEarlyKickoutboundary; asserts liveness across the seam, no missing chunks in steady state (a verification gap would drop valid V7 chunks), and each block's header version matches its epoch's protocol version.verify_anchored_chunk_keyedge-case coverage (genesis / genesis+1, skipped heights, parent-present vs parent-absent).Notes for reviewers
EarlyKickout= 152); no stable behavior changes.get_chunk_producer_info_anchored+verify_anchored_chunk_key; keep them in lockstep with the kickout aggregator.