fix(network): seed fork filter from DB head and update on each canonical block#341
fix(network): seed fork filter from DB head and update on each canonical block#341chee-chyuan wants to merge 1 commit into
Conversation
…cal block The network's fork filter was initialized from a hardcoded block number baked into BscChainSpec::head() rather than the actual canonical head from the database. This caused every peer handshake to fail with a fork ID mismatch once the chain advanced past that hardcoded block, draining all peers and stalling block sync until the node was restarted. Two fixes: - Use ctx.head() (DB-sourced) instead of ctx.chain_spec().head() (hardcoded) when building the NetworkConfig, aligning with how upstream reth initialises the fork filter. - Call network_handle.update_status() after every successful update_forkchoice() in ImportService (both incoming and mined blocks), so the fork filter stays current as hardforks activate at runtime. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pull Request ReviewThis PR fixes fork-ID desynchronization in the BSC network layer by initializing the network head from the database-backed canonical head ( Sensitive ContentNo sensitive content detected. Security IssuesNo serious security issues detected. Generated by Hashdit Bot. This tool can absolutely NOT replace manual audits. |
| timestamp: header.timestamp, | ||
| difficulty: header.difficulty, | ||
| total_difficulty: td, | ||
| }); |
There was a problem hiding this comment.
https://github.com/bnb-chain/reth/blob/develop/crates/node/builder/src/launch/engine.rs#L447
There is a update_status in the Reth engine, that is not work?
| .ok() | ||
| .flatten() | ||
| .unwrap_or_default(); | ||
| net.update_status(Head { |
Fixes #335
Root cause
BscNetworkBuilderwas initialising the network's fork filter from a hardcoded block number baked intoBscChainSpec::head()(block 40,000,000 on mainnet) rather than the actual canonical head read from the database.The fork ID is a hash of which hardforks are active at a given block height. When the node advertises a fork ID computed from block 40M to peers who know it is actually at block ~95M, every peer handshake fails with
fork id mismatchand the peer is disconnected. Once all peers are gone, block sync stalls entirely. A restart temporarily re-establishes connections until the same thing recurs.A second related issue:
ImportServicenever callednetwork_handle.update_status()after importing blocks, so even if startup worked, the fork filter would go stale the moment a hardfork timestamp was crossed at runtime.Fix
src/node/network/mod.rsReplace
ctx.chain_spec().head()(hardcoded) withctx.head()(DB-sourced) when building theNetworkConfig. This is exactly what upstream reth does —ctx.head()is populated from the database bylookup_head()beforeBuilderContextis constructed, so the fork filter is seeded correctly from the first handshake.src/node/network/block_import/service.rsCall
network_handle.update_status(head)after every successfulupdate_forkchoice()inImportService— both for incoming network blocks and locally mined blocks. This keeps the fork filter current as the chain advances and hardforks activate, mirroring theChainEvent-drivenupdate_statusloop in upstream reth's engine launcher.Testing
cargo checkpasses cleanly