core, consensus: pluggable consensus engines (#3817)

This commit adds pluggable consensus engines to go-ethereum. In short, it
introduces a generic consensus interface, and refactors the entire codebase to
use this interface.
This commit is contained in:
Péter Szilágyi
2017-04-05 01:16:29 +03:00
committed by Felix Lange
parent e50a5b7771
commit 09777952ee
61 changed files with 1681 additions and 1426 deletions

View File

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
@ -32,7 +33,6 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
)
// Backend wraps all methods required for mining.
@ -49,24 +49,24 @@ type Miner struct {
worker *worker
threads int
coinbase common.Address
mining int32
eth Backend
pow pow.PoW
engine consensus.Engine
canStart int32 // can start indicates whether we can start the mining operation
shouldStart int32 // should start indicates whether we should start after sync
}
func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, pow pow.PoW) *Miner {
func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine) *Miner {
miner := &Miner{
eth: eth,
mux: mux,
pow: pow,
worker: newWorker(config, common.Address{}, eth, mux),
engine: engine,
worker: newWorker(config, engine, common.Address{}, eth, mux),
canStart: 1,
}
miner.Register(NewCpuAgent(eth.BlockChain(), engine))
go miner.update()
return miner
@ -86,7 +86,7 @@ out:
if self.Mining() {
self.Stop()
atomic.StoreInt32(&self.shouldStart, 1)
log.Info(fmt.Sprint("Mining operation aborted due to sync operation"))
log.Info("Mining aborted due to sync")
}
case downloader.DoneEvent, downloader.FailedEvent:
shouldStart := atomic.LoadInt32(&self.shouldStart) == 1
@ -94,7 +94,7 @@ out:
atomic.StoreInt32(&self.canStart, 1)
atomic.StoreInt32(&self.shouldStart, 0)
if shouldStart {
self.Start(self.coinbase, self.threads)
self.Start(self.coinbase)
}
// unsubscribe. we're only interested in this event once
events.Unsubscribe()
@ -116,23 +116,18 @@ func (m *Miner) SetGasPrice(price *big.Int) {
m.worker.setGasPrice(price)
}
func (self *Miner) Start(coinbase common.Address, threads int) {
func (self *Miner) Start(coinbase common.Address) {
atomic.StoreInt32(&self.shouldStart, 1)
self.worker.setEtherbase(coinbase)
self.coinbase = coinbase
self.threads = threads
if atomic.LoadInt32(&self.canStart) == 0 {
log.Info(fmt.Sprint("Can not start mining operation due to network sync (starts when finished)"))
log.Info("Network syncing, will start miner afterwards")
return
}
atomic.StoreInt32(&self.mining, 1)
for i := 0; i < threads; i++ {
self.worker.register(NewCpuAgent(i, self.pow))
}
log.Info(fmt.Sprintf("Starting mining operation (CPU=%d TOT=%d)\n", threads, len(self.worker.agents)))
log.Info("Starting mining operation")
self.worker.start()
self.worker.commitNewWork()
}
@ -159,7 +154,9 @@ func (self *Miner) Mining() bool {
}
func (self *Miner) HashRate() (tot int64) {
tot += int64(self.pow.Hashrate())
if pow, ok := self.engine.(consensus.PoW); ok {
tot += int64(pow.Hashrate())
}
// do we care this might race? is it worth we're rewriting some
// aspects of the worker/locking up agents so we can get an accurate
// hashrate?