Skip to content

Commit ba0a8b7

Browse files
rjl493456442karalabe
authored andcommitted
core, eth: fix dependency cycle (#17720)
1 parent f55c26a commit ba0a8b7

File tree

2 files changed

+60
-59
lines changed

2 files changed

+60
-59
lines changed

core/blockchain.go

Lines changed: 21 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
"github.com/ethereum/go-ethereum/common/mclock"
3232
"github.com/ethereum/go-ethereum/common/prque"
3333
"github.com/ethereum/go-ethereum/consensus"
34-
"github.com/ethereum/go-ethereum/consensus/clique"
3534
"github.com/ethereum/go-ethereum/core/rawdb"
3635
"github.com/ethereum/go-ethereum/core/state"
3736
"github.com/ethereum/go-ethereum/core/types"
@@ -129,14 +128,14 @@ type BlockChain struct {
129128
validator Validator // block and state validator interface
130129
vmConfig vm.Config
131130

132-
badBlocks *lru.Cache // Bad block cache
133-
isLocalFn func(common.Address) bool // Function used to determine whether the block author is a local miner account.
131+
badBlocks *lru.Cache // Bad block cache
132+
shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block.
134133
}
135134

136135
// NewBlockChain returns a fully initialised block chain using information
137136
// available in the database. It initialises the default Ethereum Validator and
138137
// Processor.
139-
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, isLocalFn func(common.Address) bool) (*BlockChain, error) {
138+
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool) (*BlockChain, error) {
140139
if cacheConfig == nil {
141140
cacheConfig = &CacheConfig{
142141
TrieNodeLimit: 256 * 1024 * 1024,
@@ -150,20 +149,20 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
150149
badBlocks, _ := lru.New(badBlockLimit)
151150

152151
bc := &BlockChain{
153-
chainConfig: chainConfig,
154-
cacheConfig: cacheConfig,
155-
db: db,
156-
triegc: prque.New(nil),
157-
stateCache: state.NewDatabase(db),
158-
quit: make(chan struct{}),
159-
isLocalFn: isLocalFn,
160-
bodyCache: bodyCache,
161-
bodyRLPCache: bodyRLPCache,
162-
blockCache: blockCache,
163-
futureBlocks: futureBlocks,
164-
engine: engine,
165-
vmConfig: vmConfig,
166-
badBlocks: badBlocks,
152+
chainConfig: chainConfig,
153+
cacheConfig: cacheConfig,
154+
db: db,
155+
triegc: prque.New(nil),
156+
stateCache: state.NewDatabase(db),
157+
quit: make(chan struct{}),
158+
shouldPreserve: shouldPreserve,
159+
bodyCache: bodyCache,
160+
bodyRLPCache: bodyRLPCache,
161+
blockCache: blockCache,
162+
futureBlocks: futureBlocks,
163+
engine: engine,
164+
vmConfig: vmConfig,
165+
badBlocks: badBlocks,
167166
}
168167
bc.SetValidator(NewBlockValidator(chainConfig, bc, engine))
169168
bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine))
@@ -975,39 +974,11 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
975974
if block.NumberU64() < currentBlock.NumberU64() {
976975
reorg = true
977976
} else if block.NumberU64() == currentBlock.NumberU64() {
978-
if _, ok := bc.engine.(*clique.Clique); ok {
979-
// The reason we need to disable the self-reorg preserving for clique
980-
// is it can be probable to introduce a deadlock.
981-
//
982-
// e.g. If there are 7 available signers
983-
//
984-
// r1 A
985-
// r2 B
986-
// r3 C
987-
// r4 D
988-
// r5 A [X] F G
989-
// r6 [X]
990-
//
991-
// In the round5, the inturn signer E is offline, so the worst case
992-
// is A, F and G sign the block of round5 and reject the block of opponents
993-
// and in the round6, the last available signer B is offline, the whole
994-
// network is stuck.
995-
reorg = mrand.Float64() < 0.5
996-
} else {
997-
currentAuthor, err := bc.engine.Author(currentBlock.Header())
998-
if err != nil {
999-
return NonStatTy, err
1000-
}
1001-
blockAuthor, err := bc.engine.Author(block.Header())
1002-
if err != nil {
1003-
return NonStatTy, err
1004-
}
1005-
var currentLocal, blockLocal bool
1006-
if bc.isLocalFn != nil {
1007-
currentLocal, blockLocal = bc.isLocalFn(currentAuthor), bc.isLocalFn(blockAuthor)
1008-
}
1009-
reorg = !currentLocal && (blockLocal || mrand.Float64() < 0.5)
977+
var currentPreserve, blockPreserve bool
978+
if bc.shouldPreserve != nil {
979+
currentPreserve, blockPreserve = bc.shouldPreserve(currentBlock), bc.shouldPreserve(block)
1010980
}
981+
reorg = !currentPreserve && (blockPreserve || mrand.Float64() < 0.5)
1011982
}
1012983
}
1013984
if reorg {

eth/backend.go

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
156156
}
157157
cacheConfig = &core.CacheConfig{Disabled: config.NoPruning, TrieNodeLimit: config.TrieCache, TrieTimeLimit: config.TrieTimeout}
158158
)
159-
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, eth.chainConfig, eth.engine, vmConfig, eth.isMinerAccount)
159+
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, eth.chainConfig, eth.engine, vmConfig, eth.shouldPreserve)
160160
if err != nil {
161161
return nil, err
162162
}
@@ -334,30 +334,60 @@ func (s *Ethereum) Etherbase() (eb common.Address, err error) {
334334
return common.Address{}, fmt.Errorf("etherbase must be explicitly specified")
335335
}
336336

337-
// isMinerAccount checks whether the specified address is a miner account.
337+
// isLocalBlock checks whether the specified block is mined
338+
// by local miner accounts.
338339
//
339-
// This function is used during block chain reorg checking to determine
340-
// whether a block is mined by local accounts. We regard two types of
341-
// accounts as local account: etherbase and accounts specified via
342-
// `txpool.locals` flag.
343-
func (s *Ethereum) isMinerAccount(addr common.Address) bool {
340+
// We regard two types of accounts as local miner account: etherbase
341+
// and accounts specified via `txpool.locals` flag.
342+
func (s *Ethereum) isLocalBlock(block *types.Block) bool {
343+
author, err := s.engine.Author(block.Header())
344+
if err != nil {
345+
log.Warn("Failed to retrieve block author", "number", block.NumberU64(), "hash", block.Hash(), "err", err)
346+
return false
347+
}
344348
// Check whether the given address is etherbase.
345349
s.lock.RLock()
346350
etherbase := s.etherbase
347351
s.lock.RUnlock()
348-
if addr == etherbase {
352+
if author == etherbase {
349353
return true
350354
}
351355
// Check whether the given address is specified by `txpool.local`
352356
// CLI flag.
353357
for _, account := range s.config.TxPool.Locals {
354-
if account == addr {
358+
if account == author {
355359
return true
356360
}
357361
}
358362
return false
359363
}
360364

365+
// shouldPreserve checks whether we should preserve the given block
366+
// during the chain reorg depending on whether the author of block
367+
// is a local account.
368+
func (s *Ethereum) shouldPreserve(block *types.Block) bool {
369+
// The reason we need to disable the self-reorg preserving for clique
370+
// is it can be probable to introduce a deadlock.
371+
//
372+
// e.g. If there are 7 available signers
373+
//
374+
// r1 A
375+
// r2 B
376+
// r3 C
377+
// r4 D
378+
// r5 A [X] F G
379+
// r6 [X]
380+
//
381+
// In the round5, the inturn signer E is offline, so the worst case
382+
// is A, F and G sign the block of round5 and reject the block of opponents
383+
// and in the round6, the last available signer B is offline, the whole
384+
// network is stuck.
385+
if _, ok := s.engine.(*clique.Clique); ok {
386+
return false
387+
}
388+
return s.isLocalBlock(block)
389+
}
390+
361391
// SetEtherbase sets the mining reward address.
362392
func (s *Ethereum) SetEtherbase(etherbase common.Address) {
363393
s.lock.Lock()

0 commit comments

Comments
 (0)