eth/catalyst,miner: add open telemetry spans for the block building paths

This commit is contained in:
jonny rhea 2026-02-05 15:31:42 -06:00
parent 7b7be249cb
commit b0e1879a77
16 changed files with 233 additions and 78 deletions

View file

@ -20,6 +20,8 @@ require (
github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect
github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab // indirect
github.com/ferranbt/fastssz v0.1.4 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/gofrs/flock v0.12.1 // indirect
github.com/golang/snappy v1.0.0 // indirect
@ -32,6 +34,10 @@ require (
github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel v1.39.0 // indirect
go.opentelemetry.io/otel/metric v1.39.0 // indirect
go.opentelemetry.io/otel/trace v1.39.0 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/sys v0.39.0 // indirect

View file

@ -48,6 +48,11 @@ github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeD
github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg=
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
@ -59,6 +64,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA=
@ -108,6 +115,14 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=

View file

@ -17,6 +17,7 @@
package beacon
import (
"context"
"errors"
"fmt"
"math/big"
@ -29,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/internal/telemetry"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256"
@ -343,9 +345,19 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
// FinalizeAndAssemble implements consensus.Engine, setting the final state and
// assembling the block.
func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
func (beacon *Beacon) FinalizeAndAssemble(ctx context.Context, chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (result *types.Block, err error) {
ctx, _, spanEnd := telemetry.StartSpan(ctx, "consensus.beacon.FinalizeAndAssemble",
telemetry.Int64Attribute("block.number", int64(header.Number.Uint64())),
telemetry.Int64Attribute("txs.count", int64(len(body.Transactions))),
telemetry.Int64Attribute("withdrawals.count", int64(len(body.Withdrawals))),
)
defer spanEnd(err)
if !beacon.IsPoSHeader(header) {
return beacon.ethone.FinalizeAndAssemble(chain, header, state, body, receipts)
_, _, delegateEnd := telemetry.StartSpan(ctx, "consensus.beacon.delegateFinalizeAndAssemble")
block, delegateErr := beacon.ethone.FinalizeAndAssemble(ctx, chain, header, state, body, receipts)
delegateEnd(delegateErr)
return block, delegateErr
}
shanghai := chain.Config().IsShanghai(header.Number, header.Time)
if shanghai {
@ -355,17 +367,25 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
}
} else {
if len(body.Withdrawals) > 0 {
return nil, errors.New("withdrawals set before Shanghai activation")
err = errors.New("withdrawals set before Shanghai activation")
return nil, err
}
}
// Finalize and assemble the block.
_, _, finalizeEnd := telemetry.StartSpan(ctx, "consensus.beacon.Finalize")
beacon.Finalize(chain, header, state, body)
finalizeEnd(nil)
// Assign the final state root to header.
_, _, rootEnd := telemetry.StartSpan(ctx, "consensus.beacon.IntermediateRoot")
header.Root = state.IntermediateRoot(true)
rootEnd(nil)
// Assemble the final block.
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)), nil
_, _, blockEnd := telemetry.StartSpan(ctx, "consensus.beacon.NewBlock")
block := types.NewBlock(header, body, receipts, trie.NewStackTrie(nil))
blockEnd(nil)
return block, nil
}
// Seal generates a new sealing request for the given input block and pushes

View file

@ -19,6 +19,7 @@ package clique
import (
"bytes"
"context"
"errors"
"fmt"
"io"
@ -579,7 +580,7 @@ func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
// nor block rewards given, and returns the final block.
func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
func (c *Clique) FinalizeAndAssemble(ctx context.Context, chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
if len(body.Withdrawals) > 0 {
return nil, errors.New("clique does not support withdrawals")
}

View file

@ -18,6 +18,7 @@
package consensus
import (
"context"
"math/big"
"github.com/ethereum/go-ethereum/common"
@ -92,7 +93,7 @@ type Engine interface {
//
// Note: The block header and state database might be updated to reflect any
// consensus rules that happen at finalization (e.g. block rewards).
FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error)
FinalizeAndAssemble(ctx context.Context, chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error)
// Seal generates a new sealing request for the given input block and pushes
// the result into the given channel.

View file

@ -17,6 +17,7 @@
package ethash
import (
"context"
"errors"
"fmt"
"math/big"
@ -511,7 +512,7 @@ func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.
// FinalizeAndAssemble implements consensus.Engine, accumulating the block and
// uncle rewards, setting the final state and assembling the block.
func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
func (ethash *Ethash) FinalizeAndAssemble(ctx context.Context, chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
if len(body.Withdrawals) > 0 {
return nil, errors.New("ethash does not support withdrawals")
}

View file

@ -17,6 +17,7 @@
package core
import (
"context"
"fmt"
"math/big"
@ -409,7 +410,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
}
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals}
block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts)
block, err := b.engine.FinalizeAndAssemble(context.Background(), cm, b.header, statedb, &body, b.receipts)
if err != nil {
panic(err)
}

View file

@ -18,6 +18,7 @@
package catalyst
import (
"context"
"errors"
"fmt"
"reflect"
@ -35,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/telemetry"
"github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/miner"
@ -159,7 +161,7 @@ func newConsensusAPIWithoutHeartbeat(eth *eth.Ethereum) *ConsensusAPI {
//
// If there are payloadAttributes: we try to assemble a block with the payloadAttributes
// and return its payloadID.
func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
func (api *ConsensusAPI) ForkchoiceUpdatedV1(ctx context.Context, update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
if payloadAttributes != nil {
switch {
case payloadAttributes.Withdrawals != nil || payloadAttributes.BeaconRoot != nil:
@ -168,12 +170,12 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, pa
return engine.STATUS_INVALID, paramsErr("fcuV1 called post-shanghai")
}
}
return api.forkchoiceUpdated(update, payloadAttributes, engine.PayloadV1, false)
return api.forkchoiceUpdated(ctx, update, payloadAttributes, engine.PayloadV1, false)
}
// ForkchoiceUpdatedV2 is equivalent to V1 with the addition of withdrawals in the payload
// attributes. It supports both PayloadAttributesV1 and PayloadAttributesV2.
func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
func (api *ConsensusAPI) ForkchoiceUpdatedV2(ctx context.Context, update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
if params != nil {
switch {
case params.BeaconRoot != nil:
@ -186,12 +188,12 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, pa
return engine.STATUS_INVALID, unsupportedForkErr("fcuV2 must only be called with paris or shanghai payloads")
}
}
return api.forkchoiceUpdated(update, params, engine.PayloadV2, false)
return api.forkchoiceUpdated(ctx, update, params, engine.PayloadV2, false)
}
// ForkchoiceUpdatedV3 is equivalent to V2 with the addition of parent beacon block root
// in the payload attributes. It supports only PayloadAttributesV3.
func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
func (api *ConsensusAPI) ForkchoiceUpdatedV3(ctx context.Context, update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
if params != nil {
switch {
case params.Withdrawals == nil:
@ -206,10 +208,12 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa
// hash, even if params are wrong. To do this we need to split up
// forkchoiceUpdate into a function that only updates the head and then a
// function that kicks off block construction.
return api.forkchoiceUpdated(update, params, engine.PayloadV3, false)
return api.forkchoiceUpdated(ctx, update, params, engine.PayloadV3, false)
}
func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, payloadWitness bool) (engine.ForkChoiceResponse, error) {
func (api *ConsensusAPI) forkchoiceUpdated(ctx context.Context, update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, payloadWitness bool) (result engine.ForkChoiceResponse, err error) {
ctx, _, spanEnd := telemetry.StartSpan(ctx, "engine.forkchoiceUpdated")
defer spanEnd(err)
api.forkchoiceLock.Lock()
defer api.forkchoiceLock.Unlock()
@ -350,7 +354,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
if api.localBlocks.has(id) {
return valid(&id), nil
}
payload, err := api.eth.Miner().BuildPayload(args, payloadWitness)
payload, err := api.eth.Miner().BuildPayload(ctx, args, payloadWitness)
if err != nil {
log.Error("Failed to build payload", "err", err)
return valid(nil), engine.InvalidPayloadAttributes.With(err)

View file

@ -190,7 +190,7 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
SafeBlockHash: common.Hash{},
FinalizedBlockHash: common.Hash{},
}
_, err := api.ForkchoiceUpdatedV1(fcState, &blockParams)
_, err := api.ForkchoiceUpdatedV1(context.Background(), fcState, &blockParams)
if err != nil {
t.Fatalf("error preparing payload, err=%v", err)
}
@ -270,7 +270,7 @@ func TestInvalidPayloadTimestamp(t *testing.T) {
SafeBlockHash: common.Hash{},
FinalizedBlockHash: common.Hash{},
}
_, err := api.ForkchoiceUpdatedV1(fcState, &params)
_, err := api.ForkchoiceUpdatedV1(context.Background(), fcState, &params)
if test.shouldErr && err == nil {
t.Fatalf("expected error preparing payload with invalid timestamp, err=%v", err)
} else if !test.shouldErr && err != nil {
@ -329,7 +329,7 @@ func TestEth2NewBlock(t *testing.T) {
SafeBlockHash: block.Hash(),
FinalizedBlockHash: block.Hash(),
}
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
if _, err := api.ForkchoiceUpdatedV1(context.Background(), fcState, nil); err != nil {
t.Fatalf("Failed to insert block: %v", err)
}
if have, want := ethservice.BlockChain().CurrentBlock().Number.Uint64(), block.NumberU64(); have != want {
@ -369,7 +369,7 @@ func TestEth2NewBlock(t *testing.T) {
SafeBlockHash: block.Hash(),
FinalizedBlockHash: block.Hash(),
}
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
if _, err := api.ForkchoiceUpdatedV1(context.Background(), fcState, nil); err != nil {
t.Fatalf("Failed to insert block: %v", err)
}
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64() {
@ -515,7 +515,7 @@ func setupBlocks(t *testing.T, ethservice *eth.Ethereum, n int, parent *types.He
SafeBlockHash: payload.ParentHash,
FinalizedBlockHash: payload.ParentHash,
}
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
if _, err := api.ForkchoiceUpdatedV1(context.Background(), fcState, nil); err != nil {
t.Fatalf("Failed to insert block: %v", err)
}
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number {
@ -629,7 +629,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
err error
)
for i := 0; ; i++ {
if resp, err = api.ForkchoiceUpdatedV1(fcState, &params); err != nil {
if resp, err = api.ForkchoiceUpdatedV1(context.Background(), fcState, &params); err != nil {
t.Fatalf("error preparing payload, err=%v", err)
}
if resp.PayloadStatus.Status != engine.VALID {
@ -660,7 +660,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
SafeBlockHash: payload.ExecutionPayload.ParentHash,
FinalizedBlockHash: payload.ExecutionPayload.ParentHash,
}
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
if _, err := api.ForkchoiceUpdatedV1(context.Background(), fcState, nil); err != nil {
t.Fatalf("Failed to insert block: %v", err)
}
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.ExecutionPayload.Number {
@ -679,7 +679,7 @@ func assembleEnvelope(api *ConsensusAPI, parentHash common.Hash, params *engine.
Withdrawals: params.Withdrawals,
BeaconRoot: params.BeaconRoot,
}
payload, err := api.eth.Miner().BuildPayload(args, false)
payload, err := api.eth.Miner().BuildPayload(context.Background(), args, false)
if err != nil {
return nil, err
}
@ -867,7 +867,7 @@ func TestTrickRemoteBlockCache(t *testing.T) {
t.Error("invalid status: VALID on an invalid chain")
}
// Now reorg to the head of the invalid chain
resp, err := apiB.ForkchoiceUpdatedV1(engine.ForkchoiceStateV1{HeadBlockHash: payload.BlockHash, SafeBlockHash: payload.BlockHash, FinalizedBlockHash: payload.ParentHash}, nil)
resp, err := apiB.ForkchoiceUpdatedV1(context.Background(), engine.ForkchoiceStateV1{HeadBlockHash: payload.BlockHash, SafeBlockHash: payload.BlockHash, FinalizedBlockHash: payload.ParentHash}, nil)
if err != nil {
t.Fatal(err)
}
@ -970,7 +970,7 @@ func TestSimultaneousNewBlock(t *testing.T) {
for ii := 0; ii < 10; ii++ {
go func() {
defer wg.Done()
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
if _, err := api.ForkchoiceUpdatedV1(context.Background(), fcState, nil); err != nil {
errMu.Lock()
testErr = fmt.Errorf("failed to insert block: %w", err)
errMu.Unlock()
@ -1011,7 +1011,7 @@ func TestWithdrawals(t *testing.T) {
fcState := engine.ForkchoiceStateV1{
HeadBlockHash: parent.Hash(),
}
resp, err := api.ForkchoiceUpdatedV2(fcState, &blockParams)
resp, err := api.ForkchoiceUpdatedV2(context.Background(), fcState, &blockParams)
if err != nil {
t.Fatalf("error preparing payload, err=%v", err)
}
@ -1063,7 +1063,7 @@ func TestWithdrawals(t *testing.T) {
},
}
fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash
_, err = api.ForkchoiceUpdatedV2(fcState, &blockParams)
_, err = api.ForkchoiceUpdatedV2(context.Background(), fcState, &blockParams)
if err != nil {
t.Fatalf("error preparing payload, err=%v", err)
}
@ -1090,7 +1090,7 @@ func TestWithdrawals(t *testing.T) {
// 11: set block as head.
fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash
_, err = api.ForkchoiceUpdatedV2(fcState, nil)
_, err = api.ForkchoiceUpdatedV2(context.Background(), fcState, nil)
if err != nil {
t.Fatalf("error preparing payload, err=%v", err)
}
@ -1196,10 +1196,10 @@ func TestNilWithdrawals(t *testing.T) {
)
if !shanghai {
payloadVersion = engine.PayloadV1
_, err = api.ForkchoiceUpdatedV1(fcState, &test.blockParams)
_, err = api.ForkchoiceUpdatedV1(context.Background(), fcState, &test.blockParams)
} else {
payloadVersion = engine.PayloadV2
_, err = api.ForkchoiceUpdatedV2(fcState, &test.blockParams)
_, err = api.ForkchoiceUpdatedV2(context.Background(), fcState, &test.blockParams)
}
if test.wantErr {
if err == nil {
@ -1574,7 +1574,7 @@ func TestParentBeaconBlockRoot(t *testing.T) {
fcState := engine.ForkchoiceStateV1{
HeadBlockHash: parent.Hash(),
}
resp, err := api.ForkchoiceUpdatedV3(fcState, &blockParams)
resp, err := api.ForkchoiceUpdatedV3(context.Background(), fcState, &blockParams)
if err != nil {
t.Fatalf("error preparing payload, err=%v", err.(*engine.EngineAPIError).ErrorData())
}
@ -1605,7 +1605,7 @@ func TestParentBeaconBlockRoot(t *testing.T) {
}
fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash
resp, err = api.ForkchoiceUpdatedV3(fcState, nil)
resp, err = api.ForkchoiceUpdatedV3(context.Background(), fcState, nil)
if err != nil {
t.Fatalf("error preparing payload, err=%v", err.(*engine.EngineAPIError).ErrorData())
}
@ -1661,7 +1661,7 @@ func TestWitnessCreationAndConsumption(t *testing.T) {
SafeBlockHash: common.Hash{},
FinalizedBlockHash: common.Hash{},
}
_, err := api.ForkchoiceUpdatedWithWitnessV3(fcState, &blockParams)
_, err := api.ForkchoiceUpdatedWithWitnessV3(context.Background(), fcState, &blockParams)
if err != nil {
t.Fatalf("error preparing payload, err=%v", err)
}

View file

@ -17,6 +17,7 @@
package catalyst
import (
"context"
"crypto/rand"
"crypto/sha256"
"errors"
@ -32,11 +33,13 @@ import (
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/telemetry"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params/forks"
"github.com/ethereum/go-ethereum/rpc"
"go.opentelemetry.io/otel"
)
const devEpochLength = 32
@ -121,7 +124,7 @@ func NewSimulatedBeacon(period uint64, feeRecipient common.Address, eth *eth.Eth
// if genesis block, send forkchoiceUpdated to trigger transition to PoS
if block.Number.Sign() == 0 {
version := payloadVersion(eth.BlockChain().Config(), block.Time)
if _, err := engineAPI.forkchoiceUpdated(current, nil, version, false); err != nil {
if _, err := engineAPI.forkchoiceUpdated(context.Background(), current, nil, version, false); err != nil {
return nil, err
}
}
@ -191,16 +194,25 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u
}
version := payloadVersion(c.eth.BlockChain().Config(), timestamp)
tracer := otel.Tracer("")
// Create a server span for forkchoiceUpdated with payload attributes,
// simulating an incoming engine API request from a real consensus client.
var random [32]byte
rand.Read(random[:])
fcResponse, err := c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, &engine.PayloadAttributes{
fcCtx, fcSpanEnd := telemetry.StartServerSpan(context.Background(), tracer, telemetry.RPCInfo{
System: "jsonrpc",
Service: "engine",
Method: "forkchoiceUpdatedV" + fmt.Sprintf("%d", version),
})
fcResponse, err := c.engineAPI.forkchoiceUpdated(fcCtx, c.curForkchoiceState, &engine.PayloadAttributes{
Timestamp: timestamp,
SuggestedFeeRecipient: feeRecipient,
Withdrawals: withdrawals,
Random: random,
BeaconRoot: &common.Hash{},
}, version, false)
fcSpanEnd(err)
if err != nil {
return err
}
@ -214,7 +226,15 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u
return nil
}
// Create a server span for getPayload, simulating the consensus client
// coming back to retrieve the built payload.
_, gpSpanEnd := telemetry.StartServerSpan(context.Background(), tracer, telemetry.RPCInfo{
System: "jsonrpc",
Service: "engine",
Method: "getPayloadV" + fmt.Sprintf("%d", version),
})
envelope, err := c.engineAPI.getPayload(*fcResponse.PayloadID, true, nil, nil)
gpSpanEnd(err)
if err != nil {
return err
}
@ -255,15 +275,30 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u
requests = envelope.Requests
}
// Mark the payload as canon
// Create a server span for newPayload, simulating the consensus client
// sending the execution payload for validation.
_, npSpanEnd := telemetry.StartServerSpan(context.Background(), tracer, telemetry.RPCInfo{
System: "jsonrpc",
Service: "engine",
Method: "newPayloadV" + fmt.Sprintf("%d", version),
})
_, err = c.engineAPI.newPayload(*payload, blobHashes, beaconRoot, requests, false)
npSpanEnd(err)
if err != nil {
return err
}
c.setCurrentState(payload.BlockHash, finalizedHash)
// Mark the block containing the payload as canonical
if _, err = c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, nil, version, false); err != nil {
// Create a server span for the final forkchoiceUpdated (no payload attributes),
// which sets the new block as the canonical chain head.
fcuCtx, fcuSpanEnd := telemetry.StartServerSpan(context.Background(), tracer, telemetry.RPCInfo{
System: "jsonrpc",
Service: "engine",
Method: "forkchoiceUpdatedV" + fmt.Sprintf("%d", version),
})
_, err = c.engineAPI.forkchoiceUpdated(fcuCtx, c.curForkchoiceState, nil, version, false)
fcuSpanEnd(err)
if err != nil {
return err
}
c.lastBlockTime = payload.Timestamp

View file

@ -17,6 +17,7 @@
package catalyst
import (
"context"
"errors"
"strconv"
"time"
@ -34,7 +35,7 @@ import (
// ForkchoiceUpdatedWithWitnessV1 is analogous to ForkchoiceUpdatedV1, only it
// generates an execution witness too if block building was requested.
func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV1(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV1(ctx context.Context, update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
if payloadAttributes != nil {
switch {
case payloadAttributes.Withdrawals != nil || payloadAttributes.BeaconRoot != nil:
@ -43,12 +44,12 @@ func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV1(update engine.Forkchoice
return engine.STATUS_INVALID, paramsErr("fcuV1 called post-shanghai")
}
}
return api.forkchoiceUpdated(update, payloadAttributes, engine.PayloadV1, true)
return api.forkchoiceUpdated(ctx, update, payloadAttributes, engine.PayloadV1, true)
}
// ForkchoiceUpdatedWithWitnessV2 is analogous to ForkchoiceUpdatedV2, only it
// generates an execution witness too if block building was requested.
func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV2(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV2(ctx context.Context, update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
if params != nil {
switch {
case params.BeaconRoot != nil:
@ -61,12 +62,12 @@ func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV2(update engine.Forkchoice
return engine.STATUS_INVALID, unsupportedForkErr("fcuV2 must only be called with paris or shanghai payloads")
}
}
return api.forkchoiceUpdated(update, params, engine.PayloadV2, true)
return api.forkchoiceUpdated(ctx, update, params, engine.PayloadV2, true)
}
// ForkchoiceUpdatedWithWitnessV3 is analogous to ForkchoiceUpdatedV3, only it
// generates an execution witness too if block building was requested.
func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV3(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV3(ctx context.Context, update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
if params != nil {
switch {
case params.Withdrawals == nil:
@ -81,7 +82,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV3(update engine.Forkchoice
// hash, even if params are wrong. To do this we need to split up
// forkchoiceUpdate into a function that only updates the head and then a
// function that kicks off block construction.
return api.forkchoiceUpdated(update, params, engine.PayloadV3, true)
return api.forkchoiceUpdated(ctx, update, params, engine.PayloadV3, true)
}
// NewPayloadWithWitnessV1 is analogous to NewPayloadV1, only it also generates

View file

@ -347,7 +347,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
}
blockBody := &types.Body{Transactions: txes, Withdrawals: *block.BlockOverrides.Withdrawals}
chainHeadReader := &simChainHeadReader{ctx, sim.b}
b, err := sim.b.Engine().FinalizeAndAssemble(chainHeadReader, header, sim.state, blockBody, receipts)
b, err := sim.b.Engine().FinalizeAndAssemble(ctx, chainHeadReader, header, sim.state, blockBody, receipts)
if err != nil {
return nil, nil, nil, err
}

View file

@ -18,6 +18,7 @@
package miner
import (
"context"
"fmt"
"math/big"
"sync"
@ -135,8 +136,8 @@ func (miner *Miner) SetGasTip(tip *big.Int) error {
}
// BuildPayload builds the payload according to the provided parameters.
func (miner *Miner) BuildPayload(args *BuildPayloadArgs, witness bool) (*Payload, error) {
return miner.buildPayload(args, witness)
func (miner *Miner) BuildPayload(ctx context.Context, args *BuildPayloadArgs, witness bool) (*Payload, error) {
return miner.buildPayload(ctx, args, witness)
}
// getPending retrieves the pending block based on the current head block.
@ -156,16 +157,17 @@ func (miner *Miner) getPending() *newPayloadResult {
if miner.chainConfig.IsShanghai(new(big.Int).Add(header.Number, big.NewInt(1)), timestamp) {
withdrawal = []*types.Withdrawal{}
}
ret := miner.generateWork(&generateParams{
timestamp: timestamp,
forceTime: false,
parentHash: header.Hash(),
coinbase: miner.config.PendingFeeRecipient,
random: common.Hash{},
withdrawals: withdrawal,
beaconRoot: nil,
noTxs: false,
}, false) // we will never make a witness for a pending block
ret := miner.generateWork(context.Background(),
&generateParams{
timestamp: timestamp,
forceTime: false,
parentHash: header.Hash(),
coinbase: miner.config.PendingFeeRecipient,
random: common.Hash{},
withdrawals: withdrawal,
beaconRoot: nil,
noTxs: false,
}, false) // we will never make a witness for a pending block
if ret.err != nil {
return nil
}

View file

@ -17,6 +17,7 @@
package miner
import (
"context"
"crypto/sha256"
"encoding/binary"
"math/big"
@ -28,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/stateless"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/telemetry"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
@ -97,14 +99,15 @@ func newPayload(empty *types.Block, emptyRequests [][]byte, witness *stateless.W
return payload
}
// update updates the full-block with latest built version.
func (payload *Payload) update(r *newPayloadResult, elapsed time.Duration) {
// update updates the full-block with latest built version. It returns true if
// the update was accepted (i.e. the new block has higher fees than the previous).
func (payload *Payload) update(r *newPayloadResult, elapsed time.Duration) (result bool) {
payload.lock.Lock()
defer payload.lock.Unlock()
select {
case <-payload.stop:
return // reject stale update
return false // reject stale update
default:
}
// Ensure the newly provided full block has a higher transaction fee.
@ -129,8 +132,10 @@ func (payload *Payload) update(r *newPayloadResult, elapsed time.Duration) {
"root", r.block.Root(),
"elapsed", common.PrettyDuration(elapsed),
)
result = true
}
payload.cond.Broadcast() // fire signal for notifying full block
return
}
// Resolve returns the latest built payload and also terminates the background
@ -206,7 +211,15 @@ func (payload *Payload) ResolveFull() *engine.ExecutionPayloadEnvelope {
}
// buildPayload builds the payload according to the provided parameters.
func (miner *Miner) buildPayload(args *BuildPayloadArgs, witness bool) (*Payload, error) {
func (miner *Miner) buildPayload(ctx context.Context, args *BuildPayloadArgs, witness bool) (result *Payload, err error) {
payloadID := args.Id()
ctx, _, spanEnd := telemetry.StartSpan(ctx, "miner.buildPayload",
telemetry.StringAttribute("payload.id", payloadID.String()),
telemetry.StringAttribute("parent.hash", args.Parent.String()),
telemetry.Int64Attribute("timestamp", int64(args.Timestamp)),
)
defer spanEnd(err)
// Build the initial version with no transaction included. It should be fast
// enough to run. The empty payload can at least make sure there is something
// to deliver for not missing slot.
@ -220,16 +233,25 @@ func (miner *Miner) buildPayload(args *BuildPayloadArgs, witness bool) (*Payload
beaconRoot: args.BeaconRoot,
noTxs: true,
}
empty := miner.generateWork(emptyParams, witness)
empty := miner.generateWork(ctx, emptyParams, witness)
if empty.err != nil {
return nil, empty.err
}
// Construct a payload object for return.
payload := newPayload(empty.block, empty.requests, empty.witness, args.Id())
payload := newPayload(empty.block, empty.requests, empty.witness, payloadID)
// Spin up a routine for updating the payload in background. This strategy
// can maximum the revenue for including transactions with highest fee.
go func() {
var iteration int
bCtx, bSpan, bSpanEnd := telemetry.StartSpan(ctx, "miner.background",
telemetry.Int64Attribute("block.number", int64(empty.block.NumberU64())),
)
defer func() {
bSpan.SetAttributes(telemetry.Int64Attribute("iterations.total", int64(iteration)))
bSpanEnd(nil)
}()
// Setup the timer for re-building the payload. The initial clock is kept
// for triggering process immediately.
timer := time.NewTimer(0)
@ -254,18 +276,32 @@ func (miner *Miner) buildPayload(args *BuildPayloadArgs, witness bool) (*Payload
for {
select {
case <-timer.C:
iteration++
iterCtx, iterSpan, iterSpanEnd := telemetry.StartSpan(bCtx, "miner.buildIteration",
telemetry.Int64Attribute("iteration", int64(iteration)),
)
start := time.Now()
r := miner.generateWork(fullParams, witness)
r := miner.generateWork(iterCtx, fullParams, witness)
if r.err == nil {
payload.update(r, time.Since(start))
accepted := payload.update(r, time.Since(start))
iterSpan.SetAttributes(telemetry.BoolAttribute("update.accepted", accepted))
} else {
log.Info("Error while generating work", "id", payload.id, "err", r.err)
}
iterSpanEnd(r.err)
timer.Reset(miner.config.Recommit)
case <-payload.stop:
payload.lock.Lock()
emptyDelivered := payload.full == nil
payload.lock.Unlock()
bSpan.SetAttributes(
telemetry.StringAttribute("exit.reason", "delivery"),
telemetry.BoolAttribute("empty.delivered", emptyDelivered),
)
log.Info("Stopping work on payload", "id", payload.id, "reason", "delivery")
return
case <-endTimer.C:
bSpan.SetAttributes(telemetry.StringAttribute("exit.reason", "timeout"))
log.Info("Stopping work on payload", "id", payload.id, "reason", "timeout")
return
}

View file

@ -17,6 +17,7 @@
package miner
import (
"context"
"math/big"
"reflect"
"testing"
@ -156,7 +157,7 @@ func TestBuildPayload(t *testing.T) {
Random: common.Hash{},
FeeRecipient: recipient,
}
payload, err := w.buildPayload(args, false)
payload, err := w.buildPayload(context.Background(), args, false)
if err != nil {
t.Fatalf("Failed to build payload %v", err)
}

View file

@ -17,6 +17,7 @@
package miner
import (
"context"
"errors"
"fmt"
"math/big"
@ -32,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/internal/telemetry"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
@ -115,8 +117,23 @@ type generateParams struct {
}
// generateWork generates a sealing block based on the given parameters.
func (miner *Miner) generateWork(genParam *generateParams, witness bool) *newPayloadResult {
work, err := miner.prepareWork(genParam, witness)
func (miner *Miner) generateWork(ctx context.Context, genParam *generateParams, witness bool) (result *newPayloadResult) {
ctx, span, spanEnd := telemetry.StartSpan(ctx, "miner.generateWork")
defer func() {
if result != nil && result.err == nil {
span.SetAttributes(
telemetry.Int64Attribute("txs.count", int64(len(result.block.Transactions()))),
telemetry.Int64Attribute("gas.used", int64(result.block.GasUsed())),
telemetry.StringAttribute("fees", result.fees.String()),
)
}
if result != nil {
spanEnd(result.err)
} else {
spanEnd(nil)
}
}()
work, err := miner.prepareWork(ctx, genParam, witness)
if err != nil {
return &newPayloadResult{err: err}
}
@ -138,7 +155,7 @@ func (miner *Miner) generateWork(genParam *generateParams, witness bool) *newPay
})
defer timer.Stop()
err := miner.fillTransactions(interrupt, work)
err := miner.fillTransactions(ctx, interrupt, work)
if errors.Is(err, errBlockInterruptedByTimeout) {
log.Warn("Block building is interrupted", "allowance", common.PrettyDuration(miner.config.Recommit))
}
@ -172,7 +189,9 @@ func (miner *Miner) generateWork(genParam *generateParams, witness bool) *newPay
work.header.RequestsHash = &reqHash
}
block, err := miner.engine.FinalizeAndAssemble(miner.chain, work.header, work.state, &body, work.receipts)
ctx, _, finalizeSpanEnd := telemetry.StartSpan(ctx, "miner.FinalizeAndAssemble")
block, err := miner.engine.FinalizeAndAssemble(ctx, miner.chain, work.header, work.state, &body, work.receipts)
finalizeSpanEnd(err)
if err != nil {
return &newPayloadResult{err: err}
}
@ -190,7 +209,9 @@ func (miner *Miner) generateWork(genParam *generateParams, witness bool) *newPay
// prepareWork constructs the sealing task according to the given parameters,
// either based on the last chain head or specified parent. In this function
// the pending transactions are not filled yet, only the empty task returned.
func (miner *Miner) prepareWork(genParams *generateParams, witness bool) (*environment, error) {
func (miner *Miner) prepareWork(ctx context.Context, genParams *generateParams, witness bool) (result *environment, err error) {
_, _, spanEnd := telemetry.StartSpan(ctx, "miner.prepareWork")
defer spanEnd(err)
miner.confMu.RLock()
defer miner.confMu.RUnlock()
@ -295,7 +316,9 @@ func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase
}, nil
}
func (miner *Miner) commitTransaction(env *environment, tx *types.Transaction) error {
func (miner *Miner) commitTransaction(ctx context.Context, env *environment, tx *types.Transaction) (err error) {
_, _, spanEnd := telemetry.StartSpan(ctx, "miner.commitTransaction")
defer spanEnd(err)
if tx.Type() == types.BlobTxType {
return miner.commitBlobTransaction(env, tx)
}
@ -352,7 +375,9 @@ func (miner *Miner) applyTransaction(env *environment, tx *types.Transaction) (*
return receipt, err
}
func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *transactionsByPriceAndNonce, interrupt *atomic.Int32) error {
func (miner *Miner) commitTransactions(ctx context.Context, env *environment, plainTxs, blobTxs *transactionsByPriceAndNonce, interrupt *atomic.Int32) error {
ctx, _, spanEnd := telemetry.StartSpan(ctx, "miner.commitTransactions")
defer spanEnd(nil)
var (
isCancun = miner.chainConfig.IsCancun(env.header.Number, env.header.Time)
gasLimit = env.header.GasLimit
@ -448,7 +473,7 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran
// Start executing the transaction
env.state.SetTxContext(tx.Hash(), env.tcount)
err := miner.commitTransaction(env, tx)
err := miner.commitTransaction(ctx, env, tx)
switch {
case errors.Is(err, core.ErrNonceTooLow):
// New head notification data race between the transaction pool and miner, shift
@ -472,7 +497,9 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran
// 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 (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment) error {
func (miner *Miner) fillTransactions(ctx context.Context, interrupt *atomic.Int32, env *environment) (err error) {
ctx, span, spanEnd := telemetry.StartSpan(ctx, "miner.fillTransactions")
defer spanEnd(err)
miner.confMu.RLock()
tip := miner.config.GasPrice
prio := miner.prio
@ -501,6 +528,10 @@ func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment)
filter.BlobVersion = types.BlobSidecarVersion0
}
pendingBlobTxs := miner.txpool.Pending(filter)
span.SetAttributes(
telemetry.Int64Attribute("pending.plain.count", int64(len(pendingPlainTxs))),
telemetry.Int64Attribute("pending.blob.count", int64(len(pendingBlobTxs))),
)
// Split the pending transactions into locals and remotes.
prioPlainTxs, normalPlainTxs := make(map[common.Address][]*txpool.LazyTransaction), pendingPlainTxs
@ -521,7 +552,7 @@ func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment)
plainTxs := newTransactionsByPriceAndNonce(env.signer, prioPlainTxs, env.header.BaseFee)
blobTxs := newTransactionsByPriceAndNonce(env.signer, prioBlobTxs, env.header.BaseFee)
if err := miner.commitTransactions(env, plainTxs, blobTxs, interrupt); err != nil {
if err := miner.commitTransactions(ctx, env, plainTxs, blobTxs, interrupt); err != nil {
return err
}
}
@ -529,7 +560,7 @@ func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment)
plainTxs := newTransactionsByPriceAndNonce(env.signer, normalPlainTxs, env.header.BaseFee)
blobTxs := newTransactionsByPriceAndNonce(env.signer, normalBlobTxs, env.header.BaseFee)
if err := miner.commitTransactions(env, plainTxs, blobTxs, interrupt); err != nil {
if err := miner.commitTransactions(ctx, env, plainTxs, blobTxs, interrupt); err != nil {
return err
}
}