core, eth: fix dependency cycle (#17720)
This commit is contained in:
parent
f55c26ae6d
commit
ba0a8b7887
|
@ -31,7 +31,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/mclock"
|
"github.com/ethereum/go-ethereum/common/mclock"
|
||||||
"github.com/ethereum/go-ethereum/common/prque"
|
"github.com/ethereum/go-ethereum/common/prque"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/consensus/clique"
|
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
@ -129,14 +128,14 @@ type BlockChain struct {
|
||||||
validator Validator // block and state validator interface
|
validator Validator // block and state validator interface
|
||||||
vmConfig vm.Config
|
vmConfig vm.Config
|
||||||
|
|
||||||
badBlocks *lru.Cache // Bad block cache
|
badBlocks *lru.Cache // Bad block cache
|
||||||
isLocalFn func(common.Address) bool // Function used to determine whether the block author is a local miner account.
|
shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block.
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockChain returns a fully initialised block chain using information
|
// NewBlockChain returns a fully initialised block chain using information
|
||||||
// available in the database. It initialises the default Ethereum Validator and
|
// available in the database. It initialises the default Ethereum Validator and
|
||||||
// Processor.
|
// Processor.
|
||||||
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, isLocalFn func(common.Address) bool) (*BlockChain, error) {
|
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool) (*BlockChain, error) {
|
||||||
if cacheConfig == nil {
|
if cacheConfig == nil {
|
||||||
cacheConfig = &CacheConfig{
|
cacheConfig = &CacheConfig{
|
||||||
TrieNodeLimit: 256 * 1024 * 1024,
|
TrieNodeLimit: 256 * 1024 * 1024,
|
||||||
|
@ -150,20 +149,20 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
|
||||||
badBlocks, _ := lru.New(badBlockLimit)
|
badBlocks, _ := lru.New(badBlockLimit)
|
||||||
|
|
||||||
bc := &BlockChain{
|
bc := &BlockChain{
|
||||||
chainConfig: chainConfig,
|
chainConfig: chainConfig,
|
||||||
cacheConfig: cacheConfig,
|
cacheConfig: cacheConfig,
|
||||||
db: db,
|
db: db,
|
||||||
triegc: prque.New(nil),
|
triegc: prque.New(nil),
|
||||||
stateCache: state.NewDatabase(db),
|
stateCache: state.NewDatabase(db),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
isLocalFn: isLocalFn,
|
shouldPreserve: shouldPreserve,
|
||||||
bodyCache: bodyCache,
|
bodyCache: bodyCache,
|
||||||
bodyRLPCache: bodyRLPCache,
|
bodyRLPCache: bodyRLPCache,
|
||||||
blockCache: blockCache,
|
blockCache: blockCache,
|
||||||
futureBlocks: futureBlocks,
|
futureBlocks: futureBlocks,
|
||||||
engine: engine,
|
engine: engine,
|
||||||
vmConfig: vmConfig,
|
vmConfig: vmConfig,
|
||||||
badBlocks: badBlocks,
|
badBlocks: badBlocks,
|
||||||
}
|
}
|
||||||
bc.SetValidator(NewBlockValidator(chainConfig, bc, engine))
|
bc.SetValidator(NewBlockValidator(chainConfig, bc, engine))
|
||||||
bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine))
|
bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine))
|
||||||
|
@ -975,39 +974,11 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
|
||||||
if block.NumberU64() < currentBlock.NumberU64() {
|
if block.NumberU64() < currentBlock.NumberU64() {
|
||||||
reorg = true
|
reorg = true
|
||||||
} else if block.NumberU64() == currentBlock.NumberU64() {
|
} else if block.NumberU64() == currentBlock.NumberU64() {
|
||||||
if _, ok := bc.engine.(*clique.Clique); ok {
|
var currentPreserve, blockPreserve bool
|
||||||
// The reason we need to disable the self-reorg preserving for clique
|
if bc.shouldPreserve != nil {
|
||||||
// is it can be probable to introduce a deadlock.
|
currentPreserve, blockPreserve = bc.shouldPreserve(currentBlock), bc.shouldPreserve(block)
|
||||||
//
|
|
||||||
// e.g. If there are 7 available signers
|
|
||||||
//
|
|
||||||
// r1 A
|
|
||||||
// r2 B
|
|
||||||
// r3 C
|
|
||||||
// r4 D
|
|
||||||
// r5 A [X] F G
|
|
||||||
// r6 [X]
|
|
||||||
//
|
|
||||||
// In the round5, the inturn signer E is offline, so the worst case
|
|
||||||
// is A, F and G sign the block of round5 and reject the block of opponents
|
|
||||||
// and in the round6, the last available signer B is offline, the whole
|
|
||||||
// network is stuck.
|
|
||||||
reorg = mrand.Float64() < 0.5
|
|
||||||
} else {
|
|
||||||
currentAuthor, err := bc.engine.Author(currentBlock.Header())
|
|
||||||
if err != nil {
|
|
||||||
return NonStatTy, err
|
|
||||||
}
|
|
||||||
blockAuthor, err := bc.engine.Author(block.Header())
|
|
||||||
if err != nil {
|
|
||||||
return NonStatTy, err
|
|
||||||
}
|
|
||||||
var currentLocal, blockLocal bool
|
|
||||||
if bc.isLocalFn != nil {
|
|
||||||
currentLocal, blockLocal = bc.isLocalFn(currentAuthor), bc.isLocalFn(blockAuthor)
|
|
||||||
}
|
|
||||||
reorg = !currentLocal && (blockLocal || mrand.Float64() < 0.5)
|
|
||||||
}
|
}
|
||||||
|
reorg = !currentPreserve && (blockPreserve || mrand.Float64() < 0.5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if reorg {
|
if reorg {
|
||||||
|
|
|
@ -156,7 +156,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
}
|
}
|
||||||
cacheConfig = &core.CacheConfig{Disabled: config.NoPruning, TrieNodeLimit: config.TrieCache, TrieTimeLimit: config.TrieTimeout}
|
cacheConfig = &core.CacheConfig{Disabled: config.NoPruning, TrieNodeLimit: config.TrieCache, TrieTimeLimit: config.TrieTimeout}
|
||||||
)
|
)
|
||||||
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, eth.chainConfig, eth.engine, vmConfig, eth.isMinerAccount)
|
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, eth.chainConfig, eth.engine, vmConfig, eth.shouldPreserve)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -334,30 +334,60 @@ func (s *Ethereum) Etherbase() (eb common.Address, err error) {
|
||||||
return common.Address{}, fmt.Errorf("etherbase must be explicitly specified")
|
return common.Address{}, fmt.Errorf("etherbase must be explicitly specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
// isMinerAccount checks whether the specified address is a miner account.
|
// isLocalBlock checks whether the specified block is mined
|
||||||
|
// by local miner accounts.
|
||||||
//
|
//
|
||||||
// This function is used during block chain reorg checking to determine
|
// We regard two types of accounts as local miner account: etherbase
|
||||||
// whether a block is mined by local accounts. We regard two types of
|
// and accounts specified via `txpool.locals` flag.
|
||||||
// accounts as local account: etherbase and accounts specified via
|
func (s *Ethereum) isLocalBlock(block *types.Block) bool {
|
||||||
// `txpool.locals` flag.
|
author, err := s.engine.Author(block.Header())
|
||||||
func (s *Ethereum) isMinerAccount(addr common.Address) bool {
|
if err != nil {
|
||||||
|
log.Warn("Failed to retrieve block author", "number", block.NumberU64(), "hash", block.Hash(), "err", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
// Check whether the given address is etherbase.
|
// Check whether the given address is etherbase.
|
||||||
s.lock.RLock()
|
s.lock.RLock()
|
||||||
etherbase := s.etherbase
|
etherbase := s.etherbase
|
||||||
s.lock.RUnlock()
|
s.lock.RUnlock()
|
||||||
if addr == etherbase {
|
if author == etherbase {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// Check whether the given address is specified by `txpool.local`
|
// Check whether the given address is specified by `txpool.local`
|
||||||
// CLI flag.
|
// CLI flag.
|
||||||
for _, account := range s.config.TxPool.Locals {
|
for _, account := range s.config.TxPool.Locals {
|
||||||
if account == addr {
|
if account == author {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shouldPreserve checks whether we should preserve the given block
|
||||||
|
// during the chain reorg depending on whether the author of block
|
||||||
|
// is a local account.
|
||||||
|
func (s *Ethereum) shouldPreserve(block *types.Block) bool {
|
||||||
|
// The reason we need to disable the self-reorg preserving for clique
|
||||||
|
// is it can be probable to introduce a deadlock.
|
||||||
|
//
|
||||||
|
// e.g. If there are 7 available signers
|
||||||
|
//
|
||||||
|
// r1 A
|
||||||
|
// r2 B
|
||||||
|
// r3 C
|
||||||
|
// r4 D
|
||||||
|
// r5 A [X] F G
|
||||||
|
// r6 [X]
|
||||||
|
//
|
||||||
|
// In the round5, the inturn signer E is offline, so the worst case
|
||||||
|
// is A, F and G sign the block of round5 and reject the block of opponents
|
||||||
|
// and in the round6, the last available signer B is offline, the whole
|
||||||
|
// network is stuck.
|
||||||
|
if _, ok := s.engine.(*clique.Clique); ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return s.isLocalBlock(block)
|
||||||
|
}
|
||||||
|
|
||||||
// SetEtherbase sets the mining reward address.
|
// SetEtherbase sets the mining reward address.
|
||||||
func (s *Ethereum) SetEtherbase(etherbase common.Address) {
|
func (s *Ethereum) SetEtherbase(etherbase common.Address) {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
|
|
Loading…
Reference in New Issue