consensus: add three method for consensus interface

This commit is contained in:
rjl493456442 2018-05-02 19:26:32 +08:00
parent 31bcd52d4b
commit 32555698dd
7 changed files with 77 additions and 2 deletions

View file

@ -23,6 +23,7 @@ import (
"math/big" "math/big"
"math/rand" "math/rand"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/ethereum/go-ethereum/accounts" "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 // Clique is the proof-of-authority consensus engine proposed to support the
// Ethereum testnet following the Ropsten attacks. // Ethereum testnet following the Ropsten attacks.
type Clique struct { type Clique struct {
config *params.CliqueConfig // Consensus engine configuration parameters config *params.CliqueConfig // Consensus engine configuration parameters
db ethdb.Database // Database to store and retrieve snapshot checkpoints 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 recents *lru.ARCCache // Snapshots for recent block to speed up reorgs
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining 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 { if c.config.Period == 0 && len(block.Transactions()) == 0 {
return nil, errWaitTransactions 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 // Don't hold the signer fields for the entire sealing procedure
c.lock.RLock() c.lock.RLock()
signer, signFn := c.signer, c.signFn 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) 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. // Close implements consensus.Engine, returning internal error and close the clique.
func (c *Clique) Close() error { func (c *Clique) Close() error {
return nil return nil

View file

@ -97,6 +97,15 @@ type Engine interface {
// APIs returns the RPC APIs this consensus engine provides. // APIs returns the RPC APIs this consensus engine provides.
APIs(chain ChainReader) []rpc.API 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 closes the consensus engine.
Close() error Close() error
} }

View file

@ -34,4 +34,7 @@ var (
// ErrInvalidNumber is returned if a block's number doesn't equal it's parent's // ErrInvalidNumber is returned if a block's number doesn't equal it's parent's
// plus one. // plus one.
ErrInvalidNumber = errors.New("invalid block number") ErrInvalidNumber = errors.New("invalid block number")
// ErrEngineNotStart is returned if the consensus engine is not started.
ErrEngineNotStart = errors.New("consensus engine is not started")
) )

View file

@ -44,6 +44,12 @@ func (api *API) GetWork() ([3]string, error) {
err 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 { select {
case api.ethash.fetchWorkCh <- &sealWork{errCh: errCh, resCh: workCh}: case api.ethash.fetchWorkCh <- &sealWork{errCh: errCh, resCh: workCh}:
case <-api.ethash.exitCh: case <-api.ethash.exitCh:

View file

@ -22,6 +22,7 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"runtime" "runtime"
"sync/atomic"
"time" "time"
mapset "github.com/deckarep/golang-set" mapset "github.com/deckarep/golang-set"
@ -552,3 +553,18 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header
} }
state.AddBalance(header.Coinbase, reward) state.AddBalance(header.Coinbase, reward)
} }
// Start implements consensus.Engine, starting the ethash engine.
func (ethash *Ethash) Start() {
atomic.StoreInt32(&ethash.running, 1)
}
// Stop implements consensus.Engine, stopping the ethash engine.
func (ethash *Ethash) Stop() {
atomic.StoreInt32(&ethash.running, 0)
}
// IsRunning implements consensus.Engine, returning an indication if the ethash engine is currently mining.
func (ethash *Ethash) IsRunning() bool {
return atomic.LoadInt32(&ethash.running) > 0
}

View file

@ -428,6 +428,7 @@ type Ethash struct {
threads int // Number of threads to mine on if mining threads int // Number of threads to mine on if mining
update chan struct{} // Notification channel to update mining parameters update chan struct{} // Notification channel to update mining parameters
hashrate metrics.Meter // Meter tracking the average hashrate hashrate metrics.Meter // Meter tracking the average hashrate
running int32 // Indicator whether ethash engine is running or not.
// Remote sealer related fields // Remote sealer related fields
workCh chan *types.Block // Notification channel to push new work to remote sealer 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), datasets: newlru("dataset", 1, newDataset),
update: make(chan struct{}), update: make(chan struct{}),
hashrate: metrics.NewMeter(), hashrate: metrics.NewMeter(),
running: 1, // enable local mining by default
workCh: make(chan *types.Block), workCh: make(chan *types.Block),
resultCh: make(chan *types.Block), resultCh: make(chan *types.Block),
fetchWorkCh: make(chan *sealWork), 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 // SeedHash is the seed to use for generating a verification cache and the mining
// dataset. // dataset.
func SeedHash(block uint64) []byte { func SeedHash(block uint64) []byte {

View file

@ -50,6 +50,10 @@ func (ethash *Ethash) Seal(chain consensus.ChainReader, block *types.Block, stop
if ethash.shared != nil { if ethash.shared != nil {
return ethash.shared.Seal(chain, block, stop) 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 // Create a runner and the multiple search threads it directs
abort := make(chan struct{}) abort := make(chan struct{})