diff --git a/miner/bid_simulator.go b/miner/bid_simulator.go index e3cf5c6e9b..477f2052ea 100644 --- a/miner/bid_simulator.go +++ b/miner/bid_simulator.go @@ -30,8 +30,6 @@ const ( // maxBidPerBuilderPerBlock is the max bid number per builder maxBidPerBuilderPerBlock = 3 - commitInterruptBetterBid = 1 - // leftOverTimeRate is the rate of left over time to simulate a bid leftOverTimeRate = 11 // leftOverTimeScale is the scale of left over time to simulate a bid @@ -311,8 +309,6 @@ func (b *bidSimulator) newBidLoop() { // commit aborts in-flight bid execution with given signal and resubmits a new one. commit := func(reason int32, bidRuntime *BidRuntime) { - log.Debug("BidSimulator: start", "bidHash", bidRuntime.bid.Hash().Hex()) - // if the left time is not enough to do simulation, return var simDuration time.Duration if lastBid := b.GetBestBid(bidRuntime.bid.ParentHash); lastBid != nil && lastBid.duration != 0 { @@ -320,7 +316,8 @@ func (b *bidSimulator) newBidLoop() { } if time.Until(b.bidMustBefore(bidRuntime.bid.ParentHash)) <= simDuration*leftOverTimeRate/leftOverTimeScale { - log.Debug("BidSimulator: abort commit, not enough time to simulate", "bidHash", bidRuntime.bid.Hash().Hex()) + log.Debug("BidSimulator: abort commit, not enough time to simulate", + "builder", bidRuntime.bid.Builder, "bidHash", bidRuntime.bid.Hash().Hex()) return } @@ -332,6 +329,7 @@ func (b *bidSimulator) newBidLoop() { interruptCh = make(chan int32, 1) select { case b.simBidCh <- &simBidReq{interruptCh: interruptCh, bid: bidRuntime}: + log.Debug("BidSimulator: commit", "builder", bidRuntime.bid.Builder, "bidHash", bidRuntime.bid.Hash().Hex()) case <-b.exitCh: return } @@ -352,7 +350,8 @@ func (b *bidSimulator) newBidLoop() { if expectedValidatorReward.Cmp(big.NewInt(0)) < 0 { // damage self profit, ignore - log.Debug("BidSimulator: invalid bid, validator reward is less than 0, ignore", "bidHash", newBid.Hash().Hex()) + log.Debug("BidSimulator: invalid bid, validator reward is less than 0, ignore", + "builder", newBid.Builder, "bidHash", newBid.Hash().Hex()) continue } @@ -375,26 +374,27 @@ func (b *bidSimulator) newBidLoop() { } // if bestBid is not nil, check if newBid is better than bestBid - if bidRuntime.expectedBlockReward.Cmp(bestBid.expectedBlockReward) > 0 && - bidRuntime.expectedValidatorReward.Cmp(bestBid.expectedValidatorReward) > 0 { + if bidRuntime.expectedBlockReward.Cmp(bestBid.expectedBlockReward) >= 0 && + bidRuntime.expectedValidatorReward.Cmp(bestBid.expectedValidatorReward) >= 0 { // if both reward are better than last simulating newBid, commit for simulation commit(commitInterruptBetterBid, bidRuntime) continue } - log.Debug("BidSimulator: lower reward, ignore", "bidHash", newBid.Hash().Hex()) + log.Debug("BidSimulator: lower reward, ignore", + "builder", bidRuntime.bid.Builder, "bidHash", newBid.Hash().Hex()) continue } // simulatingBid must be better than bestBid, if newBid is better than simulatingBid, commit for simulation - if bidRuntime.expectedBlockReward.Cmp(simulatingBid.expectedBlockReward) > 0 && - bidRuntime.expectedValidatorReward.Cmp(simulatingBid.expectedValidatorReward) > 0 { + if bidRuntime.expectedBlockReward.Cmp(simulatingBid.expectedBlockReward) >= 0 && + bidRuntime.expectedValidatorReward.Cmp(simulatingBid.expectedValidatorReward) >= 0 { // if both reward are better than last simulating newBid, commit for simulation commit(commitInterruptBetterBid, bidRuntime) continue } - log.Debug("BidSimulator: lower reward, ignore", "bidHash", newBid.Hash().Hex()) + log.Debug("BidSimulator: lower reward, ignore", "builder", newBid.Builder, "bidHash", newBid.Hash().Hex()) case <-b.exitCh: return } @@ -546,12 +546,23 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) { go b.reportIssue(bidRuntime, err) } + b.RemoveSimulatingBid(parentHash) + bidSimTimer.UpdateSince(start) + if success { bidRuntime.duration = time.Since(simStart) - } - b.RemoveSimulatingBid(parentHash) - bidSimTimer.UpdateSince(start) + // only recommit self bid when newBidCh is empty + if len(b.newBidCh) > 0 { + return + } + + select { + case b.newBidCh <- bidRuntime.bid: + log.Debug("BidSimulator: recommit", "builder", bidRuntime.bid.Builder, "bidHash", bidRuntime.bid.Hash().Hex()) + default: + } + } }(time.Now()) // prepareWork will configure header with a suitable time according to consensus @@ -612,7 +623,8 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) { if b.config.GreedyMergeTx { delay := b.engine.Delay(b.chain, bidRuntime.env.header, &b.delayLeftOver) if delay != nil && *delay > 0 { - log.Debug("BidSimulator: greedy merge tx stopTimer", "block", bidRuntime.env.header.Number, + log.Debug("BidSimulator: greedy merge stopTimer", "block", bidRuntime.env.header.Number, + "builder", bidRuntime.bid.Builder, "header time", time.Until(time.Unix(int64(bidRuntime.env.header.Time), 0)), "commit delay", *delay, "DelayLeftOver", b.delayLeftOver) @@ -624,8 +636,8 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) { } fillErr := b.bidWorker.fillTransactions(interruptCh, bidRuntime.env, stopTimer, bidTxsSet) - log.Info("BidSimulator: greedy merge tx fill transactions", "block", bidRuntime.env.header.Number, - "tx count", bidRuntime.env.tcount-bidTxLen+1, "err", fillErr) + log.Info("BidSimulator: greedy merge stopped", "block", bidRuntime.env.header.Number, + "builder", bidRuntime.bid.Builder, "tx count", bidRuntime.env.tcount-bidTxLen+1, "err", fillErr) // recalculate the packed reward bidRuntime.packReward(b.config.ValidatorCommission) @@ -635,7 +647,8 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) { bidRuntime.env.gasPool.AddGas(params.PayBidTxGasLimit) err = bidRuntime.commitTransaction(b.chain, b.chainConfig, payBidTx) if err != nil { - log.Error("BidSimulator: failed to commit tx", "bidHash", bidRuntime.bid.Hash(), "tx", payBidTx.Hash(), "err", err) + log.Error("BidSimulator: failed to commit tx", "builder", bidRuntime.bid.Builder, + "bidHash", bidRuntime.bid.Hash(), "tx", payBidTx.Hash(), "err", err) err = fmt.Errorf("invalid tx in bid, %v", err) return } @@ -649,11 +662,22 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) { } // this is the simplest strategy: best for all the delegators. - if bidRuntime.packedBlockReward.Cmp(bestBid.packedBlockReward) > 0 { + if bidRuntime.packedBlockReward.Cmp(bestBid.packedBlockReward) >= 0 { b.SetBestBid(bidRuntime.bid.ParentHash, bidRuntime) success = true return } + + // only recommit last best bid when newBidCh is empty + if len(b.newBidCh) > 0 { + return + } + + select { + case b.newBidCh <- bestBid.bid: + log.Debug("BidSimulator: recommit last bid", "builder", bidRuntime.bid.Builder, "bidHash", bidRuntime.bid.Hash().Hex()) + default: + } } // reportIssue reports the issue to the mev-sentry diff --git a/miner/worker.go b/miner/worker.go index 2cc2ff00ab..6efcf3496a 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -73,10 +73,11 @@ var ( writeBlockTimer = metrics.NewRegisteredTimer("worker/writeblock", nil) finalizeBlockTimer = metrics.NewRegisteredTimer("worker/finalizeblock", nil) - errBlockInterruptedByNewHead = errors.New("new head arrived while building block") - errBlockInterruptedByRecommit = errors.New("recommit interrupt while building block") - errBlockInterruptedByTimeout = errors.New("timeout while building block") - errBlockInterruptedByOutOfGas = errors.New("out of gas while building block") + errBlockInterruptedByNewHead = errors.New("new head arrived while building block") + errBlockInterruptedByRecommit = errors.New("recommit interrupt while building block") + errBlockInterruptedByTimeout = errors.New("timeout while building block") + errBlockInterruptedByOutOfGas = errors.New("out of gas while building block") + errBlockInterruptedByBetterBid = errors.New("better bid arrived while building block") ) // environment is the worker's current environment and holds all @@ -144,6 +145,7 @@ const ( commitInterruptResubmit commitInterruptTimeout commitInterruptOutOfGas + commitInterruptBetterBid ) // newWorkReq represents a request for new sealing work submitting with relative interrupt notifier. @@ -1480,6 +1482,8 @@ func signalToErr(signal int32) error { return errBlockInterruptedByTimeout case commitInterruptOutOfGas: return errBlockInterruptedByOutOfGas + case commitInterruptBetterBid: + return errBlockInterruptedByBetterBid default: panic(fmt.Errorf("undefined signal %d", signal)) }