core, les, eth, miner: Istanbul consensus integration

This commit is contained in:
mark.lin 2017-12-18 10:48:59 +08:00
parent 3718bc0160
commit 159fba764a
4 changed files with 51 additions and 12 deletions

View file

@ -1406,6 +1406,11 @@ func (bc *BlockChain) BadBlocks() ([]BadBlockArgs, error) {
return headers, nil return headers, nil
} }
// HasBadBlock returns whether the block with the hash is a bad block
func (bc *BlockChain) HasBadBlock(hash common.Hash) bool {
return bc.badBlocks.Contains(hash)
}
// addBadBlock adds a bad block to the bad-block LRU cache // addBadBlock adds a bad block to the bad-block LRU cache
func (bc *BlockChain) addBadBlock(block *types.Block) { func (bc *BlockChain) addBadBlock(block *types.Block) {
bc.badBlocks.Add(block.Header().Hash(), block.Header()) bc.badBlocks.Add(block.Header().Hash(), block.Header())

View file

@ -31,10 +31,13 @@ import (
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/consensus/istanbul"
istanbulBackend "github.com/ethereum/go-ethereum/consensus/istanbul/backend"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
@ -125,7 +128,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
chainConfig: chainConfig, chainConfig: chainConfig,
eventMux: ctx.EventMux, eventMux: ctx.EventMux,
accountManager: ctx.AccountManager, accountManager: ctx.AccountManager,
engine: CreateConsensusEngine(ctx, &config.Ethash, chainConfig, chainDb), engine: CreateConsensusEngine(ctx, config, chainConfig, chainDb),
shutdownChan: make(chan bool), shutdownChan: make(chan bool),
stopDbUpgrade: stopDbUpgrade, stopDbUpgrade: stopDbUpgrade,
networkId: config.NetworkId, networkId: config.NetworkId,
@ -135,6 +138,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks), bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks),
} }
// force to set the istanbul etherbase to node key address
if chainConfig.Istanbul != nil {
eth.etherbase = crypto.PubkeyToAddress(ctx.NodeKey().PublicKey)
}
log.Info("Initialising Ethereum protocol", "versions", eth.engine.Protocol().Versions, "network", config.NetworkId) log.Info("Initialising Ethereum protocol", "versions", eth.engine.Protocol().Versions, "network", config.NetworkId)
if !config.SkipBcVersionCheck { if !config.SkipBcVersionCheck {
@ -211,30 +219,40 @@ func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Data
} }
// CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service // CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service
func CreateConsensusEngine(ctx *node.ServiceContext, config *ethash.Config, chainConfig *params.ChainConfig, db ethdb.Database) consensus.Engine { func CreateConsensusEngine(ctx *node.ServiceContext, config *Config, chainConfig *params.ChainConfig, db ethdb.Database) consensus.Engine {
// If proof-of-authority is requested, set it up // If proof-of-authority is requested, set it up
if chainConfig.Clique != nil { if chainConfig.Clique != nil {
return clique.New(chainConfig.Clique, db) return clique.New(chainConfig.Clique, db)
} }
// If Istanbul is requested, set it up
if chainConfig.Istanbul != nil {
if chainConfig.Istanbul.Epoch != 0 {
config.Istanbul.Epoch = chainConfig.Istanbul.Epoch
}
config.Istanbul.ProposerPolicy = istanbul.ProposerPolicy(chainConfig.Istanbul.ProposerPolicy)
return istanbulBackend.New(&config.Istanbul, ctx.NodeKey(), db)
}
// Otherwise assume proof-of-work // Otherwise assume proof-of-work
ethConfig := config.Ethash
switch { switch {
case config.PowMode == ethash.ModeFake: case ethConfig.PowMode == ethash.ModeFake:
log.Warn("Ethash used in fake mode") log.Warn("Ethash used in fake mode")
return ethash.NewFaker() return ethash.NewFaker()
case config.PowMode == ethash.ModeTest: case ethConfig.PowMode == ethash.ModeTest:
log.Warn("Ethash used in test mode") log.Warn("Ethash used in test mode")
return ethash.NewTester() return ethash.NewTester()
case config.PowMode == ethash.ModeShared: case ethConfig.PowMode == ethash.ModeShared:
log.Warn("Ethash used in shared mode") log.Warn("Ethash used in shared mode")
return ethash.NewShared() return ethash.NewShared()
default: default:
engine := ethash.New(ethash.Config{ engine := ethash.New(ethash.Config{
CacheDir: ctx.ResolvePath(config.CacheDir), CacheDir: ctx.ResolvePath(ethConfig.CacheDir),
CachesInMem: config.CachesInMem, CachesInMem: ethConfig.CachesInMem,
CachesOnDisk: config.CachesOnDisk, CachesOnDisk: ethConfig.CachesOnDisk,
DatasetDir: config.DatasetDir, DatasetDir: ethConfig.DatasetDir,
DatasetsInMem: config.DatasetsInMem, DatasetsInMem: ethConfig.DatasetsInMem,
DatasetsOnDisk: config.DatasetsOnDisk, DatasetsOnDisk: ethConfig.DatasetsOnDisk,
}) })
engine.SetThreads(-1) // Disable CPU mining engine.SetThreads(-1) // Disable CPU mining
return engine return engine
@ -328,6 +346,10 @@ func (s *Ethereum) Etherbase() (eb common.Address, err error) {
// set in js console via admin interface or wrapper from cli flags // set in js console via admin interface or wrapper from cli flags
func (self *Ethereum) SetEtherbase(etherbase common.Address) { func (self *Ethereum) SetEtherbase(etherbase common.Address) {
self.lock.Lock() self.lock.Lock()
if _, ok := self.engine.(consensus.Istanbul); ok {
log.Error("Cannot set etherbase in Istanbul consensus")
return
}
self.etherbase = etherbase self.etherbase = etherbase
self.lock.Unlock() self.lock.Unlock()

View file

@ -101,7 +101,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
peers: peers, peers: peers,
reqDist: newRequestDistributor(peers, quitSync), reqDist: newRequestDistributor(peers, quitSync),
accountManager: ctx.AccountManager, accountManager: ctx.AccountManager,
engine: eth.CreateConsensusEngine(ctx, &config.Ethash, chainConfig, chainDb), engine: eth.CreateConsensusEngine(ctx, config, chainConfig, chainDb),
shutdownChan: make(chan bool), shutdownChan: make(chan bool),
networkId: config.NetworkId, networkId: config.NetworkId,
bloomRequests: make(chan chan *bloombits.Retrieval), bloomRequests: make(chan chan *bloombits.Retrieval),

View file

@ -206,6 +206,10 @@ func (self *worker) start() {
atomic.StoreInt32(&self.mining, 1) atomic.StoreInt32(&self.mining, 1)
if istanbul, ok := self.engine.(consensus.Istanbul); ok {
istanbul.Start(self.chain, self.chain.CurrentBlock, self.chain.HasBadBlock)
}
// spin up agents // spin up agents
for agent := range self.agents { for agent := range self.agents {
agent.Start() agent.Start()
@ -222,6 +226,11 @@ func (self *worker) stop() {
agent.Stop() agent.Stop()
} }
} }
if istanbul, ok := self.engine.(consensus.Istanbul); ok {
istanbul.Stop()
}
atomic.StoreInt32(&self.mining, 0) atomic.StoreInt32(&self.mining, 0)
atomic.StoreInt32(&self.atWork, 0) atomic.StoreInt32(&self.atWork, 0)
} }
@ -250,6 +259,9 @@ func (self *worker) update() {
select { select {
// Handle ChainHeadEvent // Handle ChainHeadEvent
case <-self.chainHeadCh: case <-self.chainHeadCh:
if h, ok := self.engine.(consensus.Handler); ok {
h.NewChainHead()
}
self.commitNewWork() self.commitNewWork()
// Handle ChainSideEvent // Handle ChainSideEvent