fix(blockchain): reject blocks too far in future before pending storage#324
fix(blockchain): reject blocks too far in future before pending storage#324MegaRedHand wants to merge 1 commit intomainfrom
Conversation
Adds a parent-independent future-slot check in `BlockChainServer::process_or_pend_block` so blocks whose start interval is more than `GOSSIP_DISPARITY_INTERVALS` ahead of local time are dropped before the parent-state lookup. Mirrors the bound used by `validate_attestation_data`: an interval-based margin (not a whole-slot one), since a slot-wide tolerance would let an adversary pre-publish next-slot blocks ahead of any honest proposer. Without this check, a peer could flood pending pre-genesis-future blocks that would (a) get persisted to RocksDB as pending and (b) trigger BlocksByRoot fan-out for fabricated parent roots.
🤖 Kimi Code ReviewThe change adds a critical DoS protection against future-block spam and aligns block validation with the existing attestation time checks. The logic is sound and the implementation is memory-safe. Minor suggestion: Line 430: Consider using if block_start_interval > store_time.saturating_add(GOSSIP_DISPARITY_INTERVALS) {Security/Logic verification:
The change looks correct and ready for merge. Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
🤖 Claude Code ReviewNow I have all the context needed. Let me write the review. PR Review:
|
🤖 Codex Code Review
Aside from those points, the intent of the change is reasonable: rejecting fabricated future blocks before DB writes/fetch fan-out is a good defensive goal. I couldn’t run Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
Greptile SummaryThis PR adds an interval-based future-slot guard in Confidence Score: 4/5Safe to merge; the guard is logically correct, consistently mirrors the pre-existing attestation check, and touches only the orchestration layer with no spec-test impact. No P0 or P1 issues found. The single change is a focused 21-line guard that reuses an established pattern (same interval arithmetic and same constants used in No files require special attention.
|
| Filename | Overview |
|---|---|
| crates/blockchain/src/lib.rs | Adds a 21-line future-slot guard before the pending-block persist path; logic is correct and mirrors the pre-existing validate_attestation_data pattern. Minor: store_time + GOSSIP_DISPARITY_INTERVALS is a plain (non-saturating) add, consistent with the existing attestation check. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[process_or_pend_block] --> B{slot ≤ finalized_slot?}
B -- yes --> C[discard_pending_subtree\nreturn]
B -- no --> D{block_start_interval >\nstore_time + GOSSIP_DISPARITY?\nNEW}
D -- yes --> E[warn! log\ndiscard_pending_subtree\nreturn]
D -- no --> F{parent state\nmissing?}
F -- yes --> G[insert_pending_block\nto RocksDB\ntrack in-memory]
F -- no --> H[process_block\nfork-choice update]
Reviews (1): Last reviewed commit: "fix(blockchain): reject blocks too far i..." | Re-trigger Greptile
Summary
Adds a parent-independent future-slot check in
BlockChainServer::process_or_pend_blockso blocks whose start interval is more thanGOSSIP_DISPARITY_INTERVALSahead of local time are dropped before the parent-state lookup.Mirrors the bound used by
validate_attestation_data(leanSpec PR #682): an interval-based margin (not a whole-slot one), since a slot-wide tolerance would let an adversary pre-publish next-slot blocks ahead of any honest proposer.Motivation
Today, the only slot-based gate on incoming blocks is
slot <= finalized_slot. There is no upper bound, so a peer can flood blocks at arbitrary future slots and force us to:insert_pending_block(since the fabricated parent state will be missing).BlocksByRootrequests for the fabricated parent roots, fanning out to peers.The new check rejects these at the orchestration layer (
BlockChainServer) before any disk write or network request.on_block_coreis intentionally untouched: spec tests drivestore::on_block_*directly with arbitraryon_tickadvancements, and we don't want a wall-clock gate at that layer.Behavior
block_start_interval = slot * INTERVALS_PER_SLOTis the interval at which the block's slot begins. Tolerance isGOSSIP_DISPARITY_INTERVALS = 1(~800 ms), matching the attestation bound.Test plan
make fmtcleanmake lintclean (cargo clippy --workspace --all-targets -- -D warnings)cargo test --workspace --releasefrom this change (the 8 fixture failures inforkchoice_spectestspre-exist onmainafter fix: tighten attestation future-slot bound (leanSpec #682) #317 and are unrelated).warn!.