feat: recommit bid when newBidCh is empty to maximize mev reward (#2424)
This commit is contained in:
parent
6573254a62
commit
ba6726325a
@ -30,8 +30,6 @@ const (
|
|||||||
// maxBidPerBuilderPerBlock is the max bid number per builder
|
// maxBidPerBuilderPerBlock is the max bid number per builder
|
||||||
maxBidPerBuilderPerBlock = 3
|
maxBidPerBuilderPerBlock = 3
|
||||||
|
|
||||||
commitInterruptBetterBid = 1
|
|
||||||
|
|
||||||
// leftOverTimeRate is the rate of left over time to simulate a bid
|
// leftOverTimeRate is the rate of left over time to simulate a bid
|
||||||
leftOverTimeRate = 11
|
leftOverTimeRate = 11
|
||||||
// leftOverTimeScale is the scale of left over time to simulate a bid
|
// 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 aborts in-flight bid execution with given signal and resubmits a new one.
|
||||||
commit := func(reason int32, bidRuntime *BidRuntime) {
|
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
|
// if the left time is not enough to do simulation, return
|
||||||
var simDuration time.Duration
|
var simDuration time.Duration
|
||||||
if lastBid := b.GetBestBid(bidRuntime.bid.ParentHash); lastBid != nil && lastBid.duration != 0 {
|
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 {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,6 +329,7 @@ func (b *bidSimulator) newBidLoop() {
|
|||||||
interruptCh = make(chan int32, 1)
|
interruptCh = make(chan int32, 1)
|
||||||
select {
|
select {
|
||||||
case b.simBidCh <- &simBidReq{interruptCh: interruptCh, bid: bidRuntime}:
|
case b.simBidCh <- &simBidReq{interruptCh: interruptCh, bid: bidRuntime}:
|
||||||
|
log.Debug("BidSimulator: commit", "builder", bidRuntime.bid.Builder, "bidHash", bidRuntime.bid.Hash().Hex())
|
||||||
case <-b.exitCh:
|
case <-b.exitCh:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -352,7 +350,8 @@ func (b *bidSimulator) newBidLoop() {
|
|||||||
|
|
||||||
if expectedValidatorReward.Cmp(big.NewInt(0)) < 0 {
|
if expectedValidatorReward.Cmp(big.NewInt(0)) < 0 {
|
||||||
// damage self profit, ignore
|
// 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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,26 +374,27 @@ func (b *bidSimulator) newBidLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if bestBid is not nil, check if newBid is better than bestBid
|
// if bestBid is not nil, check if newBid is better than bestBid
|
||||||
if bidRuntime.expectedBlockReward.Cmp(bestBid.expectedBlockReward) > 0 &&
|
if bidRuntime.expectedBlockReward.Cmp(bestBid.expectedBlockReward) >= 0 &&
|
||||||
bidRuntime.expectedValidatorReward.Cmp(bestBid.expectedValidatorReward) > 0 {
|
bidRuntime.expectedValidatorReward.Cmp(bestBid.expectedValidatorReward) >= 0 {
|
||||||
// if both reward are better than last simulating newBid, commit for simulation
|
// if both reward are better than last simulating newBid, commit for simulation
|
||||||
commit(commitInterruptBetterBid, bidRuntime)
|
commit(commitInterruptBetterBid, bidRuntime)
|
||||||
continue
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// simulatingBid must be better than bestBid, if newBid is better than simulatingBid, commit for simulation
|
// simulatingBid must be better than bestBid, if newBid is better than simulatingBid, commit for simulation
|
||||||
if bidRuntime.expectedBlockReward.Cmp(simulatingBid.expectedBlockReward) > 0 &&
|
if bidRuntime.expectedBlockReward.Cmp(simulatingBid.expectedBlockReward) >= 0 &&
|
||||||
bidRuntime.expectedValidatorReward.Cmp(simulatingBid.expectedValidatorReward) > 0 {
|
bidRuntime.expectedValidatorReward.Cmp(simulatingBid.expectedValidatorReward) >= 0 {
|
||||||
// if both reward are better than last simulating newBid, commit for simulation
|
// if both reward are better than last simulating newBid, commit for simulation
|
||||||
commit(commitInterruptBetterBid, bidRuntime)
|
commit(commitInterruptBetterBid, bidRuntime)
|
||||||
continue
|
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:
|
case <-b.exitCh:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -546,12 +546,23 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
|
|||||||
go b.reportIssue(bidRuntime, err)
|
go b.reportIssue(bidRuntime, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if success {
|
|
||||||
bidRuntime.duration = time.Since(simStart)
|
|
||||||
}
|
|
||||||
|
|
||||||
b.RemoveSimulatingBid(parentHash)
|
b.RemoveSimulatingBid(parentHash)
|
||||||
bidSimTimer.UpdateSince(start)
|
bidSimTimer.UpdateSince(start)
|
||||||
|
|
||||||
|
if success {
|
||||||
|
bidRuntime.duration = time.Since(simStart)
|
||||||
|
|
||||||
|
// 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())
|
}(time.Now())
|
||||||
|
|
||||||
// prepareWork will configure header with a suitable time according to consensus
|
// 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 {
|
if b.config.GreedyMergeTx {
|
||||||
delay := b.engine.Delay(b.chain, bidRuntime.env.header, &b.delayLeftOver)
|
delay := b.engine.Delay(b.chain, bidRuntime.env.header, &b.delayLeftOver)
|
||||||
if delay != nil && *delay > 0 {
|
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)),
|
"header time", time.Until(time.Unix(int64(bidRuntime.env.header.Time), 0)),
|
||||||
"commit delay", *delay, "DelayLeftOver", b.delayLeftOver)
|
"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)
|
fillErr := b.bidWorker.fillTransactions(interruptCh, bidRuntime.env, stopTimer, bidTxsSet)
|
||||||
log.Info("BidSimulator: greedy merge tx fill transactions", "block", bidRuntime.env.header.Number,
|
log.Info("BidSimulator: greedy merge stopped", "block", bidRuntime.env.header.Number,
|
||||||
"tx count", bidRuntime.env.tcount-bidTxLen+1, "err", fillErr)
|
"builder", bidRuntime.bid.Builder, "tx count", bidRuntime.env.tcount-bidTxLen+1, "err", fillErr)
|
||||||
|
|
||||||
// recalculate the packed reward
|
// recalculate the packed reward
|
||||||
bidRuntime.packReward(b.config.ValidatorCommission)
|
bidRuntime.packReward(b.config.ValidatorCommission)
|
||||||
@ -635,7 +647,8 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
|
|||||||
bidRuntime.env.gasPool.AddGas(params.PayBidTxGasLimit)
|
bidRuntime.env.gasPool.AddGas(params.PayBidTxGasLimit)
|
||||||
err = bidRuntime.commitTransaction(b.chain, b.chainConfig, payBidTx)
|
err = bidRuntime.commitTransaction(b.chain, b.chainConfig, payBidTx)
|
||||||
if err != nil {
|
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)
|
err = fmt.Errorf("invalid tx in bid, %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -649,11 +662,22 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this is the simplest strategy: best for all the delegators.
|
// 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)
|
b.SetBestBid(bidRuntime.bid.ParentHash, bidRuntime)
|
||||||
success = true
|
success = true
|
||||||
return
|
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
|
// reportIssue reports the issue to the mev-sentry
|
||||||
|
@ -77,6 +77,7 @@ var (
|
|||||||
errBlockInterruptedByRecommit = errors.New("recommit interrupt while building block")
|
errBlockInterruptedByRecommit = errors.New("recommit interrupt while building block")
|
||||||
errBlockInterruptedByTimeout = errors.New("timeout while building block")
|
errBlockInterruptedByTimeout = errors.New("timeout while building block")
|
||||||
errBlockInterruptedByOutOfGas = errors.New("out of gas 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
|
// environment is the worker's current environment and holds all
|
||||||
@ -145,6 +146,7 @@ const (
|
|||||||
commitInterruptResubmit
|
commitInterruptResubmit
|
||||||
commitInterruptTimeout
|
commitInterruptTimeout
|
||||||
commitInterruptOutOfGas
|
commitInterruptOutOfGas
|
||||||
|
commitInterruptBetterBid
|
||||||
)
|
)
|
||||||
|
|
||||||
// newWorkReq represents a request for new sealing work submitting with relative interrupt notifier.
|
// newWorkReq represents a request for new sealing work submitting with relative interrupt notifier.
|
||||||
@ -1481,6 +1483,8 @@ func signalToErr(signal int32) error {
|
|||||||
return errBlockInterruptedByTimeout
|
return errBlockInterruptedByTimeout
|
||||||
case commitInterruptOutOfGas:
|
case commitInterruptOutOfGas:
|
||||||
return errBlockInterruptedByOutOfGas
|
return errBlockInterruptedByOutOfGas
|
||||||
|
case commitInterruptBetterBid:
|
||||||
|
return errBlockInterruptedByBetterBid
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("undefined signal %d", signal))
|
panic(fmt.Errorf("undefined signal %d", signal))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user