Add mevBoostLoop for requesting mev-boost service for new payload

perioidcally
This commit is contained in:
Jinsuk Park 2023-08-24 15:36:14 +09:00
parent d130217ca2
commit c6db52ee8c
No known key found for this signature in database
GPG key ID: A9356F9336B44ED3
2 changed files with 77 additions and 5 deletions

View file

@ -52,8 +52,9 @@ type Config struct {
GasPrice *big.Int // Minimum gas price for mining a transaction
Recommit time.Duration // The time interval for miner to re-create mining work.
NewPayloadTimeout time.Duration // The maximum time allowance for creating a new payload
MevBoostUrl string // URL to mev boost.
NewPayloadTimeout time.Duration // The maximum time allowance for creating a new payload
MevBoostUrl string // URL to mev boost.
MevBoostRequestInterval time.Duration // The interval for requesting mev boost for new block
}
// DefaultConfig contains default settings for miner.
@ -65,8 +66,9 @@ var DefaultConfig = Config{
// consensus-layer usually will wait a half slot of time(6s)
// for payload generation. It should be enough for Geth to
// run 3 rounds.
Recommit: 2 * time.Second,
NewPayloadTimeout: 2 * time.Second,
Recommit: 2 * time.Second,
NewPayloadTimeout: 2 * time.Second,
MevBoostRequestInterval: 1 * time.Second,
}
// Miner creates blocks and searches for proof-of-work values.

View file

@ -17,13 +17,16 @@
package miner
import (
"encoding/json"
"errors"
"fmt"
"math/big"
"net/http"
"sync"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
@ -205,6 +208,9 @@ type worker struct {
snapshotReceipts types.Receipts
snapshotState *state.StateDB
mevSnapshotBlockMu sync.RWMutex // The lock used to protect the mevSnapshotBlock below
mevSnapshotBlock *types.Block
// atomic status counters
running atomic.Bool // The indicator whether the consensus engine is running or not.
newTxs atomic.Int32 // New arrival transaction count since last sealing work submitting.
@ -278,12 +284,15 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
}
worker.newpayloadTimeout = newpayloadTimeout
worker.wg.Add(4)
worker.wg.Add(5)
go worker.mainLoop()
go worker.newWorkLoop(recommit)
go worker.resultLoop()
go worker.taskLoop()
// loop for requesting mev-boost for new block.
go worker.mevBoostLoop(worker.config.MevBoostRequestInterval)
// Submit first work to initialize pending state.
if init {
worker.startCh <- struct{}{}
@ -497,6 +506,58 @@ func (w *worker) newWorkLoop(recommit time.Duration) {
}
}
type ExecutionPayloadResponse struct {
Version string `json:"version"`
Data engine.ExecutableData `json:"data"`
}
func (res *ExecutionPayloadResponse) getBlock() (*types.Block, error) {
return engine.ExecutableDataToBlock(res.Data, nil)
}
// mevBoostLoop queries mev-boost instance for new block.
func (w *worker) mevBoostLoop(interval time.Duration) {
defer w.wg.Done()
timer := time.NewTimer(0)
defer timer.Stop()
<-timer.C // discard the initial tick
request := func(slot *big.Int, parent_hash common.Hash) {
// /eth/v1/builder/block/:slot/:parent_hash
url := fmt.Sprintf("%s/eth/v1/builder/block/%s/%s",
w.config.MevBoostUrl, slot.String(), parent_hash.String())
res, err := http.Get(url)
if err != nil {
log.Error("Failed to get mev-boost response", "err", err)
return
}
defer res.Body.Close()
var response ExecutionPayloadResponse
json.NewDecoder(res.Body).Decode(&response)
block, err := response.getBlock()
if err != nil {
log.Error("Failed to parse payload", "err", err)
return
}
w.updateMevSnapshot(block)
timer.Reset(interval)
}
for {
select {
case <-timer.C:
if w.isRunning() {
// find the parent
parent := w.chain.CurrentBlock()
go request(parent.Number, parent.Hash())
}
case <-w.exitCh:
return
}
}
}
// mainLoop is responsible for generating and submitting sealing work based on
// the received event. It can support two modes: automatically generate task and
// submit it or return task according to given parameters for various proposes.
@ -734,6 +795,15 @@ func (w *worker) updateSnapshot(env *environment) {
w.snapshotState = env.state.Copy()
}
func (w *worker) updateMevSnapshot(block *types.Block) {
w.mevSnapshotBlockMu.Lock()
defer w.mevSnapshotBlockMu.Unlock()
// Update snapshot if and only if the new block received has the larger timestamp and higher block number.
if w.mevSnapshotBlock.Header().Time < block.Header().Time && w.mevSnapshotBlock.Header().Number.Cmp(block.Header().Number) == -1 {
w.mevSnapshotBlock = block
}
}
func (w *worker) commitTransaction(env *environment, tx *types.Transaction) ([]*types.Log, error) {
var (
snap = env.state.Snapshot()