From 159fba764afac624fa79a034fb03052413896475 Mon Sep 17 00:00:00 2001 From: "mark.lin" Date: Mon, 18 Dec 2017 10:48:59 +0800 Subject: [PATCH] core, les, eth, miner: Istanbul consensus integration --- core/blockchain.go | 5 +++++ eth/backend.go | 44 +++++++++++++++++++++++++++++++++----------- les/backend.go | 2 +- miner/worker.go | 12 ++++++++++++ 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index b33eb85a44..50566e7a36 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1406,6 +1406,11 @@ func (bc *BlockChain) BadBlocks() ([]BadBlockArgs, error) { 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 func (bc *BlockChain) addBadBlock(block *types.Block) { bc.badBlocks.Add(block.Header().Hash(), block.Header()) diff --git a/eth/backend.go b/eth/backend.go index 2359f3ec30..f6477e27d2 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -31,10 +31,13 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/clique" "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/bloombits" "github.com/ethereum/go-ethereum/core/types" "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/filters" "github.com/ethereum/go-ethereum/eth/gasprice" @@ -125,7 +128,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { chainConfig: chainConfig, eventMux: ctx.EventMux, accountManager: ctx.AccountManager, - engine: CreateConsensusEngine(ctx, &config.Ethash, chainConfig, chainDb), + engine: CreateConsensusEngine(ctx, config, chainConfig, chainDb), shutdownChan: make(chan bool), stopDbUpgrade: stopDbUpgrade, networkId: config.NetworkId, @@ -135,6 +138,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { 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) 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 -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 chainConfig.Clique != nil { 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 + ethConfig := config.Ethash switch { - case config.PowMode == ethash.ModeFake: + case ethConfig.PowMode == ethash.ModeFake: log.Warn("Ethash used in fake mode") return ethash.NewFaker() - case config.PowMode == ethash.ModeTest: + case ethConfig.PowMode == ethash.ModeTest: log.Warn("Ethash used in test mode") return ethash.NewTester() - case config.PowMode == ethash.ModeShared: + case ethConfig.PowMode == ethash.ModeShared: log.Warn("Ethash used in shared mode") return ethash.NewShared() default: engine := ethash.New(ethash.Config{ - CacheDir: ctx.ResolvePath(config.CacheDir), - CachesInMem: config.CachesInMem, - CachesOnDisk: config.CachesOnDisk, - DatasetDir: config.DatasetDir, - DatasetsInMem: config.DatasetsInMem, - DatasetsOnDisk: config.DatasetsOnDisk, + CacheDir: ctx.ResolvePath(ethConfig.CacheDir), + CachesInMem: ethConfig.CachesInMem, + CachesOnDisk: ethConfig.CachesOnDisk, + DatasetDir: ethConfig.DatasetDir, + DatasetsInMem: ethConfig.DatasetsInMem, + DatasetsOnDisk: ethConfig.DatasetsOnDisk, }) engine.SetThreads(-1) // Disable CPU mining 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 func (self *Ethereum) SetEtherbase(etherbase common.Address) { self.lock.Lock() + if _, ok := self.engine.(consensus.Istanbul); ok { + log.Error("Cannot set etherbase in Istanbul consensus") + return + } self.etherbase = etherbase self.lock.Unlock() diff --git a/les/backend.go b/les/backend.go index 6a324cb04b..1e36c5ba82 100644 --- a/les/backend.go +++ b/les/backend.go @@ -101,7 +101,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { peers: peers, reqDist: newRequestDistributor(peers, quitSync), accountManager: ctx.AccountManager, - engine: eth.CreateConsensusEngine(ctx, &config.Ethash, chainConfig, chainDb), + engine: eth.CreateConsensusEngine(ctx, config, chainConfig, chainDb), shutdownChan: make(chan bool), networkId: config.NetworkId, bloomRequests: make(chan chan *bloombits.Retrieval), diff --git a/miner/worker.go b/miner/worker.go index 15395ae0b9..8d02ab23df 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -206,6 +206,10 @@ func (self *worker) start() { 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 for agent := range self.agents { agent.Start() @@ -222,6 +226,11 @@ func (self *worker) stop() { agent.Stop() } } + + if istanbul, ok := self.engine.(consensus.Istanbul); ok { + istanbul.Stop() + } + atomic.StoreInt32(&self.mining, 0) atomic.StoreInt32(&self.atWork, 0) } @@ -250,6 +259,9 @@ func (self *worker) update() { select { // Handle ChainHeadEvent case <-self.chainHeadCh: + if h, ok := self.engine.(consensus.Handler); ok { + h.NewChainHead() + } self.commitNewWork() // Handle ChainSideEvent