fix(zakura): only advance and gossip NewBlocks that land on the best chain#478
fix(zakura): only advance and gossip NewBlocks that land on the best chain#478p0mvn wants to merge 1 commit into
Conversation
|
Note Complete: Audit complete. V12 did not find any issues that need review. Open the full results here. Analyzed five files, diff |
|
Fleet soak interim report: a natural one-block min-difficulty fork hit at 4145550 ( The event did surface two adjacent issues (both pre-existing, now documented for follow-up): (1) with every zakura peer's header frontier pinned on the same abandoned block, no peer advertises a higher tip, so the #476 walk-back gets no non-linking evidence — recovery needs at least one honest-frontier peer; (2) the #474 dual-stack watchdog then correctly fell all 5 dual-stack nodes back to legacy, which (being one-way) killed the fleet's zakura layer until staggered restarts, starving the zakura-only node. Reversible fallback and reanchoring the header frontier onto the verified body chain on divergence are the proposed next fixes. |
…chain An accepted NewBlock could have committed to a side chain; advancing the header/verified frontiers and forwarding it made the whole Zakura layer follow and propagate losing branches (e.g. testnet min-difficulty forks) while each node's own chain stayed honest, stranding zakura-only peers. The driver now checks the committed hash against the best chain (ReadRequest::Depth) and routes side-chain accepts to a dedup-only event.
fff1e47 to
d5f0456
Compare
7fe1a93 to
1aa8ad6
Compare
Motivation
An inbound Zakura
NewBlockthat the block pipeline accepts can have committed to a side chain (contextually valid, lower work — e.g. a testnet min-difficulty branch).handle_new_block_acceptedstill advanced the node's header and verified frontiers and forwarded the block to every peer with a lower advertised tip, without checking which chain the block landed on. The result, observed live on the zakura testnet fleet: all 5 dual-stack fleet nodes advertised and re-forwarded a min-difficulty branch over Zakura (statuses at 4145079 on the losing branch) while their own chains stayed honest via legacy sync (4145205) — and the zakura-only node that trusted the gossip followed the losing branch end-to-end and stranded (recovered by #476, but the gossip layer should not propagate losing branches in the first place). This was discovered while validating #476 and is recorded as the follow-up bug there.Solution
After the verifier accepts a
NewBlock, the zebrad driver checks the committed hash against the best chain withReadRequest::Depth(which answersSomeonly for best-chain blocks, so it also covers a reorg the block just won):NewBlockAcceptedadvances the frontiers and forwards to eligible peers.HeaderSyncEvent::NewBlockAcceptedSideChain: the reactor remembers the hash for dedup only — no frontier advance, no height-covered marking, no forwarding. Counted insync.header.tip.new_block.side_chainand traced with reasonside_chain.Read failures are conservatively treated as side-chain: the node's own frontier still advances through the chain-tip mirror, so a false negative only skips one gossip forward, while a false positive would gossip a possibly losing branch.
Tests
new_block_side_chain_commit_does_not_advance_header_frontierspawns a real Zakura endpoint with the header-sync driver, feedsNewBlockReceivedactions through the real driver with a mocked verifier/state, and asserts that aDepth = Noneaccept leaves the header frontier untouched while aDepth = Someaccept advances it.accepted_side_chain_new_block_is_deduped_without_advancing_or_forwarding— a side-chain accept forwards nothing, advances nothing, publishes no tip, and its hash still dedups a later wireNewBlockwithout scoring the sender.cargo fmt,cargo clippy --all-targets,cargo test -p zebra-network --lib(897 passed),-p zebrad --lib zakura(53 passed) all pass.d57970e2…), all healthy and hash-equal at the tip; a soak monitor is armed on the fleet for the next naturally occurring min-difficulty branch, watching theside_chaincounter, header-vs-body frontier divergence, and strand recurrence on the zakura-only node (these branches occurred twice in the prior 4 hours, stranding the zakura-only node both times; with the gate the fleet should not follow or forward the next one). Will report the soak outcome on this PR.Follow-up Work
AI Disclosure
PR Checklist
type(scope): description