mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
eth/catalyst,miner: add open telemetry spans for the block building paths
This commit is contained in:
parent
7b7be249cb
commit
b0e1879a77
16 changed files with 233 additions and 78 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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=
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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, ¶ms)
|
||||
_, err := api.ForkchoiceUpdatedV1(context.Background(), fcState, ¶ms)
|
||||
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, ¶ms); err != nil {
|
||||
if resp, err = api.ForkchoiceUpdatedV1(context.Background(), fcState, ¶ms); 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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue