diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 26e28d43db..55799e7937 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -155,6 +155,9 @@ func loadBaseConfig(ctx *cli.Context) gethConfig { if err := loadConfig(file, &cfg); err != nil { utils.Fatalf("%v", err) } + // some default options could be overwritten after `loadConfig()` + // apply the default value if the options are not specified in config.toml file. + ethconfig.ApplyDefaultEthConfig(&cfg.Eth) } scheme := cfg.Eth.StateScheme diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index ec38bd8516..2bf32ab5c1 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -647,7 +647,7 @@ var ( MinerDelayLeftoverFlag = &cli.DurationFlag{ Name: "miner.delayleftover", Usage: "Time reserved to finalize a block", - Value: ethconfig.Defaults.Miner.DelayLeftOver, + Value: *ethconfig.Defaults.Miner.DelayLeftOver, Category: flags.MinerCategory, } @@ -1865,7 +1865,8 @@ func setMiner(ctx *cli.Context, cfg *minerconfig.Config) { cfg.Recommit = ctx.Duration(MinerRecommitIntervalFlag.Name) } if ctx.IsSet(MinerDelayLeftoverFlag.Name) { - cfg.DelayLeftOver = ctx.Duration(MinerDelayLeftoverFlag.Name) + minerDelayLeftover := ctx.Duration(MinerDelayLeftoverFlag.Name) + cfg.DelayLeftOver = &minerDelayLeftover } if ctx.Bool(VotingEnabledFlag.Name) { cfg.VoteEnable = true diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 40d118748e..de3fc353c1 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -215,3 +215,12 @@ func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database, ee *et } return beacon.New(ethash.NewFaker()), nil } + +func ApplyDefaultEthConfig(cfg *Config) { + if cfg == nil { + log.Warn("ApplyDefaultEthConfig cfg == nil") + return + } + + minerconfig.ApplyDefaultMinerConfig(&cfg.Miner) +} diff --git a/miner/bid_simulator.go b/miner/bid_simulator.go index 8068fd6261..da5be60841 100644 --- a/miner/bid_simulator.go +++ b/miner/bid_simulator.go @@ -119,38 +119,36 @@ type bidSimulator struct { func newBidSimulator( config *minerconfig.MevConfig, - delayLeftOver time.Duration, + delayLeftOver *time.Duration, minGasPrice *big.Int, eth Backend, chainConfig *params.ChainConfig, engine consensus.Engine, bidWorker bidWorker, ) *bidSimulator { - // Set default value - maxBids := uint32(3) - if config.MaxBidsPerBuilder > 0 { - maxBids = config.MaxBidsPerBuilder - } - b := &bidSimulator{ - config: config, - delayLeftOver: delayLeftOver, - minGasPrice: minGasPrice, - chain: eth.BlockChain(), - txpool: eth.TxPool(), - chainConfig: chainConfig, - engine: engine, - bidWorker: bidWorker, - maxBidsPerBuilder: maxBids, - exitCh: make(chan struct{}), - chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), - builders: make(map[common.Address]*builderclient.Client), - simBidCh: make(chan *simBidReq), - newBidCh: make(chan newBidPackage, 100), - pending: make(map[uint64]map[common.Address]map[common.Hash]struct{}), - bestBid: make(map[common.Hash]*BidRuntime), - bestBidToRun: make(map[common.Hash]*types.Bid), - simulatingBid: make(map[common.Hash]*BidRuntime), + config: config, + minGasPrice: minGasPrice, + chain: eth.BlockChain(), + txpool: eth.TxPool(), + chainConfig: chainConfig, + engine: engine, + bidWorker: bidWorker, + exitCh: make(chan struct{}), + chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), + builders: make(map[common.Address]*builderclient.Client), + simBidCh: make(chan *simBidReq), + newBidCh: make(chan newBidPackage, 100), + pending: make(map[uint64]map[common.Address]map[common.Hash]struct{}), + bestBid: make(map[common.Hash]*BidRuntime), + bestBidToRun: make(map[common.Hash]*types.Bid), + simulatingBid: make(map[common.Hash]*BidRuntime), + } + if delayLeftOver != nil { + b.delayLeftOver = *delayLeftOver + } + if config.MaxBidsPerBuilder != nil { + b.maxBidsPerBuilder = *config.MaxBidsPerBuilder } b.chainHeadSub = b.chain.SubscribeChainHeadEvent(b.chainHeadCh) @@ -360,7 +358,7 @@ func (b *bidSimulator) canBeInterrupted(targetTime uint64) bool { return true } left := time.Until(time.UnixMilli(int64(targetTime))) - return left >= b.config.NoInterruptLeftOver + return left >= *b.config.NoInterruptLeftOver } func (b *bidSimulator) newBidLoop() { @@ -396,7 +394,7 @@ func (b *bidSimulator) newBidLoop() { continue } - bidRuntime, err := newBidRuntime(newBid.bid, b.config.ValidatorCommission) + bidRuntime, err := newBidRuntime(newBid.bid, *b.config.ValidatorCommission) if err != nil { if newBid.feedback != nil { newBid.feedback <- err @@ -408,7 +406,7 @@ func (b *bidSimulator) newBidLoop() { toCommit := true bestBidToRun := b.GetBestBidToRun(newBid.bid.ParentHash) if bestBidToRun != nil { - bestBidRuntime, _ := newBidRuntime(bestBidToRun, b.config.ValidatorCommission) + bestBidRuntime, _ := newBidRuntime(bestBidToRun, *b.config.ValidatorCommission) if bidRuntime.isExpectedBetterThan(bestBidRuntime) { // new bid has better expectedBlockReward, use bidRuntime log.Debug("new bid has better expectedBlockReward", @@ -494,7 +492,7 @@ func (b *bidSimulator) getBlockInterval(parentHeader *types.Header) uint64 { func (b *bidSimulator) bidBetterBefore(parentHash common.Hash) time.Time { parentHeader := b.chain.GetHeaderByHash(parentHash) - return bidutil.BidBetterBefore(parentHeader, b.getBlockInterval(parentHeader), b.delayLeftOver, b.config.BidSimulationLeftOver) + return bidutil.BidBetterBefore(parentHeader, b.getBlockInterval(parentHeader), b.delayLeftOver, *b.config.BidSimulationLeftOver) } func (b *bidSimulator) clearLoop() { @@ -739,7 +737,7 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) { // check if bid reward is valid { - bidRuntime.packReward(b.config.ValidatorCommission) + bidRuntime.packReward(*b.config.ValidatorCommission) if !bidRuntime.validReward() { err = errors.New("reward does not achieve the expectation") return @@ -786,7 +784,7 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) { } // if enable greedy merge, fill bid env with transactions from mempool - if b.config.GreedyMergeTx { + if *b.config.GreedyMergeTx { endingBidsExtra := 20 * time.Millisecond // Add a buffer to ensure ending bids before `delayLeftOver` minTimeLeftForEndingBids := b.delayLeftOver + endingBidsExtra delay := b.engine.Delay(b.chain, bidRuntime.env.header, &minTimeLeftForEndingBids) @@ -802,7 +800,7 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) { "builder", bidRuntime.bid.Builder, "tx count", bidRuntime.env.tcount-bidTxLen+1, "err", fillErr) // recalculate the packed reward - bidRuntime.packReward(b.config.ValidatorCommission) + bidRuntime.packReward(*b.config.ValidatorCommission) } } diff --git a/miner/miner_mev.go b/miner/miner_mev.go index 9e5619a9ce..17b8cc98c0 100644 --- a/miner/miner_mev.go +++ b/miner/miner_mev.go @@ -97,9 +97,9 @@ func (miner *Miner) MevParams() *types.MevParams { } return &types.MevParams{ - ValidatorCommission: miner.worker.config.Mev.ValidatorCommission, - BidSimulationLeftOver: miner.worker.config.Mev.BidSimulationLeftOver, - NoInterruptLeftOver: miner.worker.config.Mev.NoInterruptLeftOver, + ValidatorCommission: *miner.worker.config.Mev.ValidatorCommission, + BidSimulationLeftOver: *miner.worker.config.Mev.BidSimulationLeftOver, + NoInterruptLeftOver: *miner.worker.config.Mev.NoInterruptLeftOver, GasCeil: miner.worker.config.GasCeil, GasPrice: miner.worker.config.GasPrice, BuilderFeeCeil: builderFeeCeil, diff --git a/miner/minerconfig/config.go b/miner/minerconfig/config.go index 00dc7b6b88..f1dd29e5ff 100644 --- a/miner/minerconfig/config.go +++ b/miner/minerconfig/config.go @@ -23,14 +23,25 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" ) +var ( + defaultDelayLeftOver = 50 * time.Millisecond + // default confogurations for MEV + defaultGreedyMergeTx bool = true + defaultValidatorCommission uint64 = 100 + defaultBidSimulationLeftOver = 50 * time.Millisecond + defaultNoInterruptLeftOver = 400 * time.Millisecond + defaultMaxBidsPerBuilder uint32 = 3 +) + // Config is the configuration parameters of mining. type Config struct { Etherbase common.Address `toml:",omitempty"` // Public address for block mining rewards ExtraData hexutil.Bytes `toml:",omitempty"` // Block extra data set by the miner - DelayLeftOver time.Duration // Time reserved to finalize a block(calculate root, distribute income...) + DelayLeftOver *time.Duration `toml:",omitempty"` // Time reserved to finalize a block(calculate root, distribute income...) GasFloor uint64 // Target gas floor for mined blocks. GasCeil uint64 // Target gas ceiling for mined blocks. GasPrice *big.Int // Minimum gas price for mining a transaction @@ -53,7 +64,7 @@ var DefaultConfig = Config{ // for payload generation. It should be enough for Geth to // run 3 rounds. Recommit: 3 * time.Second, - DelayLeftOver: 50 * time.Millisecond, + DelayLeftOver: &defaultDelayLeftOver, // The default value is set to 30 seconds. // Because the avg restart time in mainnet is around 30s, so the node try to wait for the next multi-proposals to be done. @@ -69,23 +80,57 @@ type BuilderConfig struct { type MevConfig struct { Enabled bool // Whether to enable Mev or not - GreedyMergeTx bool // Whether to merge local transactions to the bid + GreedyMergeTx *bool `toml:",omitempty"` // Whether to merge local transactions to the bid BuilderFeeCeil string // The maximum builder fee of a bid SentryURL string // The url of Mev sentry Builders []BuilderConfig // The list of builders - ValidatorCommission uint64 // 100 means the validator claims 1% from block reward - BidSimulationLeftOver time.Duration - NoInterruptLeftOver time.Duration - MaxBidsPerBuilder uint32 // Maximum number of bids allowed per builder per block + ValidatorCommission *uint64 `toml:",omitempty"` // 100 means the validator claims 1% from block reward + BidSimulationLeftOver *time.Duration `toml:",omitempty"` + NoInterruptLeftOver *time.Duration `toml:",omitempty"` + MaxBidsPerBuilder *uint32 `toml:",omitempty"` // Maximum number of bids allowed per builder per block } var DefaultMevConfig = MevConfig{ Enabled: false, - GreedyMergeTx: true, + GreedyMergeTx: &defaultGreedyMergeTx, SentryURL: "", Builders: nil, - ValidatorCommission: 100, - BidSimulationLeftOver: 50 * time.Millisecond, - NoInterruptLeftOver: 400 * time.Millisecond, - MaxBidsPerBuilder: 3, + ValidatorCommission: &defaultValidatorCommission, + BidSimulationLeftOver: &defaultBidSimulationLeftOver, + NoInterruptLeftOver: &defaultNoInterruptLeftOver, + MaxBidsPerBuilder: &defaultMaxBidsPerBuilder, +} + +func ApplyDefaultMinerConfig(cfg *Config) { + if cfg == nil { + log.Warn("ApplyDefaultMinerConfig cfg == nil") + return + } + // check [Eth.Miner] + if cfg.DelayLeftOver == nil { + cfg.DelayLeftOver = &defaultDelayLeftOver + log.Info("ApplyDefaultMinerConfig", "DelayLeftOver", *cfg.DelayLeftOver) + } + + // check [Eth.Miner.Mev] + if cfg.Mev.GreedyMergeTx == nil { + cfg.Mev.GreedyMergeTx = &defaultGreedyMergeTx + log.Info("ApplyDefaultMinerConfig", "Mev.GreedyMergeTx", *cfg.Mev.GreedyMergeTx) + } + if cfg.Mev.ValidatorCommission == nil { + cfg.Mev.ValidatorCommission = &defaultValidatorCommission + log.Info("ApplyDefaultMinerConfig", "Mev.ValidatorCommission", *cfg.Mev.ValidatorCommission) + } + if cfg.Mev.BidSimulationLeftOver == nil { + cfg.Mev.BidSimulationLeftOver = &defaultBidSimulationLeftOver + log.Info("ApplyDefaultMinerConfig", "Mev.BidSimulationLeftOver", *cfg.Mev.BidSimulationLeftOver) + } + if cfg.Mev.NoInterruptLeftOver == nil { + cfg.Mev.NoInterruptLeftOver = &defaultNoInterruptLeftOver + log.Info("ApplyDefaultMinerConfig", "Mev.NoInterruptLeftOver", *cfg.Mev.NoInterruptLeftOver) + } + if cfg.Mev.MaxBidsPerBuilder == nil { + cfg.Mev.MaxBidsPerBuilder = &defaultMaxBidsPerBuilder + log.Info("ApplyDefaultMinerConfig", "Mev.MaxBidsPerBuilder", *cfg.Mev.MaxBidsPerBuilder) + } } diff --git a/miner/worker.go b/miner/worker.go index 89dedca337..8a5bb0ebe1 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1292,7 +1292,7 @@ LOOP: prevWork = work workList = append(workList, work) - delay := w.engine.Delay(w.chain, work.header, &w.config.DelayLeftOver) + delay := w.engine.Delay(w.chain, work.header, w.config.DelayLeftOver) if delay == nil { log.Warn("commitWork delay is nil, something is wrong") stopTimer = nil @@ -1345,7 +1345,7 @@ LOOP: newTxsNum := 0 // stopTimer was the maximum delay for each fillTransactions // but now it is used to wait until (head.Time - DelayLeftOver) is reached. - stopTimer.Reset(time.Until(time.UnixMilli(int64(work.header.MilliTimestamp()))) - w.config.DelayLeftOver) + stopTimer.Reset(time.Until(time.UnixMilli(int64(work.header.MilliTimestamp()))) - *w.config.DelayLeftOver) LOOP_WAIT: for { select { @@ -1356,7 +1356,7 @@ LOOP: log.Debug("commitWork interruptCh closed, new block imported or resubmit triggered") return case ev := <-txsCh: - delay := w.engine.Delay(w.chain, work.header, &w.config.DelayLeftOver) + delay := w.engine.Delay(w.chain, work.header, w.config.DelayLeftOver) log.Debug("commitWork txsCh arrived", "fillDuration", fillDuration.String(), "delay", delay.String(), "work.tcount", work.tcount, "newTxsNum", newTxsNum, "len(ev.Txs)", len(ev.Txs)) @@ -1411,7 +1411,7 @@ LOOP: inturnBlocksGauge.Inc(1) // We want to start sealing the block as late as possible here if mev is enabled, so we could give builder the chance to send their final bid. // Time left till sealing the block. - tillSealingTime := time.Until(time.UnixMilli(int64(bestWork.header.MilliTimestamp()))) - w.config.DelayLeftOver + tillSealingTime := time.Until(time.UnixMilli(int64(bestWork.header.MilliTimestamp()))) - *w.config.DelayLeftOver if tillSealingTime > 0 { // Still some time left, wait for the best bid. // This happens during the peak time of the network, the local block building LOOP would break earlier than @@ -1441,7 +1441,7 @@ LOOP: if bestBid != nil && bestReward.CmpBig(bestBid.packedBlockReward) < 0 { // localValidatorReward is the reward for the validator self by the local block. - localValidatorReward := new(uint256.Int).Mul(bestReward, uint256.NewInt(w.config.Mev.ValidatorCommission)) + localValidatorReward := new(uint256.Int).Mul(bestReward, uint256.NewInt(*w.config.Mev.ValidatorCommission)) localValidatorReward.Div(localValidatorReward, uint256.NewInt(10000)) log.Debug("BidSimulator: final compare", "block", bestWork.header.Number.Uint64(),