mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
Add mevBoostLoop for requesting mev-boost service for new payload
perioidcally
This commit is contained in:
parent
d130217ca2
commit
c6db52ee8c
2 changed files with 77 additions and 5 deletions
|
|
@ -52,8 +52,9 @@ type Config struct {
|
||||||
GasPrice *big.Int // Minimum gas price for mining a transaction
|
GasPrice *big.Int // Minimum gas price for mining a transaction
|
||||||
Recommit time.Duration // The time interval for miner to re-create mining work.
|
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
|
NewPayloadTimeout time.Duration // The maximum time allowance for creating a new payload
|
||||||
MevBoostUrl string // URL to mev boost.
|
MevBoostUrl string // URL to mev boost.
|
||||||
|
MevBoostRequestInterval time.Duration // The interval for requesting mev boost for new block
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultConfig contains default settings for miner.
|
// DefaultConfig contains default settings for miner.
|
||||||
|
|
@ -65,8 +66,9 @@ var DefaultConfig = Config{
|
||||||
// consensus-layer usually will wait a half slot of time(6s)
|
// consensus-layer usually will wait a half slot of time(6s)
|
||||||
// for payload generation. It should be enough for Geth to
|
// for payload generation. It should be enough for Geth to
|
||||||
// run 3 rounds.
|
// run 3 rounds.
|
||||||
Recommit: 2 * time.Second,
|
Recommit: 2 * time.Second,
|
||||||
NewPayloadTimeout: 2 * time.Second,
|
NewPayloadTimeout: 2 * time.Second,
|
||||||
|
MevBoostRequestInterval: 1 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Miner creates blocks and searches for proof-of-work values.
|
// Miner creates blocks and searches for proof-of-work values.
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,16 @@
|
||||||
package miner
|
package miner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/beacon/engine"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
||||||
|
|
@ -205,6 +208,9 @@ type worker struct {
|
||||||
snapshotReceipts types.Receipts
|
snapshotReceipts types.Receipts
|
||||||
snapshotState *state.StateDB
|
snapshotState *state.StateDB
|
||||||
|
|
||||||
|
mevSnapshotBlockMu sync.RWMutex // The lock used to protect the mevSnapshotBlock below
|
||||||
|
mevSnapshotBlock *types.Block
|
||||||
|
|
||||||
// atomic status counters
|
// atomic status counters
|
||||||
running atomic.Bool // The indicator whether the consensus engine is running or not.
|
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.
|
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.newpayloadTimeout = newpayloadTimeout
|
||||||
|
|
||||||
worker.wg.Add(4)
|
worker.wg.Add(5)
|
||||||
go worker.mainLoop()
|
go worker.mainLoop()
|
||||||
go worker.newWorkLoop(recommit)
|
go worker.newWorkLoop(recommit)
|
||||||
go worker.resultLoop()
|
go worker.resultLoop()
|
||||||
go worker.taskLoop()
|
go worker.taskLoop()
|
||||||
|
|
||||||
|
// loop for requesting mev-boost for new block.
|
||||||
|
go worker.mevBoostLoop(worker.config.MevBoostRequestInterval)
|
||||||
|
|
||||||
// Submit first work to initialize pending state.
|
// Submit first work to initialize pending state.
|
||||||
if init {
|
if init {
|
||||||
worker.startCh <- struct{}{}
|
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
|
// mainLoop is responsible for generating and submitting sealing work based on
|
||||||
// the received event. It can support two modes: automatically generate task and
|
// the received event. It can support two modes: automatically generate task and
|
||||||
// submit it or return task according to given parameters for various proposes.
|
// 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()
|
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) {
|
func (w *worker) commitTransaction(env *environment, tx *types.Transaction) ([]*types.Log, error) {
|
||||||
var (
|
var (
|
||||||
snap = env.state.Snapshot()
|
snap = env.state.Snapshot()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue