core: sorted reorg insertion order for proper head header updating
This commit is contained in:
		
							parent
							
								
									02aeb3d766
								
							
						
					
					
						commit
						84be009154
					
				| @ -465,7 +465,7 @@ func (bc *BlockChain) insert(block *types.Block) { | |||||||
| 	} | 	} | ||||||
| 	bc.currentBlock = block | 	bc.currentBlock = block | ||||||
| 
 | 
 | ||||||
| 	// If the block is better than out head or is on a different chain, force update heads
 | 	// If the block is better than our head or is on a different chain, force update heads
 | ||||||
| 	if updateHeads { | 	if updateHeads { | ||||||
| 		bc.hc.SetCurrentHeader(block.Header()) | 		bc.hc.SetCurrentHeader(block.Header()) | ||||||
| 
 | 
 | ||||||
| @ -1140,18 +1140,17 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error { | |||||||
| 	} else { | 	} else { | ||||||
| 		log.Error("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "newnum", newBlock.Number(), "newhash", newBlock.Hash()) | 		log.Error("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "newnum", newBlock.Number(), "newhash", newBlock.Hash()) | ||||||
| 	} | 	} | ||||||
|  | 	// Insert the new chain, taking care of the proper incremental order
 | ||||||
| 	var addedTxs types.Transactions | 	var addedTxs types.Transactions | ||||||
| 	// insert blocks. Order does not matter. Last block will be written in ImportChain itself which creates the new head properly
 | 	for i := len(newChain) - 1; i >= 0; i-- { | ||||||
| 	for _, block := range newChain { |  | ||||||
| 		// insert the block in the canonical way, re-writing history
 | 		// insert the block in the canonical way, re-writing history
 | ||||||
| 		bc.insert(block) | 		bc.insert(newChain[i]) | ||||||
| 		// write lookup entries for hash based transaction/receipt searches
 | 		// write lookup entries for hash based transaction/receipt searches
 | ||||||
| 		if err := WriteTxLookupEntries(bc.chainDb, block); err != nil { | 		if err := WriteTxLookupEntries(bc.chainDb, newChain[i]); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		addedTxs = append(addedTxs, block.Transactions()...) | 		addedTxs = append(addedTxs, newChain[i].Transactions()...) | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	// calculate the difference between deleted and added transactions
 | 	// calculate the difference between deleted and added transactions
 | ||||||
| 	diff := types.TxDifference(deletedTxs, addedTxs) | 	diff := types.TxDifference(deletedTxs, addedTxs) | ||||||
| 	// When transactions get deleted from the database that means the
 | 	// When transactions get deleted from the database that means the
 | ||||||
|  | |||||||
| @ -1197,3 +1197,51 @@ func TestEIP161AccountRemoval(t *testing.T) { | |||||||
| 		t.Error("account should not exist") | 		t.Error("account should not exist") | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // This is a regression test (i.e. as weird as it is, don't delete it ever), which
 | ||||||
|  | // tests that under weird reorg conditions the blockchain and its internal header-
 | ||||||
|  | // chain return the same latest block/header.
 | ||||||
|  | //
 | ||||||
|  | // https://github.com/ethereum/go-ethereum/pull/15941
 | ||||||
|  | func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { | ||||||
|  | 	// Generate a canonical chain to act as the main dataset
 | ||||||
|  | 	engine := ethash.NewFaker() | ||||||
|  | 
 | ||||||
|  | 	db, _ := ethdb.NewMemDatabase() | ||||||
|  | 	genesis := new(Genesis).MustCommit(db) | ||||||
|  | 	blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) | ||||||
|  | 
 | ||||||
|  | 	// Generate a bunch of fork blocks, each side forking from the canonical chain
 | ||||||
|  | 	forks := make([]*types.Block, len(blocks)) | ||||||
|  | 	for i := 0; i < len(forks); i++ { | ||||||
|  | 		parent := genesis | ||||||
|  | 		if i > 0 { | ||||||
|  | 			parent = blocks[i-1] | ||||||
|  | 		} | ||||||
|  | 		fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) | ||||||
|  | 		forks[i] = fork[0] | ||||||
|  | 	} | ||||||
|  | 	// Import the canonical and fork chain side by side, verifying the current block
 | ||||||
|  | 	// and current header consistency
 | ||||||
|  | 	diskdb, _ := ethdb.NewMemDatabase() | ||||||
|  | 	new(Genesis).MustCommit(diskdb) | ||||||
|  | 
 | ||||||
|  | 	chain, err := NewBlockChain(diskdb, params.TestChainConfig, engine, vm.Config{}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("failed to create tester chain: %v", err) | ||||||
|  | 	} | ||||||
|  | 	for i := 0; i < len(blocks); i++ { | ||||||
|  | 		if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { | ||||||
|  | 			t.Fatalf("block %d: failed to insert into chain: %v", i, err) | ||||||
|  | 		} | ||||||
|  | 		if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { | ||||||
|  | 			t.Errorf("block %d: current block/header mismatch: block #%d [%x…], header #%d [%x…]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) | ||||||
|  | 		} | ||||||
|  | 		if _, err := chain.InsertChain(forks[i : i+1]); err != nil { | ||||||
|  | 			t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) | ||||||
|  | 		} | ||||||
|  | 		if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { | ||||||
|  | 			t.Errorf(" fork %d: current block/header mismatch: block #%d [%x…], header #%d [%x…]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user