You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When multiple peers advertised the same gossiped block, the node previously kept only the first advertiser. A malicious first advertiser could race honest peers, then timeout or return malformed data, causing the gossip download to fail even though other peers had also advertised the block.
This PR cleanly ports the original Zebra fix onto Zakura's security-ports branch.
Solution
Record bounded fallback advertisers for active gossiped block downloads.
Retry eligible source failures with the next fallback source.
Avoid fallback retries for consensus-invalid matching blocks, including production-shaped verifier router errors.
Add regression tests for fallback retry after malformed data and no retry after consensus-invalid data.
Adapt the source patch's crate references to Zakura's renamed crates.
The fallback path lets a block hash be retried indefinitely because it tracks only the current active source and the currently queued fallback deque. After a non-consensus failure, poll_next pops one fallback and respawns the same hash without recording that the previous source has already been tried or decrementing a per-hash attempt budget. While the fallback source is active, the previously failed source is no longer active and no longer present in the fallback deque, so another duplicate advertisement from that source is accepted again. Two malicious peers can therefore alternate malformed responses and re-advertisements to keep the same hash in pending for as long as they keep the sequence going. With enough hashes, this keeps the inbound download queue at capacity and causes later honest block advertisements to be rejected as FullQueue.
Fallback retry classification is based only on verifier error types, so deterministic local validation failures are retried from every recorded alternate advertiser. The download task performs several pre-verifier checks after requesting and accepting a matching block body, including the coinbase-height presence check and the behind-tip / ahead-of-tip height bounds. These failures are returned as ordinary boxed string errors rather than as VerifyBlockError or RouterError::Block. A Sybil can advertise the same far-ahead or otherwise locally rejected hash through the active source and up to eight fallback sources, and each source can serve the same block body. The node downloads and rechecks the same deterministic failure for each fallback even though no peer can make that block acceptable at the current tip.
A malicious first advertiser can make a valid block hash look globally invalid by serving a block with the requested header hash but a corrupted body. The download task only checks block.hash() == hash before sending the full block to the verifier, and Block::hash() hashes the header rather than the transaction list. The transaction body is bound to the header later by the verifier’s Merkle-root check. If the attacker returns the real header with mutated transactions, the verifier rejects the body as a block verification error. The new retry policy treats every VerifyBlockError and every RouterError::Block as globally consensus-invalid, so it skips recorded honest fallback advertisers that could have supplied the valid body for the same hash.
Router-wrapped consensus errors bypass retry and scoring logic
Inbound download error handling is inconsistent with the router’s wrapped verifier errors. The router surfaces consensus failures as RouterError::Block and RouterError::Checkpoint, but downstream logic still assumes failures will either be a bare VerifyBlockError or, in the retry classifier, only the Block wrapper. As a result, Inbound::poll_ready skips misbehavior accounting for router-wrapped failures instead of unwrapping them and applying their misbehavior_score(). For checkpoint-range blocks, the omission is worse because is_consensus_invalid_block_error() does not recognize RouterError::Checkpoint, so invalid checkpoint blocks are treated as retryable and can be fetched again from fallbacks. The implementation needs a shared unwrapping/classification path for both router variants so retry suppression and peer scoring use the same consensus-error view.
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
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.
Motivation
When multiple peers advertised the same gossiped block, the node previously kept only the first advertiser. A malicious first advertiser could race honest peers, then timeout or return malformed data, causing the gossip download to fail even though other peers had also advertised the block.
This PR cleanly ports the original Zebra fix onto Zakura's
security-portsbranch.Solution
Tests
cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warningscargo test -p zakura components::inboundSpecifications & References
valargroup/zebra:codex/inbound-block-fallbacks0171eb9a4916a91a0617005617991f872579c43dFollow-up Work
None.
AI Disclosure
PR Checklist
type(scope): description.