aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/blockchain.go5
-rw-r--r--core/blockchain_test.go46
2 files changed, 51 insertions, 0 deletions
diff --git a/core/blockchain.go b/core/blockchain.go
index 59be35589..361fa8243 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -1742,6 +1742,11 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
canonical := bc.GetBlockByNumber(number)
if canonical != nil && canonical.Hash() == block.Hash() {
// Not a sidechain block, this is a re-import of a canon block which has it's state pruned
+
+ // Collect the TD of the block. Since we know it's a canon one,
+ // we can get it directly, and not (like further below) use
+ // the parent and then add the block on top
+ externTd = bc.GetTd(block.Hash(), block.NumberU64())
continue
}
if canonical != nil && canonical.Root() == block.Root() {
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index 27115af52..db624c4dc 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -2241,3 +2241,49 @@ func BenchmarkBlockChain_1x1000Executions(b *testing.B) {
}
benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn)
}
+
+// Tests that importing a some old blocks, where all blocks are before the
+// pruning point.
+// This internally leads to a sidechain import, since the blocks trigger an
+// ErrPrunedAncestor error.
+// This may e.g. happen if
+// 1. Downloader rollbacks a batch of inserted blocks and exits
+// 2. Downloader starts to sync again
+// 3. The blocks fetched are all known and canonical blocks
+func TestSideImportPrunedBlocks(t *testing.T) {
+ // Generate a canonical chain to act as the main dataset
+ engine := ethash.NewFaker()
+ db := rawdb.NewMemoryDatabase()
+ genesis := new(Genesis).MustCommit(db)
+
+ // Generate and import the canonical chain
+ blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, nil)
+ diskdb := rawdb.NewMemoryDatabase()
+ new(Genesis).MustCommit(diskdb)
+ chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
+ if err != nil {
+ t.Fatalf("failed to create tester chain: %v", err)
+ }
+ if n, err := chain.InsertChain(blocks); err != nil {
+ t.Fatalf("block %d: failed to insert into chain: %v", n, err)
+ }
+
+ lastPrunedIndex := len(blocks) - TriesInMemory - 1
+ lastPrunedBlock := blocks[lastPrunedIndex]
+
+ // Verify pruning of lastPrunedBlock
+ if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) {
+ t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64())
+ }
+ firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory]
+ // Verify firstNonPrunedBlock is not pruned
+ if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) {
+ t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64())
+ }
+ // Now re-import some old blocks
+ blockToReimport := blocks[5:8]
+ _, err = chain.InsertChain(blockToReimport)
+ if err != nil {
+ t.Errorf("Got error, %v", err)
+ }
+}