Skip to content

Commit

Permalink
fix: waiting for the last simulation before pick best bid (#2507)
Browse files Browse the repository at this point in the history
  • Loading branch information
irrun authored Jun 7, 2024
1 parent 1047f0e commit af7e9b9
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 27 deletions.
40 changes: 13 additions & 27 deletions miner/bid_simulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ import (
const (
// maxBidPerBuilderPerBlock is the max bid number per builder
maxBidPerBuilderPerBlock = 3

// 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
leftOverTimeScale = 10
)

var (
Expand Down Expand Up @@ -318,18 +313,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) {
// 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 {
simDuration = lastBid.duration
}

if time.Until(b.bidMustBefore(bidRuntime.bid.ParentHash)) <= simDuration*leftOverTimeRate/leftOverTimeScale {
log.Debug("BidSimulator: abort commit, not enough time to simulate",
"builder", bidRuntime.bid.Builder, "bidHash", bidRuntime.bid.Hash().Hex())
return
}

if interruptCh != nil {
// each commit work will have its own interruptCh to stop work with a reason
interruptCh <- reason
Expand Down Expand Up @@ -370,6 +353,7 @@ func (b *bidSimulator) newBidLoop() {
expectedValidatorReward: expectedValidatorReward,
packedBlockReward: big.NewInt(0),
packedValidatorReward: big.NewInt(0),
finished: make(chan struct{}),
}

simulatingBid := b.GetSimulatingBid(newBid.ParentHash)
Expand Down Expand Up @@ -410,11 +394,6 @@ func (b *bidSimulator) newBidLoop() {
}
}

func (b *bidSimulator) bidMustBefore(parentHash common.Hash) time.Time {
parentHeader := b.chain.GetHeaderByHash(parentHash)
return bidutil.BidMustBefore(parentHeader, b.chainConfig.Parlia.Period, b.delayLeftOver)
}

func (b *bidSimulator) bidBetterBefore(parentHash common.Hash) time.Time {
parentHeader := b.chain.GetHeaderByHash(parentHash)
return bidutil.BidBetterBefore(parentHeader, b.chainConfig.Parlia.Period, b.delayLeftOver, b.config.BidSimulationLeftOver)
Expand Down Expand Up @@ -530,7 +509,6 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {

// ensure simulation exited then start next simulation
b.SetSimulatingBid(parentHash, bidRuntime)
start := time.Now()

defer func(simStart time.Time) {
logCtx := []any{
Expand All @@ -556,10 +534,11 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
}

b.RemoveSimulatingBid(parentHash)
bidSimTimer.UpdateSince(start)
close(bidRuntime.finished)

if success {
bidRuntime.duration = time.Since(simStart)
bidSimTimer.UpdateSince(simStart)

// only recommit self bid when newBidCh is empty
if len(b.newBidCh) > 0 {
Expand All @@ -583,6 +562,14 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
return
}

// if the left time is not enough to do simulation, return
delay := b.engine.Delay(b.chain, bidRuntime.env.header, &b.delayLeftOver)
if delay == nil || *delay <= 0 {
log.Info("BidSimulator: abort commit, not enough time to simulate",
"builder", bidRuntime.bid.Builder, "bidHash", bidRuntime.bid.Hash().Hex())
return
}

gasLimit := bidRuntime.env.header.GasLimit
if bidRuntime.env.gasPool == nil {
bidRuntime.env.gasPool = new(core.GasPool).AddGas(gasLimit)
Expand Down Expand Up @@ -650,14 +637,12 @@ 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 {
stopTimer := time.NewTimer(*delay)

bidTxsSet := mapset.NewSet[common.Hash]()
for _, tx := range bidRuntime.bid.Txs {
bidTxsSet.Add(tx.Hash())
}

fillErr := b.bidWorker.fillTransactions(interruptCh, bidRuntime.env, stopTimer, bidTxsSet)
fillErr := b.bidWorker.fillTransactions(interruptCh, bidRuntime.env, nil, bidTxsSet)
log.Trace("BidSimulator: greedy merge stopped", "block", bidRuntime.env.header.Number,
"builder", bidRuntime.bid.Builder, "tx count", bidRuntime.env.tcount-bidTxLen+1, "err", fillErr)

Expand Down Expand Up @@ -733,6 +718,7 @@ type BidRuntime struct {
packedBlockReward *big.Int
packedValidatorReward *big.Int

finished chan struct{}
duration time.Duration
}

Expand Down
13 changes: 13 additions & 0 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ const (
// the current 4 mining loops could have asynchronous risk of mining block with
// save height, keep recently mined blocks to avoid double sign for safety,
recentMinedCacheLimit = 20

// the default to wait for the mev miner to finish
waitMEVMinerEndTimeLimit = 50 * time.Millisecond
)

var (
Expand Down Expand Up @@ -171,6 +174,7 @@ type getWorkReq struct {

type bidFetcher interface {
GetBestBid(parentHash common.Hash) *BidRuntime
GetSimulatingBid(prevBlockHash common.Hash) *BidRuntime
}

// worker is the main object which takes care of submitting new work to consensus engine
Expand Down Expand Up @@ -1336,6 +1340,15 @@ LOOP:
// when in-turn, compare with remote work.
from := bestWork.coinbase
if w.bidFetcher != nil && bestWork.header.Difficulty.Cmp(diffInTurn) == 0 {
if pendingBid := w.bidFetcher.GetSimulatingBid(bestWork.header.ParentHash); pendingBid != nil {
waitBidTimer := time.NewTimer(waitMEVMinerEndTimeLimit)
defer waitBidTimer.Stop()
select {
case <-waitBidTimer.C:
case <-pendingBid.finished:
}
}

bestBid := w.bidFetcher.GetBestBid(bestWork.header.ParentHash)

if bestBid != nil {
Expand Down

0 comments on commit af7e9b9

Please sign in to comment.