Skip to content

Commit b0b67be

Browse files
all: remove forkchoicer and reorgNeeded (#29179)
This PR changes how sidechains are handled. Before the merge, it was possible to import a chain with lower td and not set it as canonical. After the merge, we expect every chain that we get via InsertChain to be canonical. Non-canonical blocks can still be inserted with InsertBlockWIthoutSetHead. If during the InsertChain, the existing chain is not canonical anymore, we mark it as a sidechain and send the SideChainEvents normally.
1 parent dfd33c7 commit b0b67be

36 files changed

+185
-354
lines changed

cmd/utils/cmd.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,6 @@ func ImportHistory(chain *core.BlockChain, db ethdb.Database, dir string, networ
262262
start = time.Now()
263263
reported = time.Now()
264264
imported = 0
265-
forker = core.NewForkChoice(chain, nil)
266265
h = sha256.New()
267266
buf = bytes.NewBuffer(nil)
268267
)
@@ -305,7 +304,7 @@ func ImportHistory(chain *core.BlockChain, db ethdb.Database, dir string, networ
305304
if err != nil {
306305
return fmt.Errorf("error reading receipts %d: %w", it.Number(), err)
307306
}
308-
if status, err := chain.HeaderChain().InsertHeaderChain([]*types.Header{block.Header()}, start, forker); err != nil {
307+
if status, err := chain.HeaderChain().InsertHeaderChain([]*types.Header{block.Header()}, start); err != nil {
309308
return fmt.Errorf("error inserting header %d: %w", it.Number(), err)
310309
} else if status != core.CanonStatTy {
311310
return fmt.Errorf("error inserting header %d, not canon: %v", it.Number(), status)

cmd/utils/flags.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2210,7 +2210,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
22102210
}
22112211
}
22122212
// Disable transaction indexing/unindexing by default.
2213-
chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil, nil)
2213+
chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil)
22142214
if err != nil {
22152215
Fatalf("Can't create BlockChain: %v", err)
22162216
}

cmd/utils/history_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func TestHistoryImportAndExport(t *testing.T) {
7878
})
7979

8080
// Initialize BlockChain.
81-
chain, err := core.NewBlockChain(db, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
81+
chain, err := core.NewBlockChain(db, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
8282
if err != nil {
8383
t.Fatalf("unable to initialize chain: %v", err)
8484
}
@@ -171,7 +171,7 @@ func TestHistoryImportAndExport(t *testing.T) {
171171
})
172172

173173
genesis.MustCommit(db2, triedb.NewDatabase(db, triedb.HashDefaults))
174-
imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
174+
imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
175175
if err != nil {
176176
t.Fatalf("unable to initialize chain: %v", err)
177177
}

consensus/clique/clique_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func TestReimportMirroredState(t *testing.T) {
5555
copy(genspec.ExtraData[extraVanity:], addr[:])
5656

5757
// Generate a batch of blocks, each properly signed
58-
chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genspec, nil, engine, vm.Config{}, nil, nil)
58+
chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genspec, nil, engine, vm.Config{}, nil)
5959
defer chain.Stop()
6060

6161
_, blocks, _ := core.GenerateChainWithGenesis(genspec, engine, 3, func(i int, block *core.BlockGen) {
@@ -87,7 +87,7 @@ func TestReimportMirroredState(t *testing.T) {
8787
}
8888
// Insert the first two blocks and make sure the chain is valid
8989
db = rawdb.NewMemoryDatabase()
90-
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil, nil)
90+
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil)
9191
defer chain.Stop()
9292

9393
if _, err := chain.InsertChain(blocks[:2]); err != nil {
@@ -100,7 +100,7 @@ func TestReimportMirroredState(t *testing.T) {
100100
// Simulate a crash by creating a new chain on top of the database, without
101101
// flushing the dirty states out. Insert the last block, triggering a sidechain
102102
// reimport.
103-
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil, nil)
103+
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil)
104104
defer chain.Stop()
105105

106106
if _, err := chain.InsertChain(blocks[2:]); err != nil {

consensus/clique/snapshot_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ func (tt *cliqueTest) run(t *testing.T) {
458458
batches[len(batches)-1] = append(batches[len(batches)-1], block)
459459
}
460460
// Pass all the headers through clique and ensure tallying succeeds
461-
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil)
461+
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil)
462462
if err != nil {
463463
t.Fatalf("failed to create test chain: %v", err)
464464
}

core/bench_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
195195

196196
// Time the insertion of the new chain.
197197
// State and blocks are stored in the same DB.
198-
chainman, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
198+
chainman, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
199199
defer chainman.Stop()
200200
b.ReportAllocs()
201201
b.ResetTimer()
@@ -312,7 +312,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
312312
if err != nil {
313313
b.Fatalf("error opening database at %v: %v", dir, err)
314314
}
315-
chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
315+
chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
316316
if err != nil {
317317
b.Fatalf("error creating chain: %v", err)
318318
}

core/block_validator_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func testHeaderVerification(t *testing.T, scheme string) {
5050
headers[i] = block.Header()
5151
}
5252
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
53-
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
53+
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
5454
defer chain.Stop()
5555

5656
for i := 0; i < len(blocks); i++ {
@@ -160,7 +160,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
160160
postHeaders[i] = block.Header()
161161
}
162162
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
163-
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
163+
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
164164
defer chain.Stop()
165165

166166
// Verify the blocks before the merging

core/blockchain.go

+27-80
Original file line numberDiff line numberDiff line change
@@ -259,15 +259,14 @@ type BlockChain struct {
259259
validator Validator // Block and state validator interface
260260
prefetcher Prefetcher
261261
processor Processor // Block transaction processor interface
262-
forker *ForkChoice
263262
vmConfig vm.Config
264263
logger *tracing.Hooks
265264
}
266265

267266
// NewBlockChain returns a fully initialised block chain using information
268267
// available in the database. It initialises the default Ethereum Validator
269268
// and Processor.
270-
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis, overrides *ChainOverrides, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(header *types.Header) bool, txLookupLimit *uint64) (*BlockChain, error) {
269+
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis, overrides *ChainOverrides, engine consensus.Engine, vmConfig vm.Config, txLookupLimit *uint64) (*BlockChain, error) {
271270
if cacheConfig == nil {
272271
cacheConfig = defaultCacheConfig
273272
}
@@ -312,7 +311,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
312311
return nil, err
313312
}
314313
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
315-
bc.forker = NewForkChoice(bc, shouldPreserve)
316314
bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb)
317315
bc.validator = NewBlockValidator(chainConfig, bc)
318316
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
@@ -1243,13 +1241,6 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
12431241

12441242
// Rewind may have occurred, skip in that case.
12451243
if bc.CurrentHeader().Number.Cmp(head.Number()) >= 0 {
1246-
reorg, err := bc.forker.ReorgNeeded(bc.CurrentSnapBlock(), head.Header())
1247-
if err != nil {
1248-
log.Warn("Reorg failed", "err", err)
1249-
return false
1250-
} else if !reorg {
1251-
return false
1252-
}
12531244
rawdb.WriteHeadFastBlockHash(bc.db, head.Hash())
12541245
bc.currentSnapBlock.Store(head.Header())
12551246
headFastBlockGauge.Update(int64(head.NumberU64()))
@@ -1548,42 +1539,30 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
15481539
return NonStatTy, err
15491540
}
15501541
currentBlock := bc.CurrentBlock()
1551-
reorg, err := bc.forker.ReorgNeeded(currentBlock, block.Header())
1552-
if err != nil {
1553-
return NonStatTy, err
1554-
}
1555-
if reorg {
1556-
// Reorganise the chain if the parent is not the head block
1557-
if block.ParentHash() != currentBlock.Hash() {
1558-
if err := bc.reorg(currentBlock, block); err != nil {
1559-
return NonStatTy, err
1560-
}
1542+
1543+
// Reorganise the chain if the parent is not the head block
1544+
if block.ParentHash() != currentBlock.Hash() {
1545+
if err := bc.reorg(currentBlock, block); err != nil {
1546+
return NonStatTy, err
15611547
}
1562-
status = CanonStatTy
1563-
} else {
1564-
status = SideStatTy
15651548
}
1549+
15661550
// Set new head.
1567-
if status == CanonStatTy {
1568-
bc.writeHeadBlock(block)
1569-
}
1570-
if status == CanonStatTy {
1571-
bc.chainFeed.Send(ChainEvent{Block: block, Hash: block.Hash(), Logs: logs})
1572-
if len(logs) > 0 {
1573-
bc.logsFeed.Send(logs)
1574-
}
1575-
// In theory, we should fire a ChainHeadEvent when we inject
1576-
// a canonical block, but sometimes we can insert a batch of
1577-
// canonical blocks. Avoid firing too many ChainHeadEvents,
1578-
// we will fire an accumulated ChainHeadEvent and disable fire
1579-
// event here.
1580-
if emitHeadEvent {
1581-
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
1582-
}
1583-
} else {
1584-
bc.chainSideFeed.Send(ChainSideEvent{Block: block})
1551+
bc.writeHeadBlock(block)
1552+
1553+
bc.chainFeed.Send(ChainEvent{Block: block, Hash: block.Hash(), Logs: logs})
1554+
if len(logs) > 0 {
1555+
bc.logsFeed.Send(logs)
15851556
}
1586-
return status, nil
1557+
// In theory, we should fire a ChainHeadEvent when we inject
1558+
// a canonical block, but sometimes we can insert a batch of
1559+
// canonical blocks. Avoid firing too many ChainHeadEvents,
1560+
// we will fire an accumulated ChainHeadEvent and disable fire
1561+
// event here.
1562+
if emitHeadEvent {
1563+
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
1564+
}
1565+
return CanonStatTy, nil
15871566
}
15881567

15891568
// InsertChain attempts to insert the given batch of blocks in to the canonical
@@ -1634,7 +1613,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
16341613
if bc.insertStopped() {
16351614
return 0, nil
16361615
}
1637-
16381616
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
16391617
SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number(), chain[0].Time()), chain)
16401618

@@ -1667,24 +1645,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
16671645
// 2. The block is stored as a sidechain, and is lying about it's stateroot, and passes a stateroot
16681646
// from the canonical chain, which has not been verified.
16691647
// Skip all known blocks that are behind us.
1670-
var (
1671-
reorg bool
1672-
current = bc.CurrentBlock()
1673-
)
1648+
current := bc.CurrentBlock()
16741649
for block != nil && bc.skipBlock(err, it) {
1675-
reorg, err = bc.forker.ReorgNeeded(current, block.Header())
1676-
if err != nil {
1677-
return it.index, err
1678-
}
1679-
if reorg {
1680-
// Switch to import mode if the forker says the reorg is necessary
1681-
// and also the block is not on the canonical chain.
1682-
// In eth2 the forker always returns true for reorg decision (blindly trusting
1683-
// the external consensus engine), but in order to prevent the unnecessary
1684-
// reorgs when importing known blocks, the special case is handled here.
1685-
if block.NumberU64() > current.Number.Uint64() || bc.GetCanonicalHash(block.NumberU64()) != block.Hash() {
1686-
break
1687-
}
1650+
if block.NumberU64() > current.Number.Uint64() || bc.GetCanonicalHash(block.NumberU64()) != block.Hash() {
1651+
break
16881652
}
16891653
log.Debug("Ignoring already known block", "number", block.Number(), "hash", block.Hash())
16901654
stats.ignored++
@@ -2006,9 +1970,8 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
20061970
// insertSideChain is only used pre-merge.
20071971
func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (int, error) {
20081972
var (
2009-
externTd *big.Int
2010-
lastBlock = block
2011-
current = bc.CurrentBlock()
1973+
externTd *big.Int
1974+
current = bc.CurrentBlock()
20121975
)
20131976
// The first sidechain block error is already verified to be ErrPrunedAncestor.
20141977
// Since we don't import them here, we expect ErrUnknownAncestor for the remaining
@@ -2059,22 +2022,6 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
20592022
"txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()),
20602023
"root", block.Root())
20612024
}
2062-
lastBlock = block
2063-
}
2064-
// At this point, we've written all sidechain blocks to database. Loop ended
2065-
// either on some other error or all were processed. If there was some other
2066-
// error, we can ignore the rest of those blocks.
2067-
//
2068-
// If the externTd was larger than our local TD, we now need to reimport the previous
2069-
// blocks to regenerate the required state
2070-
reorg, err := bc.forker.ReorgNeeded(current, lastBlock.Header())
2071-
if err != nil {
2072-
return it.index, err
2073-
}
2074-
if !reorg {
2075-
localTd := bc.GetTd(current.Hash(), current.Number.Uint64())
2076-
log.Info("Sidechain written to disk", "start", it.first().NumberU64(), "end", it.previous().Number, "sidetd", externTd, "localtd", localTd)
2077-
return it.index, err
20782025
}
20792026
// Gather all the sidechain hashes (full blocks may be memory heavy)
20802027
var (
@@ -2541,7 +2488,7 @@ func (bc *BlockChain) InsertHeaderChain(chain []*types.Header) (int, error) {
25412488
return 0, errChainStopped
25422489
}
25432490
defer bc.chainmu.Unlock()
2544-
_, err := bc.hc.InsertHeaderChain(chain, start, bc.forker)
2491+
_, err := bc.hc.InsertHeaderChain(chain, start)
25452492
return 0, err
25462493
}
25472494

core/blockchain_insert.go

-5
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,6 @@ func (it *insertIterator) current() *types.Header {
170170
return it.chain[it.index].Header()
171171
}
172172

173-
// first returns the first block in it.
174-
func (it *insertIterator) first() *types.Block {
175-
return it.chain[0]
176-
}
177-
178173
// remaining returns the number of remaining blocks.
179174
func (it *insertIterator) remaining() int {
180175
return len(it.chain) - it.index

core/blockchain_repair_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -1794,7 +1794,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
17941794
config.SnapshotLimit = 256
17951795
config.SnapshotWait = true
17961796
}
1797-
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
1797+
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil)
17981798
if err != nil {
17991799
t.Fatalf("Failed to create chain: %v", err)
18001800
}
@@ -1859,7 +1859,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
18591859
}
18601860
defer db.Close()
18611861

1862-
newChain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
1862+
newChain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil)
18631863
if err != nil {
18641864
t.Fatalf("Failed to recreate chain: %v", err)
18651865
}
@@ -1931,7 +1931,7 @@ func testIssue23496(t *testing.T, scheme string) {
19311931
}
19321932
engine = ethash.NewFullFaker()
19331933
)
1934-
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
1934+
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
19351935
if err != nil {
19361936
t.Fatalf("Failed to create chain: %v", err)
19371937
}
@@ -1981,7 +1981,7 @@ func testIssue23496(t *testing.T, scheme string) {
19811981
}
19821982
defer db.Close()
19831983

1984-
chain, err = NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
1984+
chain, err = NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
19851985
if err != nil {
19861986
t.Fatalf("Failed to recreate chain: %v", err)
19871987
}

core/blockchain_sethead_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1997,7 +1997,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
19971997
config.SnapshotLimit = 256
19981998
config.SnapshotWait = true
19991999
}
2000-
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
2000+
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil)
20012001
if err != nil {
20022002
t.Fatalf("Failed to create chain: %v", err)
20032003
}

0 commit comments

Comments
 (0)