From 32555698dd3e75b02197732ac9e51258b7fa2001 Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Wed, 2 May 2018 19:26:32 +0800 Subject: [PATCH] consensus: add three method for consensus interface --- consensus/clique/clique.go | 25 +++++++++++++++++++++++-- consensus/consensus.go | 9 +++++++++ consensus/errors.go | 3 +++ consensus/ethash/api.go | 6 ++++++ consensus/ethash/consensus.go | 16 ++++++++++++++++ consensus/ethash/ethash.go | 16 ++++++++++++++++ consensus/ethash/sealer.go | 4 ++++ 7 files changed, 77 insertions(+), 2 deletions(-) diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 5963900c97..4f637c3aa5 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -23,6 +23,7 @@ import ( "math/big" "math/rand" "sync" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/accounts" @@ -194,8 +195,9 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, er // Clique is the proof-of-authority consensus engine proposed to support the // Ethereum testnet following the Ropsten attacks. type Clique struct { - config *params.CliqueConfig // Consensus engine configuration parameters - db ethdb.Database // Database to store and retrieve snapshot checkpoints + config *params.CliqueConfig // Consensus engine configuration parameters + db ethdb.Database // Database to store and retrieve snapshot checkpoints + running int32 // Indicator whether clique engine is running or not. recents *lru.ARCCache // Snapshots for recent block to speed up reorgs signatures *lru.ARCCache // Signatures of recent blocks to speed up mining @@ -601,6 +603,10 @@ func (c *Clique) Seal(chain consensus.ChainReader, block *types.Block, stop <-ch if c.config.Period == 0 && len(block.Transactions()) == 0 { return nil, errWaitTransactions } + // Make sure clique engine is started. + if !c.IsRunning() { + return nil, consensus.ErrEngineNotStart + } // Don't hold the signer fields for the entire sealing procedure c.lock.RLock() signer, signFn := c.signer, c.signFn @@ -672,6 +678,21 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int { return new(big.Int).Set(diffNoTurn) } +// Start implements consensus.Engine, starting the clique consensus engine. +func (c *Clique) Start() { + atomic.StoreInt32(&c.running, 1) +} + +// Stop implements consensus.Engine, stopping the clique consensus engine. +func (c *Clique) Stop() { + atomic.StoreInt32(&c.running, 0) +} + +// IsRunning implements consensus.Engine, returning an indication if the clique engine is currently mining. +func (c *Clique) IsRunning() bool { + return atomic.LoadInt32(&c.running) > 0 +} + // Close implements consensus.Engine, returning internal error and close the clique. func (c *Clique) Close() error { return nil diff --git a/consensus/consensus.go b/consensus/consensus.go index ae0fefb490..3562388d51 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -97,6 +97,15 @@ type Engine interface { // APIs returns the RPC APIs this consensus engine provides. APIs(chain ChainReader) []rpc.API + // Start starts the consensus engine. + Start() + + // Stop stops the consensus engine. + Stop() + + // IsRunning returns an indication whether consensus engine is running or not. + IsRunning() bool + // Close closes the consensus engine. Close() error } diff --git a/consensus/errors.go b/consensus/errors.go index a005c5f63d..c7d7073e19 100644 --- a/consensus/errors.go +++ b/consensus/errors.go @@ -34,4 +34,7 @@ var ( // ErrInvalidNumber is returned if a block's number doesn't equal it's parent's // plus one. ErrInvalidNumber = errors.New("invalid block number") + + // ErrEngineNotStart is returned if the consensus engine is not started. + ErrEngineNotStart = errors.New("consensus engine is not started") ) diff --git a/consensus/ethash/api.go b/consensus/ethash/api.go index 1d648b82e2..6a1e015506 100644 --- a/consensus/ethash/api.go +++ b/consensus/ethash/api.go @@ -44,6 +44,12 @@ func (api *API) GetWork() ([3]string, error) { err error ) + // Trigger ethash to start in remote mining mode(local/cpu mining is disabled) + // if ethash is not running. + if !api.ethash.IsRunning() { + api.ethash.StartMining(new(int)) + } + select { case api.ethash.fetchWorkCh <- &sealWork{errCh: errCh, resCh: workCh}: case <-api.ethash.exitCh: diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index eb0f73d98b..094085aa8c 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -22,6 +22,7 @@ import ( "fmt" "math/big" "runtime" + "sync/atomic" "time" mapset "github.com/deckarep/golang-set" @@ -552,3 +553,18 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header } state.AddBalance(header.Coinbase, reward) } + +// Start implements consensus.Engine, starting the ethash engine. +func (ethash *Ethash) Start() { + atomic.StoreInt32(ðash.running, 1) +} + +// Stop implements consensus.Engine, stopping the ethash engine. +func (ethash *Ethash) Stop() { + atomic.StoreInt32(ðash.running, 0) +} + +// IsRunning implements consensus.Engine, returning an indication if the ethash engine is currently mining. +func (ethash *Ethash) IsRunning() bool { + return atomic.LoadInt32(ðash.running) > 0 +} diff --git a/consensus/ethash/ethash.go b/consensus/ethash/ethash.go index 424f779917..7e9e661f78 100644 --- a/consensus/ethash/ethash.go +++ b/consensus/ethash/ethash.go @@ -428,6 +428,7 @@ type Ethash struct { threads int // Number of threads to mine on if mining update chan struct{} // Notification channel to update mining parameters hashrate metrics.Meter // Meter tracking the average hashrate + running int32 // Indicator whether ethash engine is running or not. // Remote sealer related fields workCh chan *types.Block // Notification channel to push new work to remote sealer @@ -486,6 +487,7 @@ func NewTester() *Ethash { datasets: newlru("dataset", 1, newDataset), update: make(chan struct{}), hashrate: metrics.NewMeter(), + running: 1, // enable local mining by default workCh: make(chan *types.Block), resultCh: make(chan *types.Block), fetchWorkCh: make(chan *sealWork), @@ -680,6 +682,20 @@ func (ethash *Ethash) APIs(chain consensus.ChainReader) []rpc.API { } } +// StartMining starts the ethash engine with the given number of threads. +// If threads is nil the number of workers started is equal to the number of logical CPUs +// that are usable by this process. If threads is 0, than local/cpu mining will be disabled. +// If mining is already running, this method adjust the number of threads allowed to use. +func (ethash *Ethash) StartMining(threads *int) { + if threads == nil { + threads = new(int) + } else if *threads == 0 { + *threads = -1 // Disable local/cpu mining. + } + ethash.Start() + ethash.SetThreads(*threads) +} + // SeedHash is the seed to use for generating a verification cache and the mining // dataset. func SeedHash(block uint64) []byte { diff --git a/consensus/ethash/sealer.go b/consensus/ethash/sealer.go index 539e783a6c..4c164b779b 100644 --- a/consensus/ethash/sealer.go +++ b/consensus/ethash/sealer.go @@ -50,6 +50,10 @@ func (ethash *Ethash) Seal(chain consensus.ChainReader, block *types.Block, stop if ethash.shared != nil { return ethash.shared.Seal(chain, block, stop) } + // Make sure ethash engine is started. + if !ethash.IsRunning() { + return nil, consensus.ErrEngineNotStart + } // Create a runner and the multiple search threads it directs abort := make(chan struct{})