fix(consensus/XDPoS): stabilize batch header ancestor resolution#2187
fix(consensus/XDPoS): stabilize batch header ancestor resolution#2187gzliudan wants to merge 2 commits intoXinFinOrg:dev-upgradefrom
Conversation
…sion, close XFN-12 Problem - Mixed v1/v2 header batches around the switch boundary caused ambiguous verification flow and error attribution. - Early failures could leave unnecessary verification work running without explicit batch-level stop coverage. Fix - Split header verification into contiguous consensus-version batches in core import paths. - Keep strict mixed-batch rejection in XDPoS adaptor as a defensive guard (ErrMixedConsensusBatch). - Restore explicit abort propagation in blockchain batch verification loop. - Add empty-chain guard in HeaderChain.ValidateHeaderChain. Tests - Add consensus batch split unit tests for zero/single/multi/mixed v1-v2 scenarios. - Add adaptor test for mixed-batch rejection. - Add abort regression tests to ensure second batch does not start and first-batch trailing results are not emitted after abort.
Add a batch-aware verifyChainReader for XDPoS VerifyHeaders so deep consensus lookups can read in-flight headers before they are persisted to disk. This prevents transient unknown-ancestor failures during sync, including v2 paths that query headers/blocks by hash and number (for example HookPenalty and QC processing). Also add unit tests that verify batch shadowing for GetHeader/GetHeaderByHash/GetHeaderByNumber/GetBlock and fallback-to-underlying-reader behavior.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR aims to eliminate transient unknown ancestor / missing-parent failures during XDPoS batch header verification by making consensus lookups batch-aware (so in-flight headers can be resolved before being persisted), and by adjusting verification to operate on consensus-version-consistent batches.
Changes:
- Add an XDPoS
verifyChainReaderthat shadowsChainReaderlookups with headers/blocks from the current verify batch. - Split header verification into contiguous consensus-version batches in
HeaderChain.ValidateHeaderChainandBlockChain.insertChain. - Add unit tests for batch splitting and for the new chain-reader shadowing + abort behavior across batches.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| core/headerchain.go | Validate headers in per-consensus batches and handle empty input safely. |
| core/blockchain.go | Wrap header verification to run per-consensus batches during block import. |
| core/consensus_batch.go | Add helper to split contiguous headers by consensus version. |
| core/consensus_batch_test.go | Unit tests for consensus batch splitting. |
| core/headerchain_validation_test.go | Regression test: empty header chain validation should succeed. |
| core/blockchain_abort_test.go | Tests for abort propagation and ensuring later batches don’t start after early failure. |
| consensus/XDPoS/verify_chain_reader.go | New batch-shadowing ChainReader for deterministic in-flight ancestor lookups. |
| consensus/XDPoS/XDPoS.go | Use batch-shadow reader and introduce mixed-batch handling behavior. |
| consensus/XDPoS/XDPoS_test.go | Tests for mixed-batch behavior and chain-reader shadow/fallback behavior. |
| consensus/tests/engine_v2_tests/verify_header_test.go | Update tests to respect per-consensus batching expectations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| for _, batch := range splitHeadersByConsensusVersion(hc.config, chain) { | ||
| abort, results := hc.engine.VerifyHeaders(hc, chain[batch.start:batch.end], seals[batch.start:batch.end]) | ||
| for i := batch.start; i < batch.end; i++ { | ||
| header := chain[i] | ||
| // If the chain is terminating, stop processing blocks | ||
| if hc.procInterrupt() { | ||
| close(abort) | ||
| log.Debug("Premature abort during headers verification") | ||
| return 0, errors.New("aborted") | ||
| } | ||
| // If the header is a banned one, straight out abort | ||
| if BadHashes[header.Hash()] { | ||
| close(abort) | ||
| return i, ErrDenylistedHash | ||
| } | ||
| // Otherwise wait for headers checks and ensure they pass | ||
| if err := <-results; err != nil { | ||
| close(abort) | ||
| return i, err | ||
| } | ||
| } | ||
| close(abort) | ||
| } |
| results := make(chan error, len(headers)) | ||
| go func() { | ||
| for _, batch := range splitHeadersByConsensusVersion(bc.chainConfig, headers) { | ||
| batchAbort, batchResults := bc.engine.VerifyHeaders(bc, headers[batch.start:batch.end], seals[batch.start:batch.end]) | ||
| stopped := false |
| x.EngineV1.VerifyHeaders(verifyReader, v1headers, v1fullVerifies, abort, results) | ||
| case v1Count == 0 && v2Count != 0: | ||
| x.EngineV2.VerifyHeaders(verifyReader, v2headers, v2fullVerifies, abort, results) | ||
| case v1Count != 0 && v2Count != 0: | ||
| go func() { | ||
| for range headers { | ||
| select { | ||
| case <-abort: | ||
| return | ||
| case results <- ErrMixedConsensusBatch: | ||
| } | ||
| } | ||
| }() | ||
| return abort, results |
|
fixed by #2139 |
Proposed changes
fix
Error: unknown ancestorduring sync.Add a batch-aware verifyChainReader for XDPoS VerifyHeaders so deep consensus lookups can read in-flight headers before they are persisted to disk. This prevents transient unknown-ancestor failures during sync, including v2 paths that query headers/blocks by hash and number (for example HookPenalty and QC processing).
Also add unit tests that verify batch shadowing for GetHeader/GetHeaderByHash/GetHeaderByNumber/GetBlock and fallback-to-underlying-reader behavior.
error message:
Types of changes
What types of changes does your code introduce to XDC network?
Put an
✅in the boxes that applyImpacted Components
Which parts of the codebase does this PR touch?
Put an
✅in the boxes that applyChecklist
Put an
✅in the boxes once you have confirmed below actions (or provide reasons on not doing so) that