diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 4f3849a41b..fdbbc27b67 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -121,6 +121,7 @@ var ( utils.MinerLegacyExtraDataFlag, utils.MinerRecommitIntervalFlag, utils.MinerNoVerfiyFlag, + utils.MinerNoAdvanceFlag, utils.NATFlag, utils.NoDiscoverFlag, utils.DiscoveryV5Flag, diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go index 7ec1ab03f5..5d4b94d964 100644 --- a/cmd/geth/usage.go +++ b/cmd/geth/usage.go @@ -203,6 +203,7 @@ var AppHelpFlagGroups = []flagGroup{ utils.MinerExtraDataFlag, utils.MinerRecommitIntervalFlag, utils.MinerNoVerfiyFlag, + utils.MinerNoAdvanceFlag, }, }, { diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index f5f4cde5b4..4ce62e0fc4 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -424,6 +424,10 @@ var ( Name: "miner.noverify", Usage: "Disable remote sealing verification", } + MinerNoAdvanceFlag = cli.BoolFlag{ + Name: "miner.noadvance", + Usage: "Disable advance sealing on an empty block", + } // Account settings UnlockedAccountFlag = cli.StringFlag{ Name: "unlock", @@ -1392,6 +1396,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) { cfg.MinerNoverify = ctx.Bool(MinerNoVerfiyFlag.Name) } + if ctx.GlobalIsSet(MinerNoAdvanceFlag.Name) { + cfg.MinerNoAdvance = ctx.Bool(MinerNoAdvanceFlag.Name) + } if ctx.GlobalIsSet(VMEnableDebugFlag.Name) { // TODO(fjl): force-enable this in --dev mode cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) diff --git a/eth/backend.go b/eth/backend.go index b13cb10289..98de0d7c1b 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -194,7 +194,8 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { return nil, err } - eth.miner = miner.New(eth, chainConfig, eth.EventMux(), eth.engine, config.MinerRecommit, config.MinerGasFloor, config.MinerGasCeil, eth.isLocalBlock) + // todo(rjl493456442) wrap all setting into a single config struct + eth.miner = miner.New(eth, chainConfig, eth.EventMux(), eth.engine, config.MinerRecommit, config.MinerGasFloor, config.MinerGasCeil, eth.isLocalBlock, config.MinerNoAdvance) eth.miner.SetExtra(makeExtraData(config.MinerExtraData)) eth.APIBackend = &EthAPIBackend{ctx.ExtRPCEnabled(), eth, nil} diff --git a/eth/config.go b/eth/config.go index d97ae3070d..3a2ffce175 100644 --- a/eth/config.go +++ b/eth/config.go @@ -127,6 +127,7 @@ type Config struct { MinerGasPrice *big.Int MinerRecommit time.Duration MinerNoverify bool + MinerNoAdvance bool // Ethash options Ethash ethash.Config diff --git a/miner/miner.go b/miner/miner.go index 5218c12107..68b5ea1662 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -52,13 +52,13 @@ type Miner struct { shouldStart int32 // should start indicates whether we should start after sync } -func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, recommit time.Duration, gasFloor, gasCeil uint64, isLocalBlock func(block *types.Block) bool) *Miner { +func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, recommit time.Duration, gasFloor, gasCeil uint64, isLocalBlock func(block *types.Block) bool, noAdvance bool) *Miner { miner := &Miner{ eth: eth, mux: mux, engine: engine, exitCh: make(chan struct{}), - worker: newWorker(config, engine, eth, mux, recommit, gasFloor, gasCeil, isLocalBlock), + worker: newWorker(config, engine, eth, mux, recommit, gasFloor, gasCeil, isLocalBlock, noAdvance), canStart: 1, } go miner.update() diff --git a/miner/worker.go b/miner/worker.go index a9e440aec5..25abbd80b9 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -178,7 +178,7 @@ type worker struct { resubmitHook func(time.Duration, time.Duration) // Method to call upon updating resubmitting interval. } -func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, recommit time.Duration, gasFloor, gasCeil uint64, isLocalBlock func(*types.Block) bool) *worker { +func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, recommit time.Duration, gasFloor, gasCeil uint64, isLocalBlock func(*types.Block) bool, noAdvance bool) *worker { worker := &worker{ config: config, engine: engine, @@ -216,7 +216,7 @@ func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend, } go worker.mainLoop() - go worker.newWorkLoop(recommit) + go worker.newWorkLoop(recommit, noAdvance) go worker.resultLoop() go worker.taskLoop() @@ -287,7 +287,7 @@ func (w *worker) close() { } // newWorkLoop is a standalone goroutine to submit new mining work upon received events. -func (w *worker) newWorkLoop(recommit time.Duration) { +func (w *worker) newWorkLoop(recommit time.Duration, noAdvance bool) { var ( interrupt *int32 minRecommit = recommit // minimal resubmit interval specified by user. @@ -302,6 +302,10 @@ func (w *worker) newWorkLoop(recommit time.Duration) { if interrupt != nil { atomic.StoreInt32(interrupt, s) } + // Disable advance sealing explicitly if user require. + if noAdvance { + noempty = true + } interrupt = new(int32) w.newWorkCh <- &newWorkReq{interrupt: interrupt, noempty: noempty, timestamp: timestamp} timer.Reset(recommit) @@ -468,9 +472,10 @@ func (w *worker) mainLoop() { w.commitTransactions(txset, coinbase, nil) w.updateSnapshot() } else { - // If we're mining, but nothing is being processed, wake on new transactions + // If clique is running in dev mode(period is 0), disable + // advance sealing here. if w.config.Clique != nil && w.config.Clique.Period == 0 { - w.commitNewWork(nil, false, time.Now().Unix()) + w.commitNewWork(nil, true, time.Now().Unix()) } } atomic.AddInt32(&w.newTxs, int32(len(ev.Txs)))