-
Notifications
You must be signed in to change notification settings - Fork 23
test: add invalidate fork testcases #399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7e8dc2c
b266d24
fe707c5
f8119a7
174eba5
4760e68
a62a6c1
56dc403
859fe6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1422,6 +1422,10 @@ func (b *BlockAssembler) getMiningCandidate() (*model.MiningCandidate, []*subtre | |
| // Returns: | ||
| // - error: Any error encountered during reorganization | ||
| func (b *BlockAssembler) handleReorg(ctx context.Context, header *model.BlockHeader, height uint32) error { | ||
| if err := ctx.Err(); err != nil { | ||
| return errors.NewProcessingError("context", err) | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Context cancellation check added but reorg work continues The early context cancellation check at line 1425 is good defensive programming. However, if the context is cancelled during reorg processing (e.g., in the middle of fetching block headers or updating subtrees), the cleanup operations may be left incomplete. Consider: Does the reorg logic handle partial state correctly if cancelled midway? The error handling returns early, but are there any state mutations that should be rolled back?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why was this added? Should this not be taken care of the for/select where handleReorg is called? |
||
|
|
||
| startTime := time.Now() | ||
|
|
||
| prometheusBlockAssemblerReorg.Inc() | ||
|
|
@@ -1567,44 +1571,47 @@ func (b *BlockAssembler) getReorgBlockHeaders(ctx context.Context, header *model | |
| // are necessarily going to be on the same height | ||
|
|
||
| baBestBlockHeader, baBestBlockHeight := b.CurrentBlock() | ||
| startingHeight := height | ||
| if baBestBlockHeader == nil { | ||
| return nil, nil, errors.NewProcessingError("best block header is nil, reorg not possible") | ||
icellan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| if height > baBestBlockHeight { | ||
| startingHeight = baBestBlockHeight | ||
| startingHeight := baBestBlockHeight | ||
| if height < startingHeight { | ||
| startingHeight = height | ||
| } | ||
|
|
||
| // Get block locator for current chain | ||
| currentChainLocator, err := b.blockchainClient.GetBlockLocator(ctx, baBestBlockHeader.Hash(), startingHeight) | ||
| if err != nil { | ||
| return nil, nil, errors.NewServiceError("error getting block locator for current chain", err) | ||
| return nil, nil, errors.NewServiceError("error getting current chain block locator", err) | ||
| } | ||
|
|
||
| // Get block locator for the new best block | ||
| newChainLocator, err := b.blockchainClient.GetBlockLocator(ctx, header.Hash(), startingHeight) | ||
| if err != nil { | ||
| return nil, nil, errors.NewServiceError("error getting block locator for new chain", err) | ||
| return nil, nil, errors.NewServiceError("error getting new chain block locator", err) | ||
| } | ||
|
|
||
| // Find common ancestor using locators | ||
| var ( | ||
| commonAncestor *model.BlockHeader | ||
| commonAncestorMeta *model.BlockHeaderMeta | ||
| ) | ||
| newChainLocatorSet := make(map[chainhash.Hash]struct{}, len(newChainLocator)) | ||
| for _, h := range newChainLocator { | ||
| newChainLocatorSet[*h] = struct{}{} | ||
| } | ||
|
|
||
| var commonAncestorHash *chainhash.Hash | ||
| for _, currentHash := range currentChainLocator { | ||
| for _, newHash := range newChainLocator { | ||
| if currentHash.IsEqual(newHash) { | ||
| commonAncestor, commonAncestorMeta, err = b.blockchainClient.GetBlockHeader(ctx, currentHash) | ||
| if err != nil { | ||
| return nil, nil, errors.NewServiceError("error getting common ancestor header", err) | ||
| } | ||
|
|
||
| goto FoundAncestor | ||
| } | ||
| if _, ok := newChainLocatorSet[*currentHash]; ok { | ||
| commonAncestorHash = currentHash | ||
| break | ||
| } | ||
| } | ||
|
|
||
| FoundAncestor: | ||
| if commonAncestorHash == nil { | ||
| return nil, nil, errors.NewProcessingError("common ancestor not found, reorg not possible") | ||
| } | ||
|
|
||
| commonAncestor, commonAncestorMeta, err := b.blockchainClient.GetBlockHeader(ctx, commonAncestorHash) | ||
| if err != nil { | ||
| return nil, nil, errors.NewServiceError("error getting common ancestor header", err) | ||
| } | ||
|
|
||
| if commonAncestor == nil || commonAncestorMeta == nil { | ||
| return nil, nil, errors.NewProcessingError("common ancestor not found, reorg not possible") | ||
| } | ||
|
|
@@ -1654,7 +1661,7 @@ FoundAncestor: | |
| maxGetReorgHashes := b.settings.BlockAssembly.MaxGetReorgHashes | ||
| if len(filteredMoveBack) > maxGetReorgHashes { | ||
| currentHeader, currentHeight := b.CurrentBlock() | ||
| b.logger.Errorf("reorg is too big, max block reorg: current hash: %s, current height: %d, new hash: %s, new height: %d, common ancestor hash: %s, common ancestor height: %d, move down block count: %d, move up block count: %d, current locator: %v, new block locator: %v", currentHeader.Hash(), currentHeight, header.Hash(), height, commonAncestor.Hash(), commonAncestorMeta.Height, len(filteredMoveBack), len(moveForwardBlockHeaders), currentChainLocator, newChainLocator) | ||
| b.logger.Errorf("reorg is too big, max block reorg: current hash: %s, current height: %d, new hash: %s, new height: %d, common ancestor hash: %s, common ancestor height: %d, move down block count: %d, move up block count: %d", currentHeader.Hash(), currentHeight, header.Hash(), height, commonAncestor.Hash(), commonAncestorMeta.Height, len(filteredMoveBack), len(moveForwardBlockHeaders)) | ||
| return nil, nil, errors.NewProcessingError("reorg is too big, max block reorg: %d", maxGetReorgHashes) | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comprehensive nightly test workflow
The new workflow adds important long-running integration testing with 3 concurrent block generators. Key features:
Minor suggestions: