Skip to content

Commit

Permalink
feat: enlarge bid
Browse files Browse the repository at this point in the history
  • Loading branch information
irrun committed Apr 7, 2024
1 parent 8f43835 commit 60e32b4
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 15 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
github.com/davecgh/go-spew v1.1.1
github.com/deckarep/golang-set/v2 v2.1.0
github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127
github.com/emirpasic/gods v1.18.1
github.com/ethereum/c-kzg-4844 v0.4.0
github.com/fatih/color v1.13.0
github.com/fatih/structs v1.1.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@ github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/dot v0.11.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
Expand Down
70 changes: 60 additions & 10 deletions miner/bid_simulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"sync/atomic"
"time"

"github.com/emirpasic/gods/sets/hashset"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/bidutil"
"github.com/ethereum/go-ethereum/consensus"
Expand All @@ -34,6 +36,8 @@ const (
leftOverTimeRate = 11
// leftOverTimeScale is the scale of left over time to simulate a bid
leftOverTimeScale = 10

PayBidTxGas uint64 = 21000 // The gas reserved for pay bid tx
)

var (
Expand Down Expand Up @@ -64,6 +68,7 @@ var (
type WorkPreparer interface {
prepareWork(params *generateParams) (*environment, error)
etherbase() common.Address
fillTransactions(interruptCh chan int32, env *environment, stopTimer *time.Timer, bidTxs *hashset.Set) (err error)
}

// simBidReq is the request for simulating a bid
Expand All @@ -79,6 +84,7 @@ type bidSimulator struct {
delayLeftOver time.Duration
chain *core.BlockChain
chainConfig *params.ChainConfig
engine consensus.Engine
workPreparer WorkPreparer

running atomic.Bool // controlled by miner
Expand Down Expand Up @@ -112,15 +118,17 @@ type bidSimulator struct {
func newBidSimulator(
config *MevConfig,
delayLeftOver time.Duration,
chainConfig *params.ChainConfig,
chain *core.BlockChain,
chainConfig *params.ChainConfig,
engine consensus.Engine,
workPreparer WorkPreparer,
) *bidSimulator {
b := &bidSimulator{
config: config,
delayLeftOver: delayLeftOver,
chainConfig: chainConfig,
chain: chain,
chainConfig: chainConfig,
engine: engine,
workPreparer: workPreparer,
exitCh: make(chan struct{}),
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
Expand Down Expand Up @@ -354,8 +362,6 @@ func (b *bidSimulator) newBidLoop() {
packedValidatorReward: big.NewInt(0),
}

// TODO(renee-) opt bid comparation

simulatingBid := b.GetSimulatingBid(newBid.ParentHash)
// simulatingBid is nil means there is no bid in simulation
if simulatingBid == nil {
Expand Down Expand Up @@ -500,8 +506,13 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
blockNumber = bidRuntime.bid.BlockNumber
parentHash = bidRuntime.bid.ParentHash
builder = bidRuntime.bid.Builder
err error
success bool

bidTxs = bidRuntime.bid.Txs
bidLen = len(bidTxs)
payBidTx = bidTxs[bidLen-1]

err error
success bool
)

// ensure simulation exited then start next simulation
Expand Down Expand Up @@ -572,17 +583,16 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
default:
}

// Start executing the transaction
bidRuntime.env.state.SetTxContext(tx.Hash(), bidRuntime.env.tcount)
if bidRuntime.env.tcount == bidLen-1 {
break
}

err = bidRuntime.commitTransaction(b.chain, b.chainConfig, tx)
if err != nil {
log.Error("BidSimulator: failed to commit tx", "bidHash", bidRuntime.bid.Hash(), "tx", tx.Hash(), "err", err)
err = fmt.Errorf("invalid tx in bid, %v", err)
return
}

bidRuntime.env.tcount++
}

bidRuntime.packReward(b.config.ValidatorCommission)
Expand All @@ -593,6 +603,41 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
return
}

// fill transactions from mempool
if b.config.EnlargeBid {
delay := b.engine.Delay(b.chain, bidRuntime.env.header, &b.delayLeftOver)
if delay != nil || *delay > 0 {
log.Debug("BidSimulator: stopTimer", "block", bidRuntime.env.header.Number,
"header time", time.Until(time.Unix(int64(bidRuntime.env.header.Time), 0)),
"commit delay", *delay, "DelayLeftOver", b.delayLeftOver)

stopTimer := time.NewTimer(0)
defer stopTimer.Stop()
<-stopTimer.C // discard the initial tick

stopTimer.Reset(*delay)

bidTxsSet := hashset.New()
for _, tx := range bidRuntime.bid.Txs {
bidTxsSet.Add(tx.Hash())
}

bidRuntime.env.gasPool.SubGas(PayBidTxGas)

_ = b.workPreparer.fillTransactions(interruptCh, bidRuntime.env, stopTimer, bidTxsSet)

// recalculate the packed reward
bidRuntime.packReward(b.config.ValidatorCommission)
}
}

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)
err = fmt.Errorf("invalid tx in bid, %v", err)
return
}

bestBid := b.GetBestBid(parentHash)

if bestBid == nil {
Expand Down Expand Up @@ -663,6 +708,9 @@ func (r *BidRuntime) commitTransaction(chain *core.BlockChain, chainConfig *para
sc *types.BlobSidecar
)

// Start executing the transaction
r.env.state.SetTxContext(tx.Hash(), r.env.tcount)

if tx.Type() == types.BlobTxType {
sc := types.NewBlobSidecarFromTx(tx)
if sc == nil {
Expand Down Expand Up @@ -697,5 +745,7 @@ func (r *BidRuntime) commitTransaction(chain *core.BlockChain, chainConfig *para
env.receipts = append(env.receipts, receipt)
}

r.env.tcount++

return nil
}
2 changes: 1 addition & 1 deletion miner/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func New(eth Backend, config *Config, chainConfig *params.ChainConfig, mux *even
worker: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock, false),
}

miner.bidSimulator = newBidSimulator(&config.Mev, config.DelayLeftOver, chainConfig, eth.BlockChain(), miner.worker)
miner.bidSimulator = newBidSimulator(&config.Mev, config.DelayLeftOver, eth.BlockChain(), chainConfig, engine, miner.worker)
miner.worker.setBestBidFetcher(miner.bidSimulator)

miner.wg.Add(1)
Expand Down
3 changes: 2 additions & 1 deletion miner/miner_mev.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ type BuilderConfig struct {

type MevConfig struct {
Enabled bool // Whether to enable Mev or not
EnlargeBid bool // Whether to append 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 1%
ValidatorCommission uint64 // 100 means the validator claims 1% from block reward
BidSimulationLeftOver time.Duration
}

Expand Down
33 changes: 30 additions & 3 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"sync/atomic"
"time"

"github.com/emirpasic/gods/sets/hashset"
lru "github.com/hashicorp/golang-lru"
"github.com/holiman/uint256"

Expand Down Expand Up @@ -1045,7 +1046,7 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
// fillTransactions retrieves the pending transactions from the txpool and fills them
// into the given sealing block. The transaction selection and ordering strategy can
// be customized with the plugin in the future.
func (w *worker) fillTransactions(interruptCh chan int32, env *environment, stopTimer *time.Timer) (err error) {
func (w *worker) fillTransactions(interruptCh chan int32, env *environment, stopTimer *time.Timer, bidTxs *hashset.Set) (err error) {
w.mu.RLock()
tip := w.tip
w.mu.RUnlock()
Expand Down Expand Up @@ -1080,6 +1081,32 @@ func (w *worker) fillTransactions(interruptCh chan int32, env *environment, stop
localBlobTxs[account] = txs
}
}

if bidTxs != nil {
var wg sync.WaitGroup
wg.Add(4)

filterBidTxs := func(commonTxs map[common.Address][]*txpool.LazyTransaction) {
defer wg.Done()
for acc, txs := range commonTxs {
newTxs := make([]*txpool.LazyTransaction, 0)
for _, tx := range txs {
if !bidTxs.Contains(tx.Hash) {
newTxs = append(newTxs, tx)
}
}
commonTxs[acc] = newTxs
}
}

go filterBidTxs(localPlainTxs)
go filterBidTxs(localBlobTxs)
go filterBidTxs(remotePlainTxs)
go filterBidTxs(remoteBlobTxs)

wg.Wait()
}

// Fill the block with all available pending transactions.
// we will abort when:
// 1.new block was imported
Expand Down Expand Up @@ -1116,7 +1143,7 @@ func (w *worker) generateWork(params *generateParams) *newPayloadResult {
defer work.discard()

if !params.noTxs {
err := w.fillTransactions(nil, work, nil)
err := w.fillTransactions(nil, work, nil, nil)
if errors.Is(err, errBlockInterruptedByTimeout) {
log.Warn("Block building is interrupted", "allowance", common.PrettyDuration(w.newpayloadTimeout))
}
Expand Down Expand Up @@ -1216,7 +1243,7 @@ LOOP:

// Fill pending transactions from the txpool into the block.
fillStart := time.Now()
err = w.fillTransactions(interruptCh, work, stopTimer)
err = w.fillTransactions(interruptCh, work, stopTimer, nil)
fillDuration := time.Since(fillStart)
switch {
case errors.Is(err, errBlockInterruptedByNewHead):
Expand Down

0 comments on commit 60e32b4

Please sign in to comment.