Unwrap payload bid (#14035)

* engine GetPayload returns entire response

* deprecate PayloadValueTo(Gwei|Wei)

* return entire bid from builder getter

* get bid value from api bid (not ExecutionData)

* plumb bid and bundle through BuildBlockParallel

* rm ValueInGwei

* removing wei/gwei fields from the payload wrappers

* commentary around the little-endian situation

* finish the job in BuildBlockParallel

* light self-review cleanup

* fix spectest mock

* restore engine timeout

* lint fixes

* de-duplicate imports

* remove errant comment

* James feedback

---------

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
This commit is contained in:
kasey
2024-05-22 17:16:32 -05:00
committed by GitHub
parent 4d190c41cc
commit 2265af58ae
48 changed files with 629 additions and 744 deletions

View File

@@ -23,7 +23,7 @@ type SignedBid interface {
type Bid interface {
Header() (interfaces.ExecutionData, error)
BlobKzgCommitments() ([][]byte, error)
Value() []byte
Value() primitives.Wei
Pubkey() []byte
Version() int
IsNil() bool
@@ -126,8 +126,8 @@ func (b builderBid) Version() int {
}
// Value --
func (b builderBid) Value() []byte {
return b.p.Value
func (b builderBid) Value() primitives.Wei {
return primitives.LittleEndianBytesToWei(b.p.Value)
}
// Pubkey --
@@ -166,7 +166,7 @@ func WrappedBuilderBidCapella(p *ethpb.BuilderBidCapella) (Bid, error) {
// Header returns the execution data interface.
func (b builderBidCapella) Header() (interfaces.ExecutionData, error) {
// We have to convert big endian to little endian because the value is coming from the execution layer.
return blocks.WrappedExecutionPayloadHeaderCapella(b.p.Header, primitives.BigEndianBytesToWei(b.p.Value))
return blocks.WrappedExecutionPayloadHeaderCapella(b.p.Header)
}
// BlobKzgCommitments --
@@ -180,8 +180,8 @@ func (b builderBidCapella) Version() int {
}
// Value --
func (b builderBidCapella) Value() []byte {
return b.p.Value
func (b builderBidCapella) Value() primitives.Wei {
return primitives.LittleEndianBytesToWei(b.p.Value)
}
// Pubkey --
@@ -223,8 +223,8 @@ func (b builderBidDeneb) Version() int {
}
// Value --
func (b builderBidDeneb) Value() []byte {
return b.p.Value
func (b builderBidDeneb) Value() primitives.Wei {
return primitives.LittleEndianBytesToWei(b.p.Value)
}
// Pubkey --
@@ -250,7 +250,7 @@ func (b builderBidDeneb) HashTreeRootWith(hh *ssz.Hasher) error {
// Header --
func (b builderBidDeneb) Header() (interfaces.ExecutionData, error) {
// We have to convert big endian to little endian because the value is coming from the execution layer.
return blocks.WrappedExecutionPayloadHeaderDeneb(b.p.Header, blocks.PayloadValueToWei(b.p.Value))
return blocks.WrappedExecutionPayloadHeaderDeneb(b.p.Header)
}
// BlobKzgCommitments --

View File

@@ -330,7 +330,7 @@ func (c *Client) SubmitBlindedBlock(ctx context.Context, sb interfaces.ReadOnlyS
if err != nil {
return nil, nil, err
}
ed, err := blocks.NewWrappedExecutionData(pb, nil)
ed, err := blocks.NewWrappedExecutionData(pb)
if err != nil {
return nil, nil, err
}

View File

@@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"io"
"math/big"
"net/http"
"net/url"
"strconv"
@@ -16,6 +15,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
types "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
@@ -198,12 +198,12 @@ func TestClient_GetHeader(t *testing.T) {
require.NoError(t, err)
require.Equal(t, true, bytes.Equal(expectedTxRoot, withdrawalsRoot))
require.Equal(t, uint64(1), bidHeader.GasUsed())
value, err := stringToUint256("652312848583266388373324160190187140051835877600158453279131187530910662656")
// this matches the value in the testExampleHeaderResponse
bidStr := "652312848583266388373324160190187140051835877600158453279131187530910662656"
value, err := stringToUint256(bidStr)
require.NoError(t, err)
require.Equal(t, fmt.Sprintf("%#x", value.SSZBytes()), fmt.Sprintf("%#x", bid.Value()))
bidValue := bytesutil.ReverseByteOrder(bid.Value())
require.DeepEqual(t, bidValue, value.Bytes())
require.DeepEqual(t, big.NewInt(0).SetBytes(bidValue), value.Int)
require.Equal(t, 0, value.Int.Cmp(primitives.WeiToBigInt(bid.Value())))
require.Equal(t, bidStr, primitives.WeiToBigInt(bid.Value()).String())
})
t.Run("capella", func(t *testing.T) {
hc := &http.Client{
@@ -230,12 +230,11 @@ func TestClient_GetHeader(t *testing.T) {
withdrawalsRoot, err := bidHeader.WithdrawalsRoot()
require.NoError(t, err)
require.Equal(t, true, bytes.Equal(expectedWithdrawalsRoot, withdrawalsRoot))
value, err := stringToUint256("652312848583266388373324160190187140051835877600158453279131187530910662656")
bidStr := "652312848583266388373324160190187140051835877600158453279131187530910662656"
value, err := stringToUint256(bidStr)
require.NoError(t, err)
require.Equal(t, fmt.Sprintf("%#x", value.SSZBytes()), fmt.Sprintf("%#x", bid.Value()))
bidValue := bytesutil.ReverseByteOrder(bid.Value())
require.DeepEqual(t, bidValue, value.Bytes())
require.DeepEqual(t, big.NewInt(0).SetBytes(bidValue), value.Int)
require.Equal(t, 0, value.Int.Cmp(primitives.WeiToBigInt(bid.Value())))
require.Equal(t, bidStr, primitives.WeiToBigInt(bid.Value()).String())
})
t.Run("deneb", func(t *testing.T) {
hc := &http.Client{
@@ -262,12 +261,13 @@ func TestClient_GetHeader(t *testing.T) {
withdrawalsRoot, err := bidHeader.WithdrawalsRoot()
require.NoError(t, err)
require.Equal(t, true, bytes.Equal(expectedWithdrawalsRoot, withdrawalsRoot))
value, err := stringToUint256("652312848583266388373324160190187140051835877600158453279131187530910662656")
bidStr := "652312848583266388373324160190187140051835877600158453279131187530910662656"
value, err := stringToUint256(bidStr)
require.NoError(t, err)
require.Equal(t, fmt.Sprintf("%#x", value.SSZBytes()), fmt.Sprintf("%#x", bid.Value()))
bidValue := bytesutil.ReverseByteOrder(bid.Value())
require.DeepEqual(t, bidValue, value.Bytes())
require.DeepEqual(t, big.NewInt(0).SetBytes(bidValue), value.Int)
require.Equal(t, 0, value.Int.Cmp(primitives.WeiToBigInt(bid.Value())))
require.Equal(t, bidStr, primitives.WeiToBigInt(bid.Value()).String())
kcgCommitments, err := bid.BlobKzgCommitments()
require.NoError(t, err)
require.Equal(t, len(kcgCommitments) > 0, true)

View File

@@ -156,6 +156,8 @@ func (bb *BuilderBid) ToProto() (*eth.BuilderBid, error) {
}
return &eth.BuilderBid{
Header: header,
// Note that SSZBytes() reverses byte order for the little-endian representation.
// Uint256.Bytes() is big-endian, SSZBytes takes this value and reverses it.
Value: bb.Value.SSZBytes(),
Pubkey: bb.Pubkey,
}, nil
@@ -484,6 +486,8 @@ func (bb *BuilderBidCapella) ToProto() (*eth.BuilderBidCapella, error) {
}
return &eth.BuilderBidCapella{
Header: header,
// Note that SSZBytes() reverses byte order for the little-endian representation.
// Uint256.Bytes() is big-endian, SSZBytes takes this value and reverses it.
Value: bytesutil.SafeCopyBytes(bb.Value.SSZBytes()),
Pubkey: bytesutil.SafeCopyBytes(bb.Pubkey),
}, nil
@@ -1022,8 +1026,10 @@ func (bb *BuilderBidDeneb) ToProto() (*eth.BuilderBidDeneb, error) {
return &eth.BuilderBidDeneb{
Header: header,
BlobKzgCommitments: kzgCommitments,
Value: bytesutil.SafeCopyBytes(bb.Value.SSZBytes()),
Pubkey: bytesutil.SafeCopyBytes(bb.Pubkey),
// Note that SSZBytes() reverses byte order for the little-endian representation.
// Uint256.Bytes() is big-endian, SSZBytes takes this value and reverses it.
Value: bytesutil.SafeCopyBytes(bb.Value.SSZBytes()),
Pubkey: bytesutil.SafeCopyBytes(bb.Pubkey),
}, nil
}

View File

@@ -2,7 +2,6 @@ package testing
import (
"context"
"math/big"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/api/client/builder"
@@ -55,13 +54,13 @@ func (s *MockBuilderService) SubmitBlindedBlock(_ context.Context, b interfaces.
}
return w, nil, s.ErrSubmitBlindedBlock
case version.Capella:
w, err := blocks.WrappedExecutionPayloadCapella(s.PayloadCapella, big.NewInt(0))
w, err := blocks.WrappedExecutionPayloadCapella(s.PayloadCapella)
if err != nil {
return nil, nil, errors.Wrap(err, "could not wrap capella payload")
}
return w, nil, s.ErrSubmitBlindedBlock
case version.Deneb:
w, err := blocks.WrappedExecutionPayloadDeneb(s.PayloadDeneb, big.NewInt(0))
w, err := blocks.WrappedExecutionPayloadDeneb(s.PayloadDeneb)
if err != nil {
return nil, nil, errors.Wrap(err, "could not wrap deneb payload")
}

View File

@@ -1,7 +1,6 @@
package blocks_test
import (
"math/big"
"testing"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks"
@@ -610,7 +609,7 @@ func Test_ProcessPayloadCapella(t *testing.T) {
random, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
require.NoError(t, err)
payload.PrevRandao = random
wrapped, err := consensusblocks.WrappedExecutionPayloadCapella(payload, big.NewInt(0))
wrapped, err := consensusblocks.WrappedExecutionPayloadCapella(payload)
require.NoError(t, err)
_, err = blocks.ProcessPayload(st, wrapped)
require.NoError(t, err)
@@ -874,7 +873,7 @@ func emptyPayloadHeaderCapella() (interfaces.ExecutionData, error) {
BlockHash: make([]byte, fieldparams.RootLength),
TransactionsRoot: make([]byte, fieldparams.RootLength),
WithdrawalsRoot: make([]byte, fieldparams.RootLength),
}, big.NewInt(0))
})
}
func emptyPayload() *enginev1.ExecutionPayload {

View File

@@ -1,7 +1,6 @@
package blocks_test
import (
"math/big"
"math/rand"
"testing"
@@ -643,10 +642,7 @@ func TestProcessBlindWithdrawals(t *testing.T) {
require.NoError(t, err)
wdRoot, err := ssz.WithdrawalSliceRoot(test.Args.Withdrawals, fieldparams.MaxWithdrawalsPerPayload)
require.NoError(t, err)
p, err := consensusblocks.WrappedExecutionPayloadHeaderCapella(
&enginev1.ExecutionPayloadHeaderCapella{WithdrawalsRoot: wdRoot[:]},
big.NewInt(0),
)
p, err := consensusblocks.WrappedExecutionPayloadHeaderCapella(&enginev1.ExecutionPayloadHeaderCapella{WithdrawalsRoot: wdRoot[:]})
require.NoError(t, err)
post, err := blocks.ProcessWithdrawals(st, p)
if test.Control.ExpectedError {
@@ -1064,7 +1060,7 @@ func TestProcessWithdrawals(t *testing.T) {
}
st, err := prepareValidators(spb, test.Args)
require.NoError(t, err)
p, err := consensusblocks.WrappedExecutionPayloadCapella(&enginev1.ExecutionPayloadCapella{Withdrawals: test.Args.Withdrawals}, big.NewInt(0))
p, err := consensusblocks.WrappedExecutionPayloadCapella(&enginev1.ExecutionPayloadCapella{Withdrawals: test.Args.Withdrawals})
require.NoError(t, err)
post, err := blocks.ProcessWithdrawals(st, p)
if test.Control.ExpectedError {

View File

@@ -3,7 +3,6 @@ package kv
import (
"context"
"encoding/binary"
"math/big"
"math/rand"
"strconv"
"testing"
@@ -100,7 +99,7 @@ func TestState_CanSaveRetrieve(t *testing.T) {
BlockHash: make([]byte, 32),
TransactionsRoot: make([]byte, 32),
WithdrawalsRoot: make([]byte, 32),
}, big.NewInt(0))
})
require.NoError(t, err)
require.NoError(t, st.SetLatestExecutionPayloadHeader(p))
return st
@@ -125,7 +124,7 @@ func TestState_CanSaveRetrieve(t *testing.T) {
BlockHash: make([]byte, 32),
TransactionsRoot: make([]byte, 32),
WithdrawalsRoot: make([]byte, 32),
}, big.NewInt(0))
})
require.NoError(t, err)
require.NoError(t, st.SetLatestExecutionPayloadHeader(p))
return st
@@ -152,7 +151,7 @@ func TestState_CanSaveRetrieve(t *testing.T) {
WithdrawalsRoot: make([]byte, 32),
DepositReceiptsRoot: make([]byte, 32),
WithdrawalRequestsRoot: make([]byte, 32),
}, big.NewInt(0))
})
require.NoError(t, err)
require.NoError(t, st.SetLatestExecutionPayloadHeader(p))
return st

View File

@@ -118,7 +118,7 @@ type EngineCaller interface {
ForkchoiceUpdated(
ctx context.Context, state *pb.ForkchoiceState, attrs payloadattribute.Attributer,
) (*pb.PayloadIDBytes, []byte, error)
GetPayload(ctx context.Context, payloadId [8]byte, slot primitives.Slot) (interfaces.ExecutionData, *pb.BlobsBundle, bool, error)
GetPayload(ctx context.Context, payloadId [8]byte, slot primitives.Slot) (*blocks.GetPayloadResponse, error)
ExecutionBlockByHash(ctx context.Context, hash common.Hash, withTxs bool) (*pb.ExecutionBlock, error)
GetTerminalBlockHash(ctx context.Context, transitionTime uint64) ([]byte, bool, error)
}
@@ -266,69 +266,43 @@ func (s *Service) ForkchoiceUpdated(
}
}
func getPayloadMethodAndMessage(slot primitives.Slot) (string, proto.Message) {
pe := slots.ToEpoch(slot)
if pe >= params.BeaconConfig().ElectraForkEpoch {
return GetPayloadMethodV4, &pb.ExecutionPayloadElectraWithValueAndBlobsBundle{}
}
if pe >= params.BeaconConfig().DenebForkEpoch {
return GetPayloadMethodV3, &pb.ExecutionPayloadDenebWithValueAndBlobsBundle{}
}
if pe >= params.BeaconConfig().CapellaForkEpoch {
return GetPayloadMethodV2, &pb.ExecutionPayloadCapellaWithValue{}
}
return GetPayloadMethod, &pb.ExecutionPayload{}
}
// GetPayload calls the engine_getPayloadVX method via JSON-RPC.
// It returns the execution data as well as the blobs bundle.
func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte, slot primitives.Slot) (interfaces.ExecutionData, *pb.BlobsBundle, bool, error) {
func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte, slot primitives.Slot) (*blocks.GetPayloadResponse, error) {
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.GetPayload")
defer span.End()
start := time.Now()
defer func() {
getPayloadLatency.Observe(float64(time.Since(start).Milliseconds()))
}()
d := time.Now().Add(defaultEngineTimeout)
ctx, cancel := context.WithDeadline(ctx, d)
defer cancel()
if slots.ToEpoch(slot) >= params.BeaconConfig().ElectraForkEpoch {
result := &pb.ExecutionPayloadElectraWithValueAndBlobsBundle{}
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethodV4, pb.PayloadIDBytes(payloadId))
if err != nil {
return nil, nil, false, handleRPCError(err)
}
ed, err := blocks.WrappedExecutionPayloadElectra(result.Payload, blocks.PayloadValueToWei(result.Value))
if err != nil {
return nil, nil, false, err
}
return ed, result.BlobsBundle, result.ShouldOverrideBuilder, nil
}
if slots.ToEpoch(slot) >= params.BeaconConfig().DenebForkEpoch {
result := &pb.ExecutionPayloadDenebWithValueAndBlobsBundle{}
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethodV3, pb.PayloadIDBytes(payloadId))
if err != nil {
return nil, nil, false, handleRPCError(err)
}
ed, err := blocks.WrappedExecutionPayloadDeneb(result.Payload, blocks.PayloadValueToWei(result.Value))
if err != nil {
return nil, nil, false, err
}
return ed, result.BlobsBundle, result.ShouldOverrideBuilder, nil
}
if slots.ToEpoch(slot) >= params.BeaconConfig().CapellaForkEpoch {
result := &pb.ExecutionPayloadCapellaWithValue{}
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethodV2, pb.PayloadIDBytes(payloadId))
if err != nil {
return nil, nil, false, handleRPCError(err)
}
ed, err := blocks.WrappedExecutionPayloadCapella(result.Payload, blocks.PayloadValueToWei(result.Value))
if err != nil {
return nil, nil, false, err
}
return ed, nil, false, nil
}
result := &pb.ExecutionPayload{}
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethod, pb.PayloadIDBytes(payloadId))
method, result := getPayloadMethodAndMessage(slot)
err := s.rpcClient.CallContext(ctx, result, method, pb.PayloadIDBytes(payloadId))
if err != nil {
return nil, nil, false, handleRPCError(err)
return nil, handleRPCError(err)
}
ed, err := blocks.WrappedExecutionPayload(result)
res, err := blocks.NewGetPayloadResponse(result)
if err != nil {
return nil, nil, false, err
return nil, err
}
return ed, nil, false, nil
return res, nil
}
func (s *Service) ExchangeCapabilities(ctx context.Context) ([]string, error) {
@@ -591,7 +565,7 @@ func fullPayloadFromPayloadBody(
BlockHash: header.BlockHash(),
Transactions: pb.RecastHexutilByteSlice(body.Transactions),
Withdrawals: body.Withdrawals,
}, big.NewInt(0)) // We can't get the block value and don't care about the block value for this instance
}) // We can't get the block value and don't care about the block value for this instance
case version.Deneb:
ebg, err := header.ExcessBlobGas()
if err != nil {
@@ -620,7 +594,7 @@ func fullPayloadFromPayloadBody(
Withdrawals: body.Withdrawals,
ExcessBlobGas: ebg,
BlobGasUsed: bgu,
}, big.NewInt(0)) // We can't get the block value and don't care about the block value for this instance
}) // We can't get the block value and don't care about the block value for this instance
case version.Electra:
ebg, err := header.ExcessBlobGas()
if err != nil {
@@ -659,7 +633,7 @@ func fullPayloadFromPayloadBody(
BlobGasUsed: bgu,
DepositReceipts: dr,
WithdrawalRequests: wr,
}, big.NewInt(0)) // We can't get the block value and don't care about the block value for this instance
}) // We can't get the block value and don't care about the block value for this instance
default:
return nil, fmt.Errorf("unknown execution block version for payload %d", bVersion)
}

View File

@@ -25,6 +25,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
payloadattribute "github.com/prysmaticlabs/prysm/v5/consensus-types/payload-attribute"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
pb "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
@@ -74,10 +75,10 @@ func TestClient_IPC(t *testing.T) {
want, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
require.Equal(t, true, ok)
payloadId := [8]byte{1}
resp, _, override, err := srv.GetPayload(ctx, payloadId, 1)
resp, err := srv.GetPayload(ctx, payloadId, 1)
require.NoError(t, err)
require.Equal(t, false, override)
pbs := resp.Proto()
require.Equal(t, false, resp.OverrideBuilder)
pbs := resp.ExecutionData.Proto()
resPb, ok := pbs.(*pb.ExecutionPayload)
require.Equal(t, true, ok)
require.NoError(t, err)
@@ -87,10 +88,10 @@ func TestClient_IPC(t *testing.T) {
want, ok := fix["ExecutionPayloadCapellaWithValue"].(*pb.ExecutionPayloadCapellaWithValue)
require.Equal(t, true, ok)
payloadId := [8]byte{1}
resp, _, override, err := srv.GetPayload(ctx, payloadId, params.BeaconConfig().SlotsPerEpoch)
resp, err := srv.GetPayload(ctx, payloadId, params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
require.Equal(t, false, override)
pbs := resp.Proto()
require.Equal(t, false, resp.OverrideBuilder)
pbs := resp.ExecutionData.Proto()
resPb, ok := pbs.(*pb.ExecutionPayloadCapella)
require.Equal(t, true, ok)
require.DeepEqual(t, want, resPb)
@@ -131,7 +132,7 @@ func TestClient_IPC(t *testing.T) {
require.Equal(t, true, ok)
req, ok := fix["ExecutionPayloadCapella"].(*pb.ExecutionPayloadCapella)
require.Equal(t, true, ok)
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(req, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(req)
require.NoError(t, err)
latestValidHash, err := srv.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{})
require.NoError(t, err)
@@ -203,10 +204,10 @@ func TestClient_HTTP(t *testing.T) {
client.rpcClient = rpcClient
// We call the RPC method via HTTP and expect a proper result.
resp, _, override, err := client.GetPayload(ctx, payloadId, 1)
resp, err := client.GetPayload(ctx, payloadId, 1)
require.NoError(t, err)
require.Equal(t, false, override)
pbs := resp.Proto()
require.Equal(t, false, resp.OverrideBuilder)
pbs := resp.ExecutionData.Proto()
pbStruct, ok := pbs.(*pb.ExecutionPayload)
require.Equal(t, true, ok)
require.DeepEqual(t, want, pbStruct)
@@ -249,10 +250,10 @@ func TestClient_HTTP(t *testing.T) {
client.rpcClient = rpcClient
// We call the RPC method via HTTP and expect a proper result.
resp, _, override, err := client.GetPayload(ctx, payloadId, params.BeaconConfig().SlotsPerEpoch)
resp, err := client.GetPayload(ctx, payloadId, params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
require.Equal(t, false, override)
pbs := resp.Proto()
require.Equal(t, false, resp.OverrideBuilder)
pbs := resp.ExecutionData.Proto()
ep, ok := pbs.(*pb.ExecutionPayloadCapella)
require.Equal(t, true, ok)
require.DeepEqual(t, want.ExecutionPayload.BlockHash.Bytes(), ep.BlockHash)
@@ -262,9 +263,7 @@ func TestClient_HTTP(t *testing.T) {
require.DeepEqual(t, want.ExecutionPayload.PrevRandao.Bytes(), ep.PrevRandao)
require.DeepEqual(t, want.ExecutionPayload.ParentHash.Bytes(), ep.ParentHash)
v, err := resp.ValueInGwei()
require.NoError(t, err)
require.Equal(t, uint64(1236), v)
require.Equal(t, primitives.Gwei(1236), primitives.WeiToGwei(resp.Bid))
})
t.Run(GetPayloadMethodV3, func(t *testing.T) {
payloadId := [8]byte{1}
@@ -304,22 +303,22 @@ func TestClient_HTTP(t *testing.T) {
client.rpcClient = rpcClient
// We call the RPC method via HTTP and expect a proper result.
resp, blobsBundle, override, err := client.GetPayload(ctx, payloadId, 2*params.BeaconConfig().SlotsPerEpoch)
resp, err := client.GetPayload(ctx, payloadId, 2*params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
require.Equal(t, true, override)
g, err := resp.ExcessBlobGas()
require.Equal(t, true, resp.OverrideBuilder)
g, err := resp.ExecutionData.ExcessBlobGas()
require.NoError(t, err)
require.DeepEqual(t, uint64(3), g)
g, err = resp.BlobGasUsed()
g, err = resp.ExecutionData.BlobGasUsed()
require.NoError(t, err)
require.DeepEqual(t, uint64(2), g)
commitments := [][]byte{bytesutil.PadTo([]byte("commitment1"), fieldparams.BLSPubkeyLength), bytesutil.PadTo([]byte("commitment2"), fieldparams.BLSPubkeyLength)}
require.DeepEqual(t, commitments, blobsBundle.KzgCommitments)
require.DeepEqual(t, commitments, resp.BlobsBundle.KzgCommitments)
proofs := [][]byte{bytesutil.PadTo([]byte("proof1"), fieldparams.BLSPubkeyLength), bytesutil.PadTo([]byte("proof2"), fieldparams.BLSPubkeyLength)}
require.DeepEqual(t, proofs, blobsBundle.Proofs)
require.DeepEqual(t, proofs, resp.BlobsBundle.Proofs)
blobs := [][]byte{bytesutil.PadTo([]byte("a"), fieldparams.BlobLength), bytesutil.PadTo([]byte("b"), fieldparams.BlobLength)}
require.DeepEqual(t, blobs, blobsBundle.Blobs)
require.DeepEqual(t, blobs, resp.BlobsBundle.Blobs)
})
t.Run(GetPayloadMethodV4, func(t *testing.T) {
payloadId := [8]byte{1}
@@ -359,22 +358,22 @@ func TestClient_HTTP(t *testing.T) {
client.rpcClient = rpcClient
// We call the RPC method via HTTP and expect a proper result.
resp, blobsBundle, override, err := client.GetPayload(ctx, payloadId, 2*params.BeaconConfig().SlotsPerEpoch)
resp, err := client.GetPayload(ctx, payloadId, 2*params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
require.Equal(t, true, override)
g, err := resp.ExcessBlobGas()
require.Equal(t, true, resp.OverrideBuilder)
g, err := resp.ExecutionData.ExcessBlobGas()
require.NoError(t, err)
require.DeepEqual(t, uint64(3), g)
g, err = resp.BlobGasUsed()
g, err = resp.ExecutionData.BlobGasUsed()
require.NoError(t, err)
require.DeepEqual(t, uint64(2), g)
commitments := [][]byte{bytesutil.PadTo([]byte("commitment1"), fieldparams.BLSPubkeyLength), bytesutil.PadTo([]byte("commitment2"), fieldparams.BLSPubkeyLength)}
require.DeepEqual(t, commitments, blobsBundle.KzgCommitments)
require.DeepEqual(t, commitments, resp.BlobsBundle.KzgCommitments)
proofs := [][]byte{bytesutil.PadTo([]byte("proof1"), fieldparams.BLSPubkeyLength), bytesutil.PadTo([]byte("proof2"), fieldparams.BLSPubkeyLength)}
require.DeepEqual(t, proofs, blobsBundle.Proofs)
require.DeepEqual(t, proofs, resp.BlobsBundle.Proofs)
blobs := [][]byte{bytesutil.PadTo([]byte("a"), fieldparams.BlobLength), bytesutil.PadTo([]byte("b"), fieldparams.BlobLength)}
require.DeepEqual(t, blobs, blobsBundle.Blobs)
require.DeepEqual(t, blobs, resp.BlobsBundle.Blobs)
})
t.Run(ForkchoiceUpdatedMethod+" VALID status", func(t *testing.T) {
forkChoiceState := &pb.ForkchoiceState{
@@ -538,7 +537,7 @@ func TestClient_HTTP(t *testing.T) {
client := newPayloadV2Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{})
require.NoError(t, err)
@@ -552,7 +551,7 @@ func TestClient_HTTP(t *testing.T) {
client := newPayloadV3Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'})
require.NoError(t, err)
@@ -566,7 +565,7 @@ func TestClient_HTTP(t *testing.T) {
client := newPayloadV4Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadElectra(execPayload, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadElectra(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'})
require.NoError(t, err)
@@ -594,7 +593,7 @@ func TestClient_HTTP(t *testing.T) {
client := newPayloadV2Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{})
require.ErrorIs(t, ErrAcceptedSyncingPayloadStatus, err)
@@ -608,7 +607,7 @@ func TestClient_HTTP(t *testing.T) {
client := newPayloadV3Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'})
require.ErrorIs(t, ErrAcceptedSyncingPayloadStatus, err)
@@ -622,7 +621,7 @@ func TestClient_HTTP(t *testing.T) {
client := newPayloadV4Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadElectra(execPayload, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadElectra(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'})
require.ErrorIs(t, ErrAcceptedSyncingPayloadStatus, err)
@@ -650,7 +649,7 @@ func TestClient_HTTP(t *testing.T) {
client := newPayloadV2Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{})
require.ErrorIs(t, ErrInvalidBlockHashPayloadStatus, err)
@@ -664,7 +663,7 @@ func TestClient_HTTP(t *testing.T) {
client := newPayloadV3Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'})
require.ErrorIs(t, ErrInvalidBlockHashPayloadStatus, err)
@@ -678,7 +677,7 @@ func TestClient_HTTP(t *testing.T) {
client := newPayloadV4Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadElectra(execPayload, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadElectra(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'})
require.ErrorIs(t, ErrInvalidBlockHashPayloadStatus, err)
@@ -706,7 +705,7 @@ func TestClient_HTTP(t *testing.T) {
client := newPayloadV2Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{})
require.ErrorIs(t, ErrInvalidPayloadStatus, err)
@@ -720,7 +719,7 @@ func TestClient_HTTP(t *testing.T) {
client := newPayloadV3Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'})
require.ErrorIs(t, ErrInvalidPayloadStatus, err)
@@ -734,7 +733,7 @@ func TestClient_HTTP(t *testing.T) {
client := newPayloadV4Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadElectra(execPayload, big.NewInt(0))
wrappedPayload, err := blocks.WrappedExecutionPayloadElectra(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'})
require.ErrorIs(t, ErrInvalidPayloadStatus, err)

View File

@@ -25,7 +25,6 @@ go_library(
"//encoding/bytesutil:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//time/slots:go_default_library",
"@com_github_ethereum_go_ethereum//accounts/abi/bind/backends:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",

View File

@@ -15,7 +15,6 @@ import (
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
pb "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v5/time/slots"
)
// EngineClient --
@@ -23,26 +22,20 @@ type EngineClient struct {
NewPayloadResp []byte
PayloadIDBytes *pb.PayloadIDBytes
ForkChoiceUpdatedResp []byte
ExecutionPayload *pb.ExecutionPayload
ExecutionPayloadCapella *pb.ExecutionPayloadCapella
ExecutionPayloadDeneb *pb.ExecutionPayloadDeneb
ExecutionPayloadElectra *pb.ExecutionPayloadElectra
ExecutionBlock *pb.ExecutionBlock
Err error
ErrLatestExecBlock error
ErrExecBlockByHash error
ErrForkchoiceUpdated error
ErrNewPayload error
ErrGetPayload error
ExecutionPayloadByBlockHash map[[32]byte]*pb.ExecutionPayload
BlockByHashMap map[[32]byte]*pb.ExecutionBlock
NumReconstructedPayloads uint64
TerminalBlockHash []byte
TerminalBlockHashExists bool
BuilderOverride bool
OverrideValidHash [32]byte
BlockValue uint64
BlobsBundle *pb.BlobsBundle
GetPayloadResponse *blocks.GetPayloadResponse
ErrGetPayload error
}
// NewPayload --
@@ -61,33 +54,8 @@ func (e *EngineClient) ForkchoiceUpdated(
}
// GetPayload --
func (e *EngineClient) GetPayload(_ context.Context, _ [8]byte, s primitives.Slot) (interfaces.ExecutionData, *pb.BlobsBundle, bool, error) {
if slots.ToEpoch(s) >= params.BeaconConfig().ElectraForkEpoch {
ed, err := blocks.WrappedExecutionPayloadElectra(e.ExecutionPayloadElectra, big.NewInt(int64(e.BlockValue)))
if err != nil {
return nil, nil, false, err
}
return ed, e.BlobsBundle, e.BuilderOverride, nil
}
if slots.ToEpoch(s) >= params.BeaconConfig().DenebForkEpoch {
ed, err := blocks.WrappedExecutionPayloadDeneb(e.ExecutionPayloadDeneb, big.NewInt(int64(e.BlockValue)))
if err != nil {
return nil, nil, false, err
}
return ed, e.BlobsBundle, e.BuilderOverride, nil
}
if slots.ToEpoch(s) >= params.BeaconConfig().CapellaForkEpoch {
ed, err := blocks.WrappedExecutionPayloadCapella(e.ExecutionPayloadCapella, big.NewInt(int64(e.BlockValue)))
if err != nil {
return nil, nil, false, err
}
return ed, nil, e.BuilderOverride, nil
}
p, err := blocks.WrappedExecutionPayload(e.ExecutionPayload)
if err != nil {
return nil, nil, false, err
}
return p, nil, e.BuilderOverride, e.ErrGetPayload
func (e *EngineClient) GetPayload(_ context.Context, _ [8]byte, s primitives.Slot) (*blocks.GetPayloadResponse, error) {
return e.GetPayloadResponse, e.ErrGetPayload
}
// LatestExecutionBlock --

View File

@@ -12,7 +12,7 @@ import (
)
// constructGenericBeaconBlock constructs a `GenericBeaconBlock` based on the block version and other parameters.
func (vs *Server) constructGenericBeaconBlock(sBlk interfaces.SignedBeaconBlock, blobsBundle *enginev1.BlobsBundle) (*ethpb.GenericBeaconBlock, error) {
func (vs *Server) constructGenericBeaconBlock(sBlk interfaces.SignedBeaconBlock, blobsBundle *enginev1.BlobsBundle, winningBid primitives.Wei) (*ethpb.GenericBeaconBlock, error) {
if sBlk == nil || sBlk.Block() == nil {
return nil, fmt.Errorf("block cannot be nil")
}
@@ -23,17 +23,17 @@ func (vs *Server) constructGenericBeaconBlock(sBlk interfaces.SignedBeaconBlock,
}
isBlinded := sBlk.IsBlinded()
payloadValue := sBlk.ValueInWei()
bidStr := primitives.WeiToBigInt(winningBid).String()
switch sBlk.Version() {
case version.Electra:
return vs.constructElectraBlock(blockProto, isBlinded, payloadValue, blobsBundle), nil
return vs.constructElectraBlock(blockProto, isBlinded, bidStr, blobsBundle), nil
case version.Deneb:
return vs.constructDenebBlock(blockProto, isBlinded, payloadValue, blobsBundle), nil
return vs.constructDenebBlock(blockProto, isBlinded, bidStr, blobsBundle), nil
case version.Capella:
return vs.constructCapellaBlock(blockProto, isBlinded, payloadValue), nil
return vs.constructCapellaBlock(blockProto, isBlinded, bidStr), nil
case version.Bellatrix:
return vs.constructBellatrixBlock(blockProto, isBlinded, payloadValue), nil
return vs.constructBellatrixBlock(blockProto, isBlinded, bidStr), nil
case version.Altair:
return vs.constructAltairBlock(blockProto), nil
case version.Phase0:
@@ -44,42 +44,42 @@ func (vs *Server) constructGenericBeaconBlock(sBlk interfaces.SignedBeaconBlock,
}
// Helper functions for constructing blocks for each version
func (vs *Server) constructElectraBlock(blockProto proto.Message, isBlinded bool, payloadValue primitives.Wei, bundle *enginev1.BlobsBundle) *ethpb.GenericBeaconBlock {
func (vs *Server) constructElectraBlock(blockProto proto.Message, isBlinded bool, payloadValue string, bundle *enginev1.BlobsBundle) *ethpb.GenericBeaconBlock {
if isBlinded {
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedElectra{BlindedElectra: blockProto.(*ethpb.BlindedBeaconBlockElectra)}, IsBlinded: true, PayloadValue: (*payloadValue).String()}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedElectra{BlindedElectra: blockProto.(*ethpb.BlindedBeaconBlockElectra)}, IsBlinded: true, PayloadValue: payloadValue}
}
electraContents := &ethpb.BeaconBlockContentsElectra{Block: blockProto.(*ethpb.BeaconBlockElectra)}
if bundle != nil {
electraContents.KzgProofs = bundle.Proofs
electraContents.Blobs = bundle.Blobs
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Electra{Electra: electraContents}, IsBlinded: false, PayloadValue: (*payloadValue).String()}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Electra{Electra: electraContents}, IsBlinded: false, PayloadValue: payloadValue}
}
func (vs *Server) constructDenebBlock(blockProto proto.Message, isBlinded bool, payloadValue primitives.Wei, bundle *enginev1.BlobsBundle) *ethpb.GenericBeaconBlock {
func (vs *Server) constructDenebBlock(blockProto proto.Message, isBlinded bool, payloadValue string, bundle *enginev1.BlobsBundle) *ethpb.GenericBeaconBlock {
if isBlinded {
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedDeneb{BlindedDeneb: blockProto.(*ethpb.BlindedBeaconBlockDeneb)}, IsBlinded: true, PayloadValue: (*payloadValue).String()}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedDeneb{BlindedDeneb: blockProto.(*ethpb.BlindedBeaconBlockDeneb)}, IsBlinded: true, PayloadValue: payloadValue}
}
denebContents := &ethpb.BeaconBlockContentsDeneb{Block: blockProto.(*ethpb.BeaconBlockDeneb)}
if bundle != nil {
denebContents.KzgProofs = bundle.Proofs
denebContents.Blobs = bundle.Blobs
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Deneb{Deneb: denebContents}, IsBlinded: false, PayloadValue: (*payloadValue).String()}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Deneb{Deneb: denebContents}, IsBlinded: false, PayloadValue: payloadValue}
}
func (vs *Server) constructCapellaBlock(pb proto.Message, isBlinded bool, payloadValue primitives.Wei) *ethpb.GenericBeaconBlock {
func (vs *Server) constructCapellaBlock(pb proto.Message, isBlinded bool, payloadValue string) *ethpb.GenericBeaconBlock {
if isBlinded {
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedCapella{BlindedCapella: pb.(*ethpb.BlindedBeaconBlockCapella)}, IsBlinded: true, PayloadValue: (*payloadValue).String()}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedCapella{BlindedCapella: pb.(*ethpb.BlindedBeaconBlockCapella)}, IsBlinded: true, PayloadValue: payloadValue}
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Capella{Capella: pb.(*ethpb.BeaconBlockCapella)}, IsBlinded: false, PayloadValue: (*payloadValue).String()}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Capella{Capella: pb.(*ethpb.BeaconBlockCapella)}, IsBlinded: false, PayloadValue: payloadValue}
}
func (vs *Server) constructBellatrixBlock(pb proto.Message, isBlinded bool, payloadValue primitives.Wei) *ethpb.GenericBeaconBlock {
func (vs *Server) constructBellatrixBlock(pb proto.Message, isBlinded bool, payloadValue string) *ethpb.GenericBeaconBlock {
if isBlinded {
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedBellatrix{BlindedBellatrix: pb.(*ethpb.BlindedBeaconBlockBellatrix)}, IsBlinded: true, PayloadValue: (*payloadValue).String()}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedBellatrix{BlindedBellatrix: pb.(*ethpb.BlindedBeaconBlockBellatrix)}, IsBlinded: true, PayloadValue: payloadValue}
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Bellatrix{Bellatrix: pb.(*ethpb.BeaconBlockBellatrix)}, IsBlinded: false, PayloadValue: (*payloadValue).String()}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Bellatrix{Bellatrix: pb.(*ethpb.BeaconBlockBellatrix)}, IsBlinded: false, PayloadValue: payloadValue}
}
func (vs *Server) constructAltairBlock(pb proto.Message) *ethpb.GenericBeaconBlock {

View File

@@ -6,6 +6,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/testing/require"
@@ -17,7 +18,7 @@ func TestConstructGenericBeaconBlock(t *testing.T) {
// Test when sBlk or sBlk.Block() is nil
t.Run("NilBlock", func(t *testing.T) {
_, err := vs.constructGenericBeaconBlock(nil, nil)
_, err := vs.constructGenericBeaconBlock(nil, nil, primitives.ZeroWei)
require.ErrorContains(t, "block cannot be nil", err)
})
@@ -38,7 +39,7 @@ func TestConstructGenericBeaconBlock(t *testing.T) {
require.NoError(t, err)
r1, err := eb.Block.HashTreeRoot()
require.NoError(t, err)
result, err := vs.constructGenericBeaconBlock(b, nil)
result, err := vs.constructGenericBeaconBlock(b, nil, primitives.ZeroWei)
require.NoError(t, err)
r2, err := result.GetElectra().Block.HashTreeRoot()
require.NoError(t, err)
@@ -70,7 +71,7 @@ func TestConstructGenericBeaconBlock(t *testing.T) {
contents := &eth.BeaconBlockContentsDeneb{Block: eb.Block, KzgProofs: bundle.Proofs, Blobs: bundle.Blobs}
r1, err := contents.HashTreeRoot()
require.NoError(t, err)
result, err := vs.constructGenericBeaconBlock(b, bundle)
result, err := vs.constructGenericBeaconBlock(b, bundle, primitives.ZeroWei)
require.NoError(t, err)
r2, err := result.GetDeneb().HashTreeRoot()
require.NoError(t, err)
@@ -85,7 +86,7 @@ func TestConstructGenericBeaconBlock(t *testing.T) {
r1, err := b.Block().HashTreeRoot()
require.NoError(t, err)
scs := &enginev1.BlobsBundle{}
result, err := vs.constructGenericBeaconBlock(b, scs)
result, err := vs.constructGenericBeaconBlock(b, scs, primitives.ZeroWei)
require.NoError(t, err)
r2, err := result.GetBlindedDeneb().HashTreeRoot()
require.NoError(t, err)
@@ -98,7 +99,7 @@ func TestConstructGenericBeaconBlock(t *testing.T) {
t.Run("capella block", func(t *testing.T) {
b, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella())
require.NoError(t, err)
result, err := vs.constructGenericBeaconBlock(b, nil)
result, err := vs.constructGenericBeaconBlock(b, nil, primitives.ZeroWei)
require.NoError(t, err)
r1, err := result.GetCapella().HashTreeRoot()
require.NoError(t, err)
@@ -112,7 +113,7 @@ func TestConstructGenericBeaconBlock(t *testing.T) {
t.Run("blind capella block", func(t *testing.T) {
b, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockCapella())
require.NoError(t, err)
result, err := vs.constructGenericBeaconBlock(b, nil)
result, err := vs.constructGenericBeaconBlock(b, nil, primitives.ZeroWei)
require.NoError(t, err)
r1, err := result.GetBlindedCapella().HashTreeRoot()
require.NoError(t, err)
@@ -126,7 +127,7 @@ func TestConstructGenericBeaconBlock(t *testing.T) {
t.Run("bellatrix block", func(t *testing.T) {
b, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockBellatrix())
require.NoError(t, err)
result, err := vs.constructGenericBeaconBlock(b, nil)
result, err := vs.constructGenericBeaconBlock(b, nil, primitives.ZeroWei)
require.NoError(t, err)
r1, err := result.GetBellatrix().HashTreeRoot()
require.NoError(t, err)
@@ -140,7 +141,7 @@ func TestConstructGenericBeaconBlock(t *testing.T) {
t.Run("altair block", func(t *testing.T) {
b, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockAltair())
require.NoError(t, err)
result, err := vs.constructGenericBeaconBlock(b, nil)
result, err := vs.constructGenericBeaconBlock(b, nil, primitives.ZeroWei)
require.NoError(t, err)
r1, err := result.GetAltair().HashTreeRoot()
require.NoError(t, err)
@@ -154,7 +155,7 @@ func TestConstructGenericBeaconBlock(t *testing.T) {
t.Run("phase0 block", func(t *testing.T) {
b, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock())
require.NoError(t, err)
result, err := vs.constructGenericBeaconBlock(b, nil)
result, err := vs.constructGenericBeaconBlock(b, nil, primitives.ZeroWei)
require.NoError(t, err)
r1, err := result.GetPhase0().HashTreeRoot()
require.NoError(t, err)

View File

@@ -11,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
emptypb "github.com/golang/protobuf/ptypes/empty"
"github.com/pkg/errors"
builderapi "github.com/prysmaticlabs/prysm/v5/api/client/builder"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/builder"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/cache"
@@ -25,6 +26,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
"github.com/prysmaticlabs/prysm/v5/time/slots"
@@ -40,7 +42,7 @@ var eth1DataNotification bool
const (
eth1dataTimeout = 2 * time.Second
defaultBuilderBoostFactor = uint64(100)
defaultBuilderBoostFactor = primitives.Gwei(100)
)
// GetBeaconBlock is called by a proposer during its assigned slot to request a block to sign
@@ -93,27 +95,19 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
builderBoostFactor := defaultBuilderBoostFactor
if req.BuilderBoostFactor != nil {
builderBoostFactor = req.BuilderBoostFactor.Value
builderBoostFactor = primitives.Gwei(req.BuilderBoostFactor.Value)
}
if err = vs.BuildBlockParallel(ctx, sBlk, head, req.SkipMevBoost, builderBoostFactor); err != nil {
return nil, errors.Wrap(err, "could not build block in parallel")
}
sr, err := vs.computeStateRoot(ctx, sBlk)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not compute state root: %v", err)
}
sBlk.SetStateRoot(sr)
resp, err := vs.BuildBlockParallel(ctx, sBlk, head, req.SkipMevBoost, builderBoostFactor)
log.WithFields(logrus.Fields{
"slot": req.Slot,
"sinceSlotStartTime": time.Since(t),
"validator": sBlk.Block().ProposerIndex(),
}).Info("Finished building block")
// Blob cache is updated after BuildBlockParallel
return vs.constructGenericBeaconBlock(sBlk, bundleCache.get(req.Slot))
if err != nil {
return nil, errors.Wrap(err, "could not build block in parallel")
}
return resp, nil
}
func (vs *Server) handleSuccesfulReorgAttempt(ctx context.Context, slot primitives.Slot, parentRoot, headRoot [32]byte) (state.BeaconState, error) {
@@ -184,7 +178,7 @@ func (vs *Server) getParentState(ctx context.Context, slot primitives.Slot) (sta
return head, parentRoot, err
}
func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.SignedBeaconBlock, head state.BeaconState, skipMevBoost bool, builderBoostFactor uint64) error {
func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.SignedBeaconBlock, head state.BeaconState, skipMevBoost bool, builderBoostFactor primitives.Gwei) (*ethpb.GenericBeaconBlock, error) {
// Build consensus fields in background
var wg sync.WaitGroup
wg.Add(1)
@@ -231,30 +225,39 @@ func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.Signed
vs.setBlsToExecData(sBlk, head)
}()
localPayload, overrideBuilder, err := vs.getLocalPayload(ctx, sBlk.Block(), head)
if err != nil {
return status.Errorf(codes.Internal, "Could not get local payload: %v", err)
}
// There's no reason to try to get a builder bid if local override is true.
var builderPayload interfaces.ExecutionData
var builderKzgCommitments [][]byte
overrideBuilder = overrideBuilder || skipMevBoost // Skip using mev-boost if requested by the caller.
if !overrideBuilder {
builderPayload, builderKzgCommitments, err = vs.getBuilderPayloadAndBlobs(ctx, sBlk.Block().Slot(), sBlk.Block().ProposerIndex())
winningBid := primitives.ZeroWei
var bundle *enginev1.BlobsBundle
if sBlk.Version() >= version.Bellatrix {
local, err := vs.getLocalPayload(ctx, sBlk.Block(), head)
if err != nil {
builderGetPayloadMissCount.Inc()
log.WithError(err).Error("Could not get builder payload")
return nil, status.Errorf(codes.Internal, "Could not get local payload: %v", err)
}
// There's no reason to try to get a builder bid if local override is true.
var builderBid builderapi.Bid
if !(local.OverrideBuilder || skipMevBoost) {
builderBid, err = vs.getBuilderPayloadAndBlobs(ctx, sBlk.Block().Slot(), sBlk.Block().ProposerIndex())
if err != nil {
builderGetPayloadMissCount.Inc()
log.WithError(err).Error("Could not get builder payload")
}
}
winningBid, bundle, err = setExecutionData(ctx, sBlk, local, builderBid, builderBoostFactor)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not set execution data: %v", err)
}
}
if err := setExecutionData(ctx, sBlk, localPayload, builderPayload, builderKzgCommitments, builderBoostFactor); err != nil {
return status.Errorf(codes.Internal, "Could not set execution data: %v", err)
wg.Wait()
sr, err := vs.computeStateRoot(ctx, sBlk)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not compute state root: %v", err)
}
sBlk.SetStateRoot(sr)
wg.Wait() // Wait until block is built via consensus and execution fields.
return nil
return vs.constructGenericBeaconBlock(sBlk, bundle, winningBid)
}
// ProposeBeaconBlock handles the proposal of beacon blocks.

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"fmt"
"math/big"
"strings"
"time"
@@ -14,12 +15,14 @@ import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing"
"github.com/prysmaticlabs/prysm/v5/network/forks"
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
"github.com/prysmaticlabs/prysm/v5/time/slots"
"github.com/sirupsen/logrus"
@@ -50,47 +53,52 @@ var emptyTransactionsRoot = [32]byte{127, 254, 36, 30, 166, 1, 135, 253, 176, 24
const blockBuilderTimeout = 1 * time.Second
// Sets the execution data for the block. Execution data can come from local EL client or remote builder depends on validator registration and circuit breaker conditions.
func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, localPayload, builderPayload interfaces.ExecutionData, builderKzgCommitments [][]byte, builderBoostFactor uint64) error {
func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, local *blocks.GetPayloadResponse, bid builder.Bid, builderBoostFactor primitives.Gwei) (primitives.Wei, *enginev1.BlobsBundle, error) {
_, span := trace.StartSpan(ctx, "ProposerServer.setExecutionData")
defer span.End()
slot := blk.Block().Slot()
if slots.ToEpoch(slot) < params.BeaconConfig().BellatrixForkEpoch {
return nil
return primitives.ZeroWei, nil, nil
}
if localPayload == nil {
return errors.New("local payload is nil")
if local == nil {
return primitives.ZeroWei, nil, errors.New("local payload is nil")
}
// Use local payload if builder payload is nil.
if builderPayload == nil {
return setLocalExecution(blk, localPayload)
if bid == nil {
return local.Bid, local.BlobsBundle, setLocalExecution(blk, local)
}
var builderKzgCommitments [][]byte
builderPayload, err := bid.Header()
if err != nil {
log.WithError(err).Warn("Proposer: failed to retrieve header from BuilderBid")
return local.Bid, local.BlobsBundle, setLocalExecution(blk, local)
}
if bid.Version() >= version.Deneb {
builderKzgCommitments, err = bid.BlobKzgCommitments()
if err != nil {
log.WithError(err).Warn("Proposer: failed to retrieve kzg commitments from BuilderBid")
}
}
switch {
case blk.Version() >= version.Capella:
// Compare payload values between local and builder. Default to the local value if it is higher.
localValueGwei, err := localPayload.ValueInGwei()
if err != nil {
return errors.Wrap(err, "failed to get local payload value")
}
builderValueGwei, err := builderPayload.ValueInGwei()
if err != nil {
log.WithError(err).Warn("Proposer: failed to get builder payload value") // Default to local if can't get builder value.
return setLocalExecution(blk, localPayload)
}
withdrawalsMatched, err := matchingWithdrawalsRoot(localPayload, builderPayload)
withdrawalsMatched, err := matchingWithdrawalsRoot(local.ExecutionData, builderPayload)
if err != nil {
tracing.AnnotateError(span, err)
log.WithError(err).Warn("Proposer: failed to match withdrawals root")
return setLocalExecution(blk, localPayload)
return local.Bid, local.BlobsBundle, setLocalExecution(blk, local)
}
// Compare payload values between local and builder. Default to the local value if it is higher.
localValueGwei := primitives.WeiToGwei(local.Bid)
builderValueGwei := primitives.WeiToGwei(bid.Value())
// Use builder payload if the following in true:
// builder_bid_value * builderBoostFactor(default 100) > local_block_value * (local-block-value-boost + 100)
boost := params.BeaconConfig().LocalBlockValueBoost
boost := primitives.Gwei(params.BeaconConfig().LocalBlockValueBoost)
higherValueBuilder := builderValueGwei*builderBoostFactor > localValueGwei*(100+boost)
if boost > 0 && builderBoostFactor != defaultBuilderBoostFactor {
log.WithFields(logrus.Fields{
@@ -107,9 +115,9 @@ func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, loc
if higherValueBuilder && withdrawalsMatched { // Builder value is higher and withdrawals match.
if err := setBuilderExecution(blk, builderPayload, builderKzgCommitments); err != nil {
log.WithError(err).Warn("Proposer: failed to set builder payload")
return setLocalExecution(blk, localPayload)
return local.Bid, local.BlobsBundle, setLocalExecution(blk, local)
} else {
return nil
return bid.Value(), nil, nil
}
}
if !higherValueBuilder {
@@ -127,39 +135,39 @@ func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, loc
trace.Int64Attribute("builderGweiValue", int64(builderValueGwei)), // lint:ignore uintcast -- This is OK for tracing.
trace.Int64Attribute("builderBoostFactor", int64(builderBoostFactor)), // lint:ignore uintcast -- This is OK for tracing.
)
return setLocalExecution(blk, localPayload)
return local.Bid, local.BlobsBundle, setLocalExecution(blk, local)
default: // Bellatrix case.
if err := setBuilderExecution(blk, builderPayload, builderKzgCommitments); err != nil {
log.WithError(err).Warn("Proposer: failed to set builder payload")
return setLocalExecution(blk, localPayload)
return local.Bid, local.BlobsBundle, setLocalExecution(blk, local)
} else {
return nil
return bid.Value(), nil, nil
}
}
}
// This function retrieves the payload header and kzg commitments given the slot number and the validator index.
// It's a no-op if the latest head block is not versioned bellatrix.
func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitives.Slot, idx primitives.ValidatorIndex) (interfaces.ExecutionData, [][]byte, error) {
func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitives.Slot, idx primitives.ValidatorIndex) (builder.Bid, error) {
ctx, span := trace.StartSpan(ctx, "ProposerServer.getPayloadHeaderFromBuilder")
defer span.End()
if slots.ToEpoch(slot) < params.BeaconConfig().BellatrixForkEpoch {
return nil, nil, errors.New("can't get payload header from builder before bellatrix epoch")
return nil, errors.New("can't get payload header from builder before bellatrix epoch")
}
b, err := vs.HeadFetcher.HeadBlock(ctx)
if err != nil {
return nil, nil, err
return nil, err
}
h, err := b.Block().Body().Execution()
if err != nil {
return nil, nil, errors.Wrap(err, "failed to get execution header")
return nil, errors.Wrap(err, "failed to get execution header")
}
pk, err := vs.HeadFetcher.HeadValidatorIndexToPublicKey(ctx, idx)
if err != nil {
return nil, nil, err
return nil, err
}
ctx, cancel := context.WithTimeout(ctx, blockBuilderTimeout)
@@ -167,76 +175,76 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitiv
signedBid, err := vs.BlockBuilder.GetHeader(ctx, slot, bytesutil.ToBytes32(h.BlockHash()), pk)
if err != nil {
return nil, nil, err
return nil, err
}
if signedBid.IsNil() {
return nil, nil, errors.New("builder returned nil bid")
return nil, errors.New("builder returned nil bid")
}
fork, err := forks.Fork(slots.ToEpoch(slot))
if err != nil {
return nil, nil, errors.Wrap(err, "unable to get fork information")
return nil, errors.Wrap(err, "unable to get fork information")
}
forkName, ok := params.BeaconConfig().ForkVersionNames[bytesutil.ToBytes4(fork.CurrentVersion)]
if !ok {
return nil, nil, errors.New("unable to find current fork in schedule")
return nil, errors.New("unable to find current fork in schedule")
}
if !strings.EqualFold(version.String(signedBid.Version()), forkName) {
return nil, nil, fmt.Errorf("builder bid response version: %d is different from head block version: %d for epoch %d", signedBid.Version(), b.Version(), slots.ToEpoch(slot))
return nil, fmt.Errorf("builder bid response version: %d is different from head block version: %d for epoch %d", signedBid.Version(), b.Version(), slots.ToEpoch(slot))
}
bid, err := signedBid.Message()
if err != nil {
return nil, nil, errors.Wrap(err, "could not get bid")
return nil, errors.Wrap(err, "could not get bid")
}
if bid.IsNil() {
return nil, nil, errors.New("builder returned nil bid")
return nil, errors.New("builder returned nil bid")
}
v := bytesutil.LittleEndianBytesToBigInt(bid.Value())
if v.String() == "0" {
return nil, nil, errors.New("builder returned header with 0 bid amount")
v := bid.Value()
if big.NewInt(0).Cmp(v) == 0 {
return nil, errors.New("builder returned header with 0 bid amount")
}
header, err := bid.Header()
if err != nil {
return nil, nil, errors.Wrap(err, "could not get bid header")
return nil, errors.Wrap(err, "could not get bid header")
}
txRoot, err := header.TransactionsRoot()
if err != nil {
return nil, nil, errors.Wrap(err, "could not get transaction root")
return nil, errors.Wrap(err, "could not get transaction root")
}
if bytesutil.ToBytes32(txRoot) == emptyTransactionsRoot {
return nil, nil, errors.New("builder returned header with an empty tx root")
return nil, errors.New("builder returned header with an empty tx root")
}
if !bytes.Equal(header.ParentHash(), h.BlockHash()) {
return nil, nil, fmt.Errorf("incorrect parent hash %#x != %#x", header.ParentHash(), h.BlockHash())
return nil, fmt.Errorf("incorrect parent hash %#x != %#x", header.ParentHash(), h.BlockHash())
}
t, err := slots.ToTime(uint64(vs.TimeFetcher.GenesisTime().Unix()), slot)
if err != nil {
return nil, nil, err
return nil, err
}
if header.Timestamp() != uint64(t.Unix()) {
return nil, nil, fmt.Errorf("incorrect timestamp %d != %d", header.Timestamp(), uint64(t.Unix()))
return nil, fmt.Errorf("incorrect timestamp %d != %d", header.Timestamp(), uint64(t.Unix()))
}
if err := validateBuilderSignature(signedBid); err != nil {
return nil, nil, errors.Wrap(err, "could not validate builder signature")
return nil, errors.Wrap(err, "could not validate builder signature")
}
var kzgCommitments [][]byte
if bid.Version() >= version.Deneb {
kzgCommitments, err = bid.BlobKzgCommitments()
if err != nil {
return nil, nil, errors.Wrap(err, "could not get blob kzg commitments")
return nil, errors.Wrap(err, "could not get blob kzg commitments")
}
if len(kzgCommitments) > fieldparams.MaxBlobsPerBlock {
return nil, nil, fmt.Errorf("builder returned too many kzg commitments: %d", len(kzgCommitments))
return nil, fmt.Errorf("builder returned too many kzg commitments: %d", len(kzgCommitments))
}
for _, c := range kzgCommitments {
if len(c) != fieldparams.BLSPubkeyLength {
return nil, nil, fmt.Errorf("builder returned invalid kzg commitment length: %d", len(c))
return nil, fmt.Errorf("builder returned invalid kzg commitment length: %d", len(c))
}
}
}
@@ -255,12 +263,12 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitiv
l.Info("Received header with bid")
span.AddAttributes(
trace.StringAttribute("value", v.String()),
trace.StringAttribute("value", primitives.WeiToBigInt(v).String()),
trace.StringAttribute("builderPubKey", fmt.Sprintf("%#x", bid.Pubkey())),
trace.StringAttribute("blockHash", fmt.Sprintf("%#x", header.BlockHash())),
)
return header, kzgCommitments, nil
return bid, nil
}
// Validates builder signature and returns an error if the signature is invalid.
@@ -310,13 +318,12 @@ func matchingWithdrawalsRoot(local, builder interfaces.ExecutionData) (bool, err
// setLocalExecution sets the execution context for a local beacon block.
// It delegates to setExecution for the actual work.
func setLocalExecution(blk interfaces.SignedBeaconBlock, execution interfaces.ExecutionData) error {
func setLocalExecution(blk interfaces.SignedBeaconBlock, local *blocks.GetPayloadResponse) error {
var kzgCommitments [][]byte
fullBlobsBundle := bundleCache.get(blk.Block().Slot())
if fullBlobsBundle != nil {
kzgCommitments = fullBlobsBundle.KzgCommitments
if local.BlobsBundle != nil {
kzgCommitments = local.BlobsBundle.KzgCommitments
}
return setExecution(blk, execution, false, kzgCommitments)
return setExecution(blk, local.ExecutionData, false, kzgCommitments)
}
// setBuilderExecution sets the execution context for a builder's beacon block.

View File

@@ -28,6 +28,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
"github.com/prysmaticlabs/prysm/v5/testing/require"
"github.com/prysmaticlabs/prysm/v5/testing/util"
"github.com/prysmaticlabs/prysm/v5/time/slots"
@@ -46,7 +47,7 @@ func TestServer_setExecutionData(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
capellaTransitionState, _ := util.DeterministicGenesisStateCapella(t, 1)
wrappedHeaderCapella, err := blocks.WrappedExecutionPayloadHeaderCapella(&v1.ExecutionPayloadHeaderCapella{BlockNumber: 1}, big.NewInt(0))
wrappedHeaderCapella, err := blocks.WrappedExecutionPayloadHeaderCapella(&v1.ExecutionPayloadHeaderCapella{BlockNumber: 1})
require.NoError(t, err)
require.NoError(t, capellaTransitionState.SetLatestExecutionPayloadHeader(wrappedHeaderCapella))
b2pbCapella := util.NewBeaconBlockCapella()
@@ -59,7 +60,7 @@ func TestServer_setExecutionData(t *testing.T) {
require.NoError(t, beaconDB.SaveFeeRecipientsByValidatorIDs(context.Background(), []primitives.ValidatorIndex{0}, []common.Address{{}}))
denebTransitionState, _ := util.DeterministicGenesisStateDeneb(t, 1)
wrappedHeaderDeneb, err := blocks.WrappedExecutionPayloadHeaderDeneb(&v1.ExecutionPayloadHeaderDeneb{BlockNumber: 2}, big.NewInt(0))
wrappedHeaderDeneb, err := blocks.WrappedExecutionPayloadHeaderDeneb(&v1.ExecutionPayloadHeaderDeneb{BlockNumber: 2})
require.NoError(t, err)
require.NoError(t, denebTransitionState.SetLatestExecutionPayloadHeader(wrappedHeaderDeneb))
b2pbDeneb := util.NewBeaconBlockDeneb()
@@ -77,8 +78,14 @@ func TestServer_setExecutionData(t *testing.T) {
Amount: 3,
}}
id := &v1.PayloadIDBytes{0x1}
ed, err := blocks.NewWrappedExecutionData(&v1.ExecutionPayloadCapella{BlockNumber: 1, Withdrawals: withdrawals})
require.NoError(t, err)
vs := &Server{
ExecutionEngineCaller: &powtesting.EngineClient{PayloadIDBytes: id, ExecutionPayloadCapella: &v1.ExecutionPayloadCapella{BlockNumber: 1, Withdrawals: withdrawals}, BlockValue: 0},
ExecutionEngineCaller: &powtesting.EngineClient{
GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed},
PayloadIDBytes: id,
},
HeadFetcher: &blockchainTest.ChainService{State: capellaTransitionState},
FinalizationFetcher: &blockchainTest.ChainService{},
BeaconDB: beaconDB,
@@ -92,12 +99,14 @@ func TestServer_setExecutionData(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella())
require.NoError(t, err)
b := blk.Block()
localPayload, _, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderPayload, builderKzgCommitments, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
require.NoError(t, err)
require.DeepEqual(t, [][]uint8(nil), builderKzgCommitments)
require.NoError(t, setExecutionData(context.Background(), blk, localPayload, builderPayload, builderKzgCommitments, defaultBuilderBoostFactor))
require.IsNil(t, builderBid)
_, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor)
require.NoError(t, err)
require.IsNil(t, bundle)
e, err := blk.Block().Body().Execution()
require.NoError(t, err)
require.Equal(t, uint64(1), e.BlockNumber()) // Local block
@@ -153,12 +162,20 @@ func TestServer_setExecutionData(t *testing.T) {
vs.HeadFetcher = chain
b := blk.Block()
localPayload, _, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderPayload, builderKzgCommitments, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
require.NoError(t, err)
require.DeepEqual(t, [][]uint8(nil), builderKzgCommitments)
require.NoError(t, setExecutionData(context.Background(), blk, localPayload, builderPayload, builderKzgCommitments, defaultBuilderBoostFactor))
_, err = builderBid.Header()
require.NoError(t, err)
builderKzgCommitments, err := builderBid.BlobKzgCommitments()
if builderBid.Version() >= version.Deneb {
require.NoError(t, err)
}
require.DeepEqual(t, [][]uint8{}, builderKzgCommitments)
_, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor)
require.NoError(t, err)
require.IsNil(t, bundle)
e, err := blk.Block().Body().Execution()
require.NoError(t, err)
require.Equal(t, uint64(1), e.BlockNumber()) // Local block because incorrect withdrawals
@@ -217,12 +234,20 @@ func TestServer_setExecutionData(t *testing.T) {
vs.HeadFetcher = chain
b := blk.Block()
localPayload, _, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderPayload, builderKzgCommitments, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
require.NoError(t, err)
require.DeepEqual(t, [][]uint8(nil), builderKzgCommitments)
require.NoError(t, setExecutionData(context.Background(), blk, localPayload, builderPayload, builderKzgCommitments, defaultBuilderBoostFactor))
_, err = builderBid.Header()
require.NoError(t, err)
builderKzgCommitments, err := builderBid.BlobKzgCommitments()
if builderBid.Version() >= version.Deneb {
require.NoError(t, err)
}
require.DeepEqual(t, [][]uint8{}, builderKzgCommitments)
_, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor)
require.NoError(t, err)
require.IsNil(t, bundle)
e, err := blk.Block().Body().Execution()
require.NoError(t, err)
require.Equal(t, uint64(2), e.BlockNumber()) // Builder block
@@ -280,12 +305,20 @@ func TestServer_setExecutionData(t *testing.T) {
vs.HeadFetcher = chain
b := blk.Block()
localPayload, _, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderPayload, builderKzgCommitments, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
require.NoError(t, err)
require.DeepEqual(t, [][]uint8(nil), builderKzgCommitments)
require.NoError(t, setExecutionData(context.Background(), blk, localPayload, builderPayload, builderKzgCommitments, math.MaxUint64))
_, err = builderBid.Header()
require.NoError(t, err)
builderKzgCommitments, err := builderBid.BlobKzgCommitments()
if builderBid.Version() >= version.Deneb {
require.NoError(t, err)
}
require.DeepEqual(t, [][]uint8{}, builderKzgCommitments)
_, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, math.MaxUint64)
require.NoError(t, err)
require.IsNil(t, bundle)
e, err := blk.Block().Body().Execution()
require.NoError(t, err)
require.Equal(t, uint64(2), e.BlockNumber()) // builder block
@@ -343,12 +376,20 @@ func TestServer_setExecutionData(t *testing.T) {
vs.HeadFetcher = chain
b := blk.Block()
localPayload, _, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderPayload, builderKzgCommitments, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
require.NoError(t, err)
require.DeepEqual(t, [][]uint8(nil), builderKzgCommitments)
require.NoError(t, setExecutionData(context.Background(), blk, localPayload, builderPayload, builderKzgCommitments, 0))
_, err = builderBid.Header()
require.NoError(t, err)
builderKzgCommitments, err := builderBid.BlobKzgCommitments()
if builderBid.Version() >= version.Deneb {
require.NoError(t, err)
}
require.DeepEqual(t, [][]uint8{}, builderKzgCommitments)
_, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, 0)
require.NoError(t, err)
require.IsNil(t, bundle)
e, err := blk.Block().Body().Execution()
require.NoError(t, err)
require.Equal(t, uint64(1), e.BlockNumber()) // local block
@@ -356,14 +397,25 @@ func TestServer_setExecutionData(t *testing.T) {
t.Run("Builder configured. Local block has higher value", func(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella())
require.NoError(t, err)
vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, ExecutionPayloadCapella: &v1.ExecutionPayloadCapella{BlockNumber: 3}, BlockValue: 2 * 1e9}
elBid := primitives.Uint64ToWei(2 * 1e9)
ed, err := blocks.NewWrappedExecutionData(&v1.ExecutionPayloadCapella{BlockNumber: 3})
require.NoError(t, err)
vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed, Bid: elBid}}
b := blk.Block()
localPayload, _, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderPayload, builderKzgCommitments, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
require.NoError(t, err)
require.DeepEqual(t, [][]uint8(nil), builderKzgCommitments)
require.NoError(t, setExecutionData(context.Background(), blk, localPayload, builderPayload, builderKzgCommitments, defaultBuilderBoostFactor))
_, err = builderBid.Header()
require.NoError(t, err)
builderKzgCommitments, err := builderBid.BlobKzgCommitments()
if builderBid.Version() >= version.Deneb {
require.NoError(t, err)
}
require.DeepEqual(t, [][]uint8{}, builderKzgCommitments)
_, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor)
require.NoError(t, err)
require.IsNil(t, bundle)
e, err := blk.Block().Body().Execution()
require.NoError(t, err)
require.Equal(t, uint64(3), e.BlockNumber()) // Local block
@@ -377,14 +429,26 @@ func TestServer_setExecutionData(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella())
require.NoError(t, err)
vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, ExecutionPayloadCapella: &v1.ExecutionPayloadCapella{BlockNumber: 3}, BlockValue: 1 * 1e9}
elBid := primitives.Uint64ToWei(1 * 1e9)
ed, err := blocks.NewWrappedExecutionData(&v1.ExecutionPayloadCapella{BlockNumber: 3})
require.NoError(t, err)
vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed, Bid: elBid}}
b := blk.Block()
localPayload, _, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderPayload, builderKzgCommitments, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
require.NoError(t, err)
require.DeepEqual(t, [][]uint8(nil), builderKzgCommitments)
require.NoError(t, setExecutionData(context.Background(), blk, localPayload, builderPayload, builderKzgCommitments, defaultBuilderBoostFactor))
builderKzgCommitments, err := builderBid.BlobKzgCommitments()
if builderBid.Version() >= version.Deneb {
require.NoError(t, err)
}
_, err = builderBid.Header()
require.NoError(t, err)
require.DeepEqual(t, [][]uint8{}, builderKzgCommitments)
_, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor)
require.NoError(t, err)
require.IsNil(t, bundle)
e, err := blk.Block().Body().Execution()
require.NoError(t, err)
require.Equal(t, uint64(3), e.BlockNumber()) // Local block
@@ -399,14 +463,18 @@ func TestServer_setExecutionData(t *testing.T) {
HasConfigured: true,
Cfg: &builderTest.Config{BeaconDB: beaconDB},
}
vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, ExecutionPayloadCapella: &v1.ExecutionPayloadCapella{BlockNumber: 4}, BlockValue: 0}
b := blk.Block()
localPayload, _, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
ed, err := blocks.NewWrappedExecutionData(&v1.ExecutionPayloadCapella{BlockNumber: 4})
require.NoError(t, err)
builderPayload, builderKzgCommitments, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed}}
b := blk.Block()
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
require.ErrorIs(t, consensus_types.ErrNilObjectWrapped, err) // Builder returns fault. Use local block
require.DeepEqual(t, [][]uint8(nil), builderKzgCommitments)
require.NoError(t, setExecutionData(context.Background(), blk, localPayload, builderPayload, builderKzgCommitments, defaultBuilderBoostFactor))
require.IsNil(t, builderBid)
_, bundle, err := setExecutionData(context.Background(), blk, res, nil, defaultBuilderBoostFactor)
require.NoError(t, err)
require.IsNil(t, bundle)
e, err := blk.Block().Body().Execution()
require.NoError(t, err)
require.Equal(t, uint64(4), e.BlockNumber()) // Local block
@@ -428,17 +496,21 @@ func TestServer_setExecutionData(t *testing.T) {
Proofs: [][]byte{{4, 5, 6}},
Blobs: [][]byte{{7, 8, 9}},
}
vs.ExecutionEngineCaller = &powtesting.EngineClient{
PayloadIDBytes: id,
BlobsBundle: blobsBundle,
ExecutionPayloadDeneb: &v1.ExecutionPayloadDeneb{BlockNumber: 4},
BlockValue: 0}
blk.SetSlot(primitives.Slot(params.BeaconConfig().DenebForkEpoch) * params.BeaconConfig().SlotsPerEpoch)
localPayload, _, err := vs.getLocalPayload(ctx, blk.Block(), capellaTransitionState)
ed, err := blocks.NewWrappedExecutionData(&v1.ExecutionPayloadDeneb{BlockNumber: 4})
require.NoError(t, err)
require.Equal(t, uint64(4), localPayload.BlockNumber())
cachedBundle := bundleCache.get(blk.Block().Slot())
require.DeepEqual(t, cachedBundle, blobsBundle)
vs.ExecutionEngineCaller = &powtesting.EngineClient{
PayloadIDBytes: id,
GetPayloadResponse: &blocks.GetPayloadResponse{
ExecutionData: ed,
BlobsBundle: blobsBundle,
Bid: primitives.ZeroWei,
},
}
blk.SetSlot(primitives.Slot(params.BeaconConfig().DenebForkEpoch) * params.BeaconConfig().SlotsPerEpoch)
res, err := vs.getLocalPayload(ctx, blk.Block(), capellaTransitionState)
require.NoError(t, err)
require.Equal(t, uint64(4), res.ExecutionData.BlockNumber())
require.DeepEqual(t, res.BlobsBundle, blobsBundle)
})
t.Run("Can get builder payload and blobs in Deneb", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
@@ -502,19 +574,31 @@ func TestServer_setExecutionData(t *testing.T) {
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix()))
vs.TimeFetcher = chain
vs.HeadFetcher = chain
vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, ExecutionPayloadDeneb: &v1.ExecutionPayloadDeneb{BlockNumber: 4, Withdrawals: withdrawals}, BlockValue: 0}
ed, err := blocks.NewWrappedExecutionData(&v1.ExecutionPayloadDeneb{BlockNumber: 4, Withdrawals: withdrawals})
require.NoError(t, err)
vs.ExecutionEngineCaller = &powtesting.EngineClient{
PayloadIDBytes: id,
GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed},
}
require.NoError(t, err)
blk.SetSlot(primitives.Slot(params.BeaconConfig().DenebForkEpoch) * params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
builderPayload, builderKzgCommitments, err := vs.getBuilderPayloadAndBlobs(ctx, blk.Block().Slot(), blk.Block().ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, blk.Block().Slot(), blk.Block().ProposerIndex())
require.NoError(t, err)
builderPayload, err := builderBid.Header()
require.NoError(t, err)
builderKzgCommitments, err := builderBid.BlobKzgCommitments()
require.NoError(t, err)
require.DeepEqual(t, bid.BlobKzgCommitments, builderKzgCommitments)
require.Equal(t, bid.Header.BlockNumber, builderPayload.BlockNumber()) // header should be the same from block
localPayload, _, err := vs.getLocalPayload(ctx, blk.Block(), denebTransitionState)
res, err := vs.getLocalPayload(ctx, blk.Block(), denebTransitionState)
require.NoError(t, err)
require.NoError(t, setExecutionData(context.Background(), blk, localPayload, builderPayload, builderKzgCommitments, defaultBuilderBoostFactor))
_, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor)
require.NoError(t, err)
require.IsNil(t, bundle)
got, err := blk.Block().Body().BlobKzgCommitments()
require.NoError(t, err)
@@ -737,10 +821,12 @@ func TestServer_getPayloadHeader(t *testing.T) {
}}
hb, err := vs.HeadFetcher.HeadBlock(context.Background())
require.NoError(t, err)
h, _, err := vs.getPayloadHeaderFromBuilder(context.Background(), hb.Block().Slot(), 0)
bid, err := vs.getPayloadHeaderFromBuilder(context.Background(), hb.Block().Slot(), 0)
if tc.err != "" {
require.ErrorContains(t, tc.err, err)
} else {
require.NoError(t, err)
h, err := bid.Header()
require.NoError(t, err)
if tc.returnedHeader != nil {
want, err := blocks.WrappedExecutionPayloadHeader(tc.returnedHeader)
@@ -748,7 +834,7 @@ func TestServer_getPayloadHeader(t *testing.T) {
require.DeepEqual(t, want, h)
}
if tc.returnedHeaderCapella != nil {
want, err := blocks.WrappedExecutionPayloadHeaderCapella(tc.returnedHeaderCapella, big.NewInt(197121)) // value is a mock
want, err := blocks.WrappedExecutionPayloadHeaderCapella(tc.returnedHeaderCapella) // value is a mock
require.NoError(t, err)
require.DeepEqual(t, want, h)
}
@@ -805,7 +891,7 @@ func Test_matchingWithdrawalsRoot(t *testing.T) {
})
t.Run("could not get builder withdrawals root", func(t *testing.T) {
local := &v1.ExecutionPayloadCapella{}
p, err := blocks.WrappedExecutionPayloadCapella(local, big.NewInt(0))
p, err := blocks.WrappedExecutionPayloadCapella(local)
require.NoError(t, err)
header := &v1.ExecutionPayloadHeader{}
h, err := blocks.WrappedExecutionPayloadHeader(header)
@@ -815,10 +901,10 @@ func Test_matchingWithdrawalsRoot(t *testing.T) {
})
t.Run("withdrawals mismatch", func(t *testing.T) {
local := &v1.ExecutionPayloadCapella{}
p, err := blocks.WrappedExecutionPayloadCapella(local, big.NewInt(0))
p, err := blocks.WrappedExecutionPayloadCapella(local)
require.NoError(t, err)
header := &v1.ExecutionPayloadHeaderCapella{}
h, err := blocks.WrappedExecutionPayloadHeaderCapella(header, big.NewInt(0))
h, err := blocks.WrappedExecutionPayloadHeaderCapella(header)
require.NoError(t, err)
matched, err := matchingWithdrawalsRoot(p, h)
require.NoError(t, err)
@@ -832,13 +918,13 @@ func Test_matchingWithdrawalsRoot(t *testing.T) {
Amount: 3,
}}
local := &v1.ExecutionPayloadCapella{Withdrawals: wds}
p, err := blocks.WrappedExecutionPayloadCapella(local, big.NewInt(0))
p, err := blocks.WrappedExecutionPayloadCapella(local)
require.NoError(t, err)
header := &v1.ExecutionPayloadHeaderCapella{}
wr, err := ssz.WithdrawalSliceRoot(wds, fieldparams.MaxWithdrawalsPerPayload)
require.NoError(t, err)
header.WithdrawalsRoot = wr[:]
h, err := blocks.WrappedExecutionPayloadHeaderCapella(header, big.NewInt(0))
h, err := blocks.WrappedExecutionPayloadHeaderCapella(header)
require.NoError(t, err)
matched, err := matchingWithdrawalsRoot(p, h)
require.NoError(t, err)

View File

@@ -8,6 +8,7 @@ import (
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prysmaticlabs/prysm/v5/api/client/builder"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
@@ -47,12 +48,12 @@ func setFeeRecipientIfBurnAddress(val *cache.TrackedValidator) {
}
// This returns the local execution payload of a given slot. The function has full awareness of pre and post merge.
func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBeaconBlock, st state.BeaconState) (interfaces.ExecutionData, bool, error) {
func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBeaconBlock, st state.BeaconState) (*consensusblocks.GetPayloadResponse, error) {
ctx, span := trace.StartSpan(ctx, "ProposerServer.getLocalPayload")
defer span.End()
if blk.Version() < version.Bellatrix {
return nil, false, nil
return nil, nil
}
slot := blk.Slot()
@@ -77,34 +78,31 @@ func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBe
var pid primitives.PayloadID
copy(pid[:], payloadId[:])
payloadIDCacheHit.Inc()
payload, bundle, overrideBuilder, err := vs.ExecutionEngineCaller.GetPayload(ctx, pid, slot)
switch {
case err == nil:
bundleCache.add(slot, bundle)
warnIfFeeRecipientDiffers(payload, val.FeeRecipient)
return payload, overrideBuilder, nil
case errors.Is(err, context.DeadlineExceeded):
default:
return nil, false, errors.Wrap(err, "could not get cached payload from execution client")
res, err := vs.ExecutionEngineCaller.GetPayload(ctx, pid, slot)
if err == nil {
warnIfFeeRecipientDiffers(val.FeeRecipient[:], res.ExecutionData.FeeRecipient())
return res, nil
}
// TODO: TestServer_getExecutionPayloadContextTimeout expects this behavior.
// We need to figure out if it is actually important to "retry" by falling through to the code below when
// we get a timeout when trying to retrieve the cached payload id.
if !errors.Is(err, context.DeadlineExceeded) {
return nil, errors.Wrap(err, "could not get cached payload from execution client")
}
}
log.WithFields(logFields).Debug("payload ID cache miss")
parentHash, err := vs.getParentBlockHash(ctx, st, slot)
switch {
case errors.Is(err, errActivationNotReached) || errors.Is(err, errNoTerminalBlockHash):
p, err := consensusblocks.WrappedExecutionPayload(emptyPayload())
if err != nil {
return nil, false, err
}
return p, false, nil
return consensusblocks.NewGetPayloadResponse(emptyPayload())
case err != nil:
return nil, false, err
return nil, err
}
payloadIDCacheMiss.Inc()
random, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
if err != nil {
return nil, false, err
return nil, err
}
finalizedBlockHash := [32]byte{}
@@ -123,14 +121,14 @@ func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBe
t, err := slots.ToTime(st.GenesisTime(), slot)
if err != nil {
return nil, false, err
return nil, err
}
var attr payloadattribute.Attributer
switch st.Version() {
case version.Deneb, version.Electra:
withdrawals, _, err := st.ExpectedWithdrawals()
if err != nil {
return nil, false, err
return nil, err
}
attr, err = payloadattribute.New(&enginev1.PayloadAttributesV3{
Timestamp: uint64(t.Unix()),
@@ -140,12 +138,12 @@ func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBe
ParentBeaconBlockRoot: headRoot[:],
})
if err != nil {
return nil, false, err
return nil, err
}
case version.Capella:
withdrawals, _, err := st.ExpectedWithdrawals()
if err != nil {
return nil, false, err
return nil, err
}
attr, err = payloadattribute.New(&enginev1.PayloadAttributesV2{
Timestamp: uint64(t.Unix()),
@@ -154,7 +152,7 @@ func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBe
Withdrawals: withdrawals,
})
if err != nil {
return nil, false, err
return nil, err
}
case version.Bellatrix:
attr, err = payloadattribute.New(&enginev1.PayloadAttributes{
@@ -163,39 +161,35 @@ func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBe
SuggestedFeeRecipient: val.FeeRecipient[:],
})
if err != nil {
return nil, false, err
return nil, err
}
default:
return nil, false, errors.New("unknown beacon state version")
return nil, errors.New("unknown beacon state version")
}
payloadID, _, err := vs.ExecutionEngineCaller.ForkchoiceUpdated(ctx, f, attr)
if err != nil {
return nil, false, errors.Wrap(err, "could not prepare payload")
return nil, errors.Wrap(err, "could not prepare payload")
}
if payloadID == nil {
return nil, false, fmt.Errorf("nil payload with block hash: %#x", parentHash)
return nil, fmt.Errorf("nil payload with block hash: %#x", parentHash)
}
payload, bundle, overrideBuilder, err := vs.ExecutionEngineCaller.GetPayload(ctx, *payloadID, slot)
res, err := vs.ExecutionEngineCaller.GetPayload(ctx, *payloadID, slot)
if err != nil {
return nil, false, err
return nil, err
}
bundleCache.add(slot, bundle)
warnIfFeeRecipientDiffers(payload, val.FeeRecipient)
localValueGwei, err := payload.ValueInGwei()
if err == nil {
log.WithField("value", localValueGwei).Debug("received execution payload from local engine")
}
return payload, overrideBuilder, nil
warnIfFeeRecipientDiffers(val.FeeRecipient[:], res.ExecutionData.FeeRecipient())
log.WithField("value", res.Bid).Debug("received execution payload from local engine")
return res, nil
}
// warnIfFeeRecipientDiffers logs a warning if the fee recipient in the included payload does not
// match the requested one.
func warnIfFeeRecipientDiffers(payload interfaces.ExecutionData, feeRecipient primitives.ExecutionAddress) {
// Warn if the fee recipient is not the value we expect.
if payload != nil && !bytes.Equal(payload.FeeRecipient(), feeRecipient[:]) {
// warnIfFeeRecipientDiffers logs a warning if the fee recipient in the payload (eg the EL engine get payload response) does not
// match what was expected (eg the fee recipient previously used to request preparation of the payload).
func warnIfFeeRecipientDiffers(want, got []byte) {
if !bytes.Equal(want, got) {
logrus.WithFields(logrus.Fields{
"wantedFeeRecipient": fmt.Sprintf("%#x", feeRecipient),
"received": fmt.Sprintf("%#x", payload.FeeRecipient()),
"wantedFeeRecipient": fmt.Sprintf("%#x", want),
"received": fmt.Sprintf("%#x", got),
}).Warn("Fee recipient address from execution client is not what was expected. " +
"It is possible someone has compromised your client to try and take your transaction fees")
}
@@ -234,20 +228,20 @@ func (vs *Server) getTerminalBlockHashIfExists(ctx context.Context, transitionTi
func (vs *Server) getBuilderPayloadAndBlobs(ctx context.Context,
slot primitives.Slot,
vIdx primitives.ValidatorIndex) (interfaces.ExecutionData, [][]byte, error) {
vIdx primitives.ValidatorIndex) (builder.Bid, error) {
ctx, span := trace.StartSpan(ctx, "ProposerServer.getBuilderPayloadAndBlobs")
defer span.End()
if slots.ToEpoch(slot) < params.BeaconConfig().BellatrixForkEpoch {
return nil, nil, nil
return nil, nil
}
canUseBuilder, err := vs.canUseBuilder(ctx, slot, vIdx)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to check if we can use the builder")
return nil, errors.Wrap(err, "failed to check if we can use the builder")
}
span.AddAttributes(trace.BoolAttribute("canUseBuilder", canUseBuilder))
if !canUseBuilder {
return nil, nil, nil
return nil, nil
}
return vs.getPayloadHeaderFromBuilder(ctx, slot, vIdx)

View File

@@ -3,7 +3,6 @@ package validator
import (
"context"
"errors"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -61,7 +60,7 @@ func TestServer_getExecutionPayload(t *testing.T) {
}))
capellaTransitionState, _ := util.DeterministicGenesisStateCapella(t, 1)
wrappedHeaderCapella, err := blocks.WrappedExecutionPayloadHeaderCapella(&pb.ExecutionPayloadHeaderCapella{BlockNumber: 1}, big.NewInt(0))
wrappedHeaderCapella, err := blocks.WrappedExecutionPayloadHeaderCapella(&pb.ExecutionPayloadHeaderCapella{BlockNumber: 1})
require.NoError(t, err)
require.NoError(t, capellaTransitionState.SetLatestExecutionPayloadHeader(wrappedHeaderCapella))
b2pbCapella := util.NewBeaconBlockCapella()
@@ -146,8 +145,10 @@ func TestServer_getExecutionPayload(t *testing.T) {
cfg.TerminalBlockHashActivationEpoch = tt.activationEpoch
params.OverrideBeaconConfig(cfg)
ed, err := blocks.NewWrappedExecutionData(&pb.ExecutionPayload{})
require.NoError(t, err)
vs := &Server{
ExecutionEngineCaller: &powtesting.EngineClient{PayloadIDBytes: tt.payloadID, ErrForkchoiceUpdated: tt.forkchoiceErr, ExecutionPayload: &pb.ExecutionPayload{}, BuilderOverride: tt.override},
ExecutionEngineCaller: &powtesting.EngineClient{PayloadIDBytes: tt.payloadID, ErrForkchoiceUpdated: tt.forkchoiceErr, GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed, OverrideBuilder: tt.override}},
HeadFetcher: &chainMock.ChainService{State: tt.st},
FinalizationFetcher: &chainMock.ChainService{},
BeaconDB: beaconDB,
@@ -164,12 +165,11 @@ func TestServer_getExecutionPayload(t *testing.T) {
blk.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
b, err := blocks.NewSignedBeaconBlock(blk)
require.NoError(t, err)
var gotOverride bool
_, gotOverride, err = vs.getLocalPayload(context.Background(), b.Block(), tt.st)
res, err := vs.getLocalPayload(context.Background(), b.Block(), tt.st)
if tt.errString != "" {
require.ErrorContains(t, tt.errString, err)
} else {
require.Equal(t, tt.wantedOverride, gotOverride)
require.Equal(t, tt.wantedOverride, res.OverrideBuilder)
require.NoError(t, err)
}
})
@@ -194,8 +194,10 @@ func TestServer_getExecutionPayloadContextTimeout(t *testing.T) {
cfg.TerminalBlockHashActivationEpoch = 1
params.OverrideBeaconConfig(cfg)
ed, err := blocks.NewWrappedExecutionData(&pb.ExecutionPayload{})
require.NoError(t, err)
vs := &Server{
ExecutionEngineCaller: &powtesting.EngineClient{PayloadIDBytes: &pb.PayloadIDBytes{}, ErrGetPayload: context.DeadlineExceeded, ExecutionPayload: &pb.ExecutionPayload{}},
ExecutionEngineCaller: &powtesting.EngineClient{PayloadIDBytes: &pb.PayloadIDBytes{}, ErrGetPayload: context.DeadlineExceeded, GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed}},
HeadFetcher: &chainMock.ChainService{State: nonTransitionSt},
BeaconDB: beaconDB,
PayloadIDCache: cache.NewPayloadIDCache(),
@@ -209,7 +211,7 @@ func TestServer_getExecutionPayloadContextTimeout(t *testing.T) {
blk.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
b, err := blocks.NewSignedBeaconBlock(blk)
require.NoError(t, err)
_, _, err = vs.getLocalPayload(context.Background(), b.Block(), nonTransitionSt)
_, err = vs.getLocalPayload(context.Background(), b.Block(), nonTransitionSt)
require.NoError(t, err)
}
@@ -241,10 +243,12 @@ func TestServer_getExecutionPayload_UnexpectedFeeRecipient(t *testing.T) {
payloadID := &pb.PayloadIDBytes{0x1}
payload := emptyPayload()
payload.FeeRecipient = feeRecipient[:]
ed, err := blocks.NewWrappedExecutionData(payload)
require.NoError(t, err)
vs := &Server{
ExecutionEngineCaller: &powtesting.EngineClient{
PayloadIDBytes: payloadID,
ExecutionPayload: payload,
PayloadIDBytes: payloadID,
GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed},
},
HeadFetcher: &chainMock.ChainService{State: transitionSt},
FinalizationFetcher: &chainMock.ChainService{},
@@ -264,10 +268,10 @@ func TestServer_getExecutionPayload_UnexpectedFeeRecipient(t *testing.T) {
blk.Block.ParentRoot = bytesutil.PadTo([]byte{}, 32)
b, err := blocks.NewSignedBeaconBlock(blk)
require.NoError(t, err)
gotPayload, _, err := vs.getLocalPayload(context.Background(), b.Block(), transitionSt)
res, err := vs.getLocalPayload(context.Background(), b.Block(), transitionSt)
require.NoError(t, err)
require.NotNil(t, gotPayload)
require.Equal(t, common.Address(gotPayload.FeeRecipient()), feeRecipient)
require.NotNil(t, res)
require.Equal(t, common.Address(res.ExecutionData.FeeRecipient()), feeRecipient)
// We should NOT be getting the warning.
require.LogsDoNotContain(t, hook, "Fee recipient address from execution client is not what was expected")
@@ -277,9 +281,9 @@ func TestServer_getExecutionPayload_UnexpectedFeeRecipient(t *testing.T) {
payload.FeeRecipient = evilRecipientAddress[:]
vs.PayloadIDCache = cache.NewPayloadIDCache()
gotPayload, _, err = vs.getLocalPayload(context.Background(), b.Block(), transitionSt)
res, err = vs.getLocalPayload(context.Background(), b.Block(), transitionSt)
require.NoError(t, err)
require.NotNil(t, gotPayload)
require.NotNil(t, res)
// Users should be warned.
require.LogsContain(t, hook, "Fee recipient address from execution client is not what was expected")

View File

@@ -277,9 +277,11 @@ func TestServer_GetBeaconBlock_Bellatrix(t *testing.T) {
proposerServer := getProposerServer(db, beaconState, parentRoot[:])
proposerServer.Eth1BlockFetcher = c
ed, err := blocks.NewWrappedExecutionData(payload)
require.NoError(t, err)
proposerServer.ExecutionEngineCaller = &mockExecution.EngineClient{
PayloadIDBytes: &enginev1.PayloadIDBytes{1},
ExecutionPayload: payload,
PayloadIDBytes: &enginev1.PayloadIDBytes{1},
GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed},
}
randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys)
@@ -400,9 +402,11 @@ func TestServer_GetBeaconBlock_Capella(t *testing.T) {
}
proposerServer := getProposerServer(db, beaconState, parentRoot[:])
ed, err := blocks.NewWrappedExecutionData(payload)
require.NoError(t, err)
proposerServer.ExecutionEngineCaller = &mockExecution.EngineClient{
PayloadIDBytes: &enginev1.PayloadIDBytes{1},
ExecutionPayloadCapella: payload,
PayloadIDBytes: &enginev1.PayloadIDBytes{1},
GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed},
}
randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys)
@@ -510,6 +514,8 @@ func TestServer_GetBeaconBlock_Deneb(t *testing.T) {
BlobGasUsed: 4,
ExcessBlobGas: 5,
}
ed, err := blocks.NewWrappedExecutionData(payload)
require.NoError(t, err)
kc := make([][]byte, 0)
kc = append(kc, bytesutil.PadTo([]byte("kc"), 48))
@@ -520,9 +526,11 @@ func TestServer_GetBeaconBlock_Deneb(t *testing.T) {
bundle := &enginev1.BlobsBundle{KzgCommitments: kc, Proofs: proofs, Blobs: blobs}
proposerServer := getProposerServer(db, beaconState, parentRoot[:])
proposerServer.ExecutionEngineCaller = &mockExecution.EngineClient{
PayloadIDBytes: &enginev1.PayloadIDBytes{1},
ExecutionPayloadDeneb: payload,
BlobsBundle: bundle,
PayloadIDBytes: &enginev1.PayloadIDBytes{1},
GetPayloadResponse: &blocks.GetPayloadResponse{
ExecutionData: ed,
BlobsBundle: bundle,
},
}
randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys)
@@ -651,9 +659,11 @@ func TestServer_GetBeaconBlock_Electra(t *testing.T) {
}
proposerServer := getProposerServer(db, beaconState, parentRoot[:])
ed, err := blocks.NewWrappedExecutionData(payload)
require.NoError(t, err)
proposerServer.ExecutionEngineCaller = &mockExecution.EngineClient{
PayloadIDBytes: &enginev1.PayloadIDBytes{1},
ExecutionPayloadElectra: payload,
PayloadIDBytes: &enginev1.PayloadIDBytes{1},
GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed},
}
randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys)

View File

@@ -2,7 +2,6 @@ package state_native
import (
"fmt"
"math/big"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
@@ -24,11 +23,11 @@ func (b *BeaconState) LatestExecutionPayloadHeader() (interfaces.ExecutionData,
case version.Bellatrix:
return blocks.WrappedExecutionPayloadHeader(b.latestExecutionPayloadHeaderVal())
case version.Capella:
return blocks.WrappedExecutionPayloadHeaderCapella(b.latestExecutionPayloadHeaderCapellaVal(), big.NewInt(0))
return blocks.WrappedExecutionPayloadHeaderCapella(b.latestExecutionPayloadHeaderCapellaVal())
case version.Deneb:
return blocks.WrappedExecutionPayloadHeaderDeneb(b.latestExecutionPayloadHeaderDenebVal(), big.NewInt(0))
return blocks.WrappedExecutionPayloadHeaderDeneb(b.latestExecutionPayloadHeaderDenebVal())
case version.Electra:
return blocks.WrappedExecutionPayloadHeaderElectra(b.latestExecutionPayloadHeaderElectraVal(), big.NewInt(0))
return blocks.WrappedExecutionPayloadHeaderElectra(b.latestExecutionPayloadHeaderElectraVal())
default:
return nil, fmt.Errorf("unsupported version (%s) for latest execution payload header", version.String(b.version))
}

View File

@@ -2,7 +2,6 @@ package state_native_test
import (
"context"
"math/big"
"testing"
"github.com/prysmaticlabs/go-bitfield"
@@ -254,7 +253,7 @@ func TestComputeFieldRootsWithHasher_Capella(t *testing.T) {
require.NoError(t, beaconState.SetInactivityScores([]uint64{1, 2, 3}))
require.NoError(t, beaconState.SetCurrentSyncCommittee(syncCommittee("current")))
require.NoError(t, beaconState.SetNextSyncCommittee(syncCommittee("next")))
wrappedHeader, err := blocks.WrappedExecutionPayloadHeaderCapella(executionPayloadHeaderCapella(), big.NewInt(0))
wrappedHeader, err := blocks.WrappedExecutionPayloadHeaderCapella(executionPayloadHeaderCapella())
require.NoError(t, err)
require.NoError(t, beaconState.SetLatestExecutionPayloadHeader(wrappedHeader))
require.NoError(t, beaconState.SetNextWithdrawalIndex(123))

View File

@@ -23,19 +23,19 @@ func TestSetLatestExecutionPayloadHeader(t *testing.T) {
}(),
func() interfaces.ExecutionData {
e := util.NewBeaconBlockCapella().Block.Body.ExecutionPayload
ee, err := blocks.WrappedExecutionPayloadCapella(e, nil)
ee, err := blocks.WrappedExecutionPayloadCapella(e)
require.NoError(t, err)
return ee
}(),
func() interfaces.ExecutionData {
e := util.NewBeaconBlockDeneb().Block.Body.ExecutionPayload
ee, err := blocks.WrappedExecutionPayloadDeneb(e, nil)
ee, err := blocks.WrappedExecutionPayloadDeneb(e)
require.NoError(t, err)
return ee
}(),
func() interfaces.ExecutionData {
e := util.NewBeaconBlockElectra().Block.Body.ExecutionPayload
ee, err := blocks.WrappedExecutionPayloadElectra(e, nil)
ee, err := blocks.WrappedExecutionPayloadElectra(e)
require.NoError(t, err)
return ee
}(),
@@ -50,19 +50,19 @@ func TestSetLatestExecutionPayloadHeader(t *testing.T) {
}(),
func() interfaces.ExecutionData {
e := util.NewBlindedBeaconBlockCapella().Block.Body.ExecutionPayloadHeader
ee, err := blocks.WrappedExecutionPayloadHeaderCapella(e, nil)
ee, err := blocks.WrappedExecutionPayloadHeaderCapella(e)
require.NoError(t, err)
return ee
}(),
func() interfaces.ExecutionData {
e := util.NewBlindedBeaconBlockDeneb().Message.Body.ExecutionPayloadHeader
ee, err := blocks.WrappedExecutionPayloadHeaderDeneb(e, nil)
ee, err := blocks.WrappedExecutionPayloadHeaderDeneb(e)
require.NoError(t, err)
return ee
}(),
func() interfaces.ExecutionData {
e := util.NewBlindedBeaconBlockElectra().Message.Body.ExecutionPayloadHeader
ee, err := blocks.WrappedExecutionPayloadHeaderElectra(e, nil)
ee, err := blocks.WrappedExecutionPayloadHeaderElectra(e)
require.NoError(t, err)
return ee
}(),

View File

@@ -5,6 +5,7 @@ go_library(
srcs = [
"execution.go",
"factory.go",
"get_payload.go",
"getters.go",
"kzg.go",
"proto.go",
@@ -31,7 +32,6 @@ go_library(
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_fastssz//:go_default_library",
"@com_github_prysmaticlabs_gohashtree//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
],
)

View File

@@ -3,13 +3,11 @@ package blocks
import (
"bytes"
"errors"
"math/big"
fastssz "github.com/prysmaticlabs/fastssz"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
@@ -24,19 +22,25 @@ type executionPayload struct {
}
// NewWrappedExecutionData creates an appropriate execution payload wrapper based on the incoming type.
func NewWrappedExecutionData(v proto.Message, weiValue primitives.Wei) (interfaces.ExecutionData, error) {
if weiValue == nil {
weiValue = new(big.Int).SetInt64(0)
func NewWrappedExecutionData(v proto.Message) (interfaces.ExecutionData, error) {
if v == nil {
return nil, consensus_types.ErrNilObjectWrapped
}
switch pbStruct := v.(type) {
case *enginev1.ExecutionPayload:
return WrappedExecutionPayload(pbStruct)
case *enginev1.ExecutionPayloadCapella:
return WrappedExecutionPayloadCapella(pbStruct, weiValue)
return WrappedExecutionPayloadCapella(pbStruct)
case *enginev1.ExecutionPayloadCapellaWithValue:
return WrappedExecutionPayloadCapella(pbStruct.Payload)
case *enginev1.ExecutionPayloadDeneb:
return WrappedExecutionPayloadDeneb(pbStruct, weiValue)
return WrappedExecutionPayloadDeneb(pbStruct)
case *enginev1.ExecutionPayloadDenebWithValueAndBlobsBundle:
return WrappedExecutionPayloadDeneb(pbStruct.Payload)
case *enginev1.ExecutionPayloadElectra:
return WrappedExecutionPayloadElectra(pbStruct, weiValue)
return WrappedExecutionPayloadElectra(pbStruct)
case *enginev1.ExecutionPayloadElectraWithValueAndBlobsBundle:
return WrappedExecutionPayloadElectra(pbStruct.Payload)
default:
return nil, ErrUnsupportedVersion
}
@@ -193,16 +197,6 @@ func (e executionPayload) ExcessBlobGas() (uint64, error) {
return 0, consensus_types.ErrUnsupportedField
}
// ValueInWei --
func (executionPayload) ValueInWei() (primitives.Wei, error) {
return nil, consensus_types.ErrUnsupportedField
}
// ValueInGwei --
func (executionPayload) ValueInGwei() (uint64, error) {
return 0, consensus_types.ErrUnsupportedField
}
// executionPayloadHeader is a convenience wrapper around a blinded beacon block body's execution header data structure
// This wrapper allows us to conform to a common interface so that beacon
// blocks for future forks can also be applied across Prysm without issues.
@@ -361,16 +355,6 @@ func (e executionPayloadHeader) ExcessBlobGas() (uint64, error) {
return 0, consensus_types.ErrUnsupportedField
}
// ValueInWei --
func (executionPayloadHeader) ValueInWei() (primitives.Wei, error) {
return nil, consensus_types.ErrUnsupportedField
}
// ValueInGwei --
func (executionPayloadHeader) ValueInGwei() (uint64, error) {
return 0, consensus_types.ErrUnsupportedField
}
// PayloadToHeader converts `payload` into execution payload header format.
func PayloadToHeader(payload interfaces.ExecutionData) (*enginev1.ExecutionPayloadHeader, error) {
txs, err := payload.Transactions()
@@ -403,16 +387,14 @@ func PayloadToHeader(payload interfaces.ExecutionData) (*enginev1.ExecutionPaylo
// This wrapper allows us to conform to a common interface so that beacon
// blocks for future forks can also be applied across Prysm without issues.
type executionPayloadCapella struct {
p *enginev1.ExecutionPayloadCapella
weiValue primitives.Wei
gweiValue uint64
p *enginev1.ExecutionPayloadCapella
}
var _ interfaces.ExecutionData = &executionPayloadCapella{}
// WrappedExecutionPayloadCapella is a constructor which wraps a protobuf execution payload into an interface.
func WrappedExecutionPayloadCapella(p *enginev1.ExecutionPayloadCapella, value primitives.Wei) (interfaces.ExecutionData, error) {
w := executionPayloadCapella{p: p, weiValue: value, gweiValue: uint64(primitives.WeiToGwei(value))}
func WrappedExecutionPayloadCapella(p *enginev1.ExecutionPayloadCapella) (interfaces.ExecutionData, error) {
w := executionPayloadCapella{p: p}
if w.IsNil() {
return nil, consensus_types.ErrNilObjectWrapped
}
@@ -559,30 +541,18 @@ func (e executionPayloadCapella) ExcessBlobGas() (uint64, error) {
return 0, consensus_types.ErrUnsupportedField
}
// ValueInWei --
func (e executionPayloadCapella) ValueInWei() (primitives.Wei, error) {
return e.weiValue, nil
}
// ValueInGwei --
func (e executionPayloadCapella) ValueInGwei() (uint64, error) {
return e.gweiValue, nil
}
// executionPayloadHeaderCapella is a convenience wrapper around a blinded beacon block body's execution header data structure
// This wrapper allows us to conform to a common interface so that beacon
// blocks for future forks can also be applied across Prysm without issues.
type executionPayloadHeaderCapella struct {
p *enginev1.ExecutionPayloadHeaderCapella
weiValue primitives.Wei
gweiValue uint64
p *enginev1.ExecutionPayloadHeaderCapella
}
var _ interfaces.ExecutionData = &executionPayloadHeaderCapella{}
// WrappedExecutionPayloadHeaderCapella is a constructor which wraps a protobuf execution header into an interface.
func WrappedExecutionPayloadHeaderCapella(p *enginev1.ExecutionPayloadHeaderCapella, value primitives.Wei) (interfaces.ExecutionData, error) {
w := executionPayloadHeaderCapella{p: p, weiValue: value, gweiValue: uint64(primitives.WeiToGwei(value))}
func WrappedExecutionPayloadHeaderCapella(p *enginev1.ExecutionPayloadHeaderCapella) (interfaces.ExecutionData, error) {
w := executionPayloadHeaderCapella{p: p}
if w.IsNil() {
return nil, consensus_types.ErrNilObjectWrapped
}
@@ -729,16 +699,6 @@ func (e executionPayloadHeaderCapella) ExcessBlobGas() (uint64, error) {
return 0, consensus_types.ErrUnsupportedField
}
// ValueInWei --
func (e executionPayloadHeaderCapella) ValueInWei() (primitives.Wei, error) {
return e.weiValue, nil
}
// ValueInGwei --
func (e executionPayloadHeaderCapella) ValueInGwei() (uint64, error) {
return e.gweiValue, nil
}
// PayloadToHeaderCapella converts `payload` into execution payload header format.
func PayloadToHeaderCapella(payload interfaces.ExecutionData) (*enginev1.ExecutionPayloadHeaderCapella, error) {
txs, err := payload.Transactions()
@@ -965,16 +925,14 @@ func IsEmptyExecutionData(data interfaces.ExecutionData) (bool, error) {
// This wrapper allows us to conform to a common interface so that beacon
// blocks for future forks can also be applied across Prysm without issues.
type executionPayloadHeaderDeneb struct {
p *enginev1.ExecutionPayloadHeaderDeneb
weiValue primitives.Wei
gweiValue uint64
p *enginev1.ExecutionPayloadHeaderDeneb
}
var _ interfaces.ExecutionData = &executionPayloadHeaderDeneb{}
// WrappedExecutionPayloadHeaderDeneb is a constructor which wraps a protobuf execution header into an interface.
func WrappedExecutionPayloadHeaderDeneb(p *enginev1.ExecutionPayloadHeaderDeneb, value primitives.Wei) (interfaces.ExecutionData, error) {
w := executionPayloadHeaderDeneb{p: p, weiValue: value, gweiValue: uint64(primitives.WeiToGwei(value))}
func WrappedExecutionPayloadHeaderDeneb(p *enginev1.ExecutionPayloadHeaderDeneb) (interfaces.ExecutionData, error) {
w := executionPayloadHeaderDeneb{p: p}
if w.IsNil() {
return nil, consensus_types.ErrNilObjectWrapped
}
@@ -1116,16 +1074,6 @@ func (e executionPayloadHeaderDeneb) ExcessBlobGas() (uint64, error) {
return e.p.ExcessBlobGas, nil
}
// ValueInWei --
func (e executionPayloadHeaderDeneb) ValueInWei() (primitives.Wei, error) {
return e.weiValue, nil
}
// ValueInGwei --
func (e executionPayloadHeaderDeneb) ValueInGwei() (uint64, error) {
return e.gweiValue, nil
}
// IsBlinded returns true if the underlying data is blinded.
func (e executionPayloadHeaderDeneb) IsBlinded() bool {
return true
@@ -1135,16 +1083,14 @@ func (e executionPayloadHeaderDeneb) IsBlinded() bool {
// This wrapper allows us to conform to a common interface so that beacon
// blocks for future forks can also be applied across Prysm without issues.
type executionPayloadDeneb struct {
p *enginev1.ExecutionPayloadDeneb
weiValue primitives.Wei
gweiValue uint64
p *enginev1.ExecutionPayloadDeneb
}
var _ interfaces.ExecutionData = &executionPayloadDeneb{}
// WrappedExecutionPayloadDeneb is a constructor which wraps a protobuf execution payload into an interface.
func WrappedExecutionPayloadDeneb(p *enginev1.ExecutionPayloadDeneb, value primitives.Wei) (interfaces.ExecutionData, error) {
w := executionPayloadDeneb{p: p, weiValue: value, gweiValue: uint64(primitives.WeiToGwei(value))}
func WrappedExecutionPayloadDeneb(p *enginev1.ExecutionPayloadDeneb) (interfaces.ExecutionData, error) {
w := executionPayloadDeneb{p: p}
if w.IsNil() {
return nil, consensus_types.ErrNilObjectWrapped
}
@@ -1284,16 +1230,6 @@ func (e executionPayloadDeneb) ExcessBlobGas() (uint64, error) {
return e.p.ExcessBlobGas, nil
}
// ValueInWei --
func (e executionPayloadDeneb) ValueInWei() (primitives.Wei, error) {
return e.weiValue, nil
}
// ValueInGwei --
func (e executionPayloadDeneb) ValueInGwei() (uint64, error) {
return e.gweiValue, nil
}
// IsBlinded returns true if the underlying data is blinded.
func (e executionPayloadDeneb) IsBlinded() bool {
return false
@@ -1303,17 +1239,15 @@ func (e executionPayloadDeneb) IsBlinded() bool {
// This wrapper allows us to conform to a common interface so that beacon
// blocks for future forks can also be applied across Prysm without issues.
type executionPayloadHeaderElectra struct {
p *enginev1.ExecutionPayloadHeaderElectra
weiValue primitives.Wei
gweiValue uint64
p *enginev1.ExecutionPayloadHeaderElectra
}
var _ interfaces.ExecutionData = &executionPayloadElectra{}
var _ interfaces.ExecutionDataElectra = &executionPayloadElectra{}
// WrappedExecutionPayloadHeaderElectra is a constructor which wraps a protobuf execution header into an interface.
func WrappedExecutionPayloadHeaderElectra(p *enginev1.ExecutionPayloadHeaderElectra, value primitives.Wei) (interfaces.ExecutionData, error) {
w := executionPayloadHeaderElectra{p: p, weiValue: value, gweiValue: uint64(primitives.WeiToGwei(value))}
func WrappedExecutionPayloadHeaderElectra(p *enginev1.ExecutionPayloadHeaderElectra) (interfaces.ExecutionData, error) {
w := executionPayloadHeaderElectra{p: p}
if w.IsNil() {
return nil, consensus_types.ErrNilObjectWrapped
}
@@ -1455,16 +1389,6 @@ func (e executionPayloadHeaderElectra) ExcessBlobGas() (uint64, error) {
return e.p.ExcessBlobGas, nil
}
// ValueInWei --
func (e executionPayloadHeaderElectra) ValueInWei() (primitives.Wei, error) {
return e.weiValue, nil
}
// ValueInGwei --
func (e executionPayloadHeaderElectra) ValueInGwei() (uint64, error) {
return e.gweiValue, nil
}
// DepositReceipts --
func (e executionPayloadHeaderElectra) DepositReceipts() ([]*enginev1.DepositReceipt, error) {
return nil, consensus_types.ErrUnsupportedField
@@ -1484,14 +1408,12 @@ func (e executionPayloadHeaderElectra) IsBlinded() bool {
// This wrapper allows us to conform to a common interface so that beacon
// blocks for future forks can also be applied across Prysm without issues.
type executionPayloadElectra struct {
p *enginev1.ExecutionPayloadElectra
weiValue primitives.Wei
gweiValue uint64
p *enginev1.ExecutionPayloadElectra
}
// WrappedExecutionPayloadElectra is a constructor which wraps a protobuf execution payload into an interface.
func WrappedExecutionPayloadElectra(p *enginev1.ExecutionPayloadElectra, value primitives.Wei) (interfaces.ExecutionData, error) {
w := executionPayloadElectra{p: p, weiValue: value, gweiValue: uint64(primitives.WeiToGwei(value))}
func WrappedExecutionPayloadElectra(p *enginev1.ExecutionPayloadElectra) (interfaces.ExecutionData, error) {
w := executionPayloadElectra{p: p}
if w.IsNil() {
return nil, consensus_types.ErrNilObjectWrapped
}
@@ -1634,16 +1556,6 @@ func (e executionPayloadElectra) ExcessBlobGas() (uint64, error) {
return e.p.ExcessBlobGas, nil
}
// ValueInWei --
func (e executionPayloadElectra) ValueInWei() (primitives.Wei, error) {
return e.weiValue, nil
}
// ValueInGwei --
func (e executionPayloadElectra) ValueInGwei() (uint64, error) {
return e.gweiValue, nil
}
// DepositReceipts --
func (e executionPayloadElectra) DepositReceipts() []*enginev1.DepositReceipt {
return e.p.DepositReceipts
@@ -1658,16 +1570,3 @@ func (e executionPayloadElectra) WithdrawalRequests() []*enginev1.ExecutionLayer
func (e executionPayloadElectra) IsBlinded() bool {
return false
}
// PayloadValueToWei returns a Wei value given the payload's value
func PayloadValueToWei(value []byte) primitives.Wei {
// We have to convert big endian to little endian because the value is coming from the execution layer.
return big.NewInt(0).SetBytes(bytesutil.ReverseByteOrder(value))
}
// PayloadValueToGwei returns a Gwei value given the payload's value
func PayloadValueToGwei(value []byte) primitives.Gwei {
// We have to convert big endian to little endian because the value is coming from the execution layer.
v := big.NewInt(0).SetBytes(bytesutil.ReverseByteOrder(value))
return primitives.WeiToGwei(v)
}

View File

@@ -1,7 +1,6 @@
package blocks_test
import (
"math/big"
"testing"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
@@ -106,14 +105,8 @@ func TestWrapExecutionPayloadCapella(t *testing.T) {
Amount: 77,
}},
}
payload, err := blocks.WrappedExecutionPayloadCapella(data, big.NewInt(10*1e9))
payload, err := blocks.WrappedExecutionPayloadCapella(data)
require.NoError(t, err)
wei, err := payload.ValueInWei()
require.NoError(t, err)
assert.Equal(t, 0, big.NewInt(10*1e9).Cmp(wei))
gwei, err := payload.ValueInGwei()
require.NoError(t, err)
assert.Equal(t, uint64(10), gwei)
assert.DeepEqual(t, data, payload.Proto())
}
@@ -136,16 +129,9 @@ func TestWrapExecutionPayloadHeaderCapella(t *testing.T) {
TransactionsRoot: []byte("transactionsroot"),
WithdrawalsRoot: []byte("withdrawalsroot"),
}
payload, err := blocks.WrappedExecutionPayloadHeaderCapella(data, big.NewInt(10*1e9))
payload, err := blocks.WrappedExecutionPayloadHeaderCapella(data)
require.NoError(t, err)
wei, err := payload.ValueInWei()
require.NoError(t, err)
assert.Equal(t, 0, big.NewInt(10*1e9).Cmp(wei))
gwei, err := payload.ValueInGwei()
require.NoError(t, err)
assert.Equal(t, uint64(10), gwei)
assert.DeepEqual(t, data, payload.Proto())
txRoot, err := payload.TransactionsRoot()
@@ -158,22 +144,22 @@ func TestWrapExecutionPayloadHeaderCapella(t *testing.T) {
}
func TestWrapExecutionPayloadCapella_IsNil(t *testing.T) {
_, err := blocks.WrappedExecutionPayloadCapella(nil, big.NewInt(0))
_, err := blocks.WrappedExecutionPayloadCapella(nil)
require.Equal(t, consensus_types.ErrNilObjectWrapped, err)
data := &enginev1.ExecutionPayloadCapella{GasUsed: 54}
payload, err := blocks.WrappedExecutionPayloadCapella(data, big.NewInt(0))
payload, err := blocks.WrappedExecutionPayloadCapella(data)
require.NoError(t, err)
assert.Equal(t, false, payload.IsNil())
}
func TestWrapExecutionPayloadHeaderCapella_IsNil(t *testing.T) {
_, err := blocks.WrappedExecutionPayloadHeaderCapella(nil, big.NewInt(0))
_, err := blocks.WrappedExecutionPayloadHeaderCapella(nil)
require.Equal(t, consensus_types.ErrNilObjectWrapped, err)
data := &enginev1.ExecutionPayloadHeaderCapella{GasUsed: 54}
payload, err := blocks.WrappedExecutionPayloadHeaderCapella(data, big.NewInt(0))
payload, err := blocks.WrappedExecutionPayloadHeaderCapella(data)
require.NoError(t, err)
assert.Equal(t, false, payload.IsNil())
@@ -236,14 +222,8 @@ func TestWrapExecutionPayloadDeneb(t *testing.T) {
BlobGasUsed: 88,
ExcessBlobGas: 99,
}
payload, err := blocks.WrappedExecutionPayloadDeneb(data, big.NewInt(420*1e9))
payload, err := blocks.WrappedExecutionPayloadDeneb(data)
require.NoError(t, err)
wei, err := payload.ValueInWei()
require.NoError(t, err)
assert.Equal(t, 0, big.NewInt(420*1e9).Cmp(wei))
gwei, err := payload.ValueInGwei()
require.NoError(t, err)
assert.Equal(t, uint64(420), gwei)
g, err := payload.BlobGasUsed()
require.NoError(t, err)
@@ -274,16 +254,9 @@ func TestWrapExecutionPayloadHeaderDeneb(t *testing.T) {
BlobGasUsed: 88,
ExcessBlobGas: 99,
}
payload, err := blocks.WrappedExecutionPayloadHeaderDeneb(data, big.NewInt(10*1e9))
payload, err := blocks.WrappedExecutionPayloadHeaderDeneb(data)
require.NoError(t, err)
wei, err := payload.ValueInWei()
require.NoError(t, err)
assert.Equal(t, 0, big.NewInt(10*1e9).Cmp(wei))
gwei, err := payload.ValueInGwei()
require.NoError(t, err)
assert.Equal(t, uint64(10), gwei)
g, err := payload.BlobGasUsed()
require.NoError(t, err)
require.DeepEqual(t, uint64(88), g)
@@ -384,7 +357,7 @@ func createWrappedPayloadCapella(t testing.TB) interfaces.ExecutionData {
BlockHash: make([]byte, fieldparams.RootLength),
Transactions: make([][]byte, 0),
Withdrawals: make([]*enginev1.Withdrawal, 0),
}, big.NewInt(0))
})
require.NoError(t, err)
return payload
}
@@ -406,7 +379,7 @@ func createWrappedPayloadHeaderCapella(t testing.TB) interfaces.ExecutionData {
BlockHash: make([]byte, fieldparams.RootLength),
TransactionsRoot: make([]byte, fieldparams.RootLength),
WithdrawalsRoot: make([]byte, fieldparams.RootLength),
}, big.NewInt(0))
})
require.NoError(t, err)
return payload
}
@@ -430,7 +403,7 @@ func createWrappedPayloadDeneb(t testing.TB) interfaces.ExecutionData {
Withdrawals: make([]*enginev1.Withdrawal, 0),
BlobGasUsed: 0,
ExcessBlobGas: 0,
}, big.NewInt(0))
})
require.NoError(t, err)
return payload
}
@@ -454,7 +427,7 @@ func createWrappedPayloadHeaderDeneb(t testing.TB) interfaces.ExecutionData {
WithdrawalsRoot: make([]byte, fieldparams.RootLength),
BlobGasUsed: 0,
ExcessBlobGas: 0,
}, big.NewInt(0))
})
require.NoError(t, err)
return payload
}

View File

@@ -2,7 +2,6 @@ package blocks
import (
"fmt"
"math/big"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
@@ -260,11 +259,11 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea
case *enginev1.ExecutionPayload:
wrappedPayload, wrapErr = WrappedExecutionPayload(p)
case *enginev1.ExecutionPayloadCapella:
wrappedPayload, wrapErr = WrappedExecutionPayloadCapella(p, big.NewInt(0))
wrappedPayload, wrapErr = WrappedExecutionPayloadCapella(p)
case *enginev1.ExecutionPayloadDeneb:
wrappedPayload, wrapErr = WrappedExecutionPayloadDeneb(p, big.NewInt(0))
wrappedPayload, wrapErr = WrappedExecutionPayloadDeneb(p)
case *enginev1.ExecutionPayloadElectra:
wrappedPayload, wrapErr = WrappedExecutionPayloadElectra(p, big.NewInt(0))
wrappedPayload, wrapErr = WrappedExecutionPayloadElectra(p)
default:
return nil, fmt.Errorf("%T is not a type of execution payload", p)
}

View File

@@ -3,7 +3,6 @@ package blocks
import (
"bytes"
"errors"
"math/big"
"testing"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
@@ -517,7 +516,7 @@ func TestBuildSignedBeaconBlockFromExecutionPayload(t *testing.T) {
ExcessBlobGas: 123,
BlobGasUsed: 321,
}
wrapped, err := WrappedExecutionPayloadDeneb(payload, big.NewInt(123))
wrapped, err := WrappedExecutionPayloadDeneb(payload)
require.NoError(t, err)
header, err := PayloadToHeaderDeneb(wrapped)
require.NoError(t, err)

View File

@@ -0,0 +1,60 @@
package blocks
import (
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
pb "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
"google.golang.org/protobuf/proto"
)
// GetPayloadResponse represents the result of unmarshaling an execution engine
// GetPayloadResponseV(1|2|3|4) value.
type GetPayloadResponse struct {
ExecutionData interfaces.ExecutionData
BlobsBundle *pb.BlobsBundle
OverrideBuilder bool
// todo: should we convert this to Gwei up front?
Bid primitives.Wei
}
// bundleGetter is an interface satisfied by get payload responses that have a blobs bundle.
type bundleGetter interface {
GetBlobsBundle() *pb.BlobsBundle
}
// bidValueGetter is an interface satisfied by get payload responses that have a bid value.
type bidValueGetter interface {
GetValue() []byte
}
type shouldOverrideBuilderGetter interface {
GetShouldOverrideBuilder() bool
}
func NewGetPayloadResponse(msg proto.Message) (*GetPayloadResponse, error) {
r := &GetPayloadResponse{}
bundleGetter, hasBundle := msg.(bundleGetter)
if hasBundle {
r.BlobsBundle = bundleGetter.GetBlobsBundle()
}
bidValueGetter, hasBid := msg.(bidValueGetter)
wei := primitives.ZeroWei
if hasBid {
// The protobuf types that engine api responses unmarshal into store their values in little endian form.
// This is done for consistency with other uint256 values stored in protobufs for SSZ values.
// Long term we should move away from protobuf types for these values and just keep the bid as a big.Int as soon
// as we unmarshal it from the engine api response.
wei = primitives.LittleEndianBytesToWei(bidValueGetter.GetValue())
}
r.Bid = wei
shouldOverride, hasShouldOverride := msg.(shouldOverrideBuilderGetter)
if hasShouldOverride {
r.OverrideBuilder = shouldOverride.GetShouldOverrideBuilder()
}
ed, err := NewWrappedExecutionData(msg)
if err != nil {
return nil, err
}
r.ExecutionData = ed
return r, nil
}

View File

@@ -2,7 +2,6 @@ package blocks
import (
"fmt"
"math/big"
"github.com/pkg/errors"
ssz "github.com/prysmaticlabs/fastssz"
@@ -14,7 +13,6 @@ import (
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
log "github.com/sirupsen/logrus"
)
// BeaconBlockIsNil checks if any composite field of input signed beacon block is nil.
@@ -327,44 +325,6 @@ func (b *SignedBeaconBlock) IsBlinded() bool {
return b.version >= version.Bellatrix && b.block.body.executionPayload == nil
}
// ValueInWei metadata on the payload value returned by the builder.
func (b *SignedBeaconBlock) ValueInWei() primitives.Wei {
exec, err := b.block.body.Execution()
if err != nil {
if !errors.Is(err, consensus_types.ErrUnsupportedField) {
log.WithError(err).Warn("failed to retrieve execution payload")
}
return big.NewInt(0)
}
val, err := exec.ValueInWei()
if err != nil {
if !errors.Is(err, consensus_types.ErrUnsupportedField) {
log.WithError(err).Warn("failed to retrieve execution payload")
}
return big.NewInt(0)
}
return val
}
// ValueInGwei metadata on the payload value returned by the builder.
func (b *SignedBeaconBlock) ValueInGwei() uint64 {
exec, err := b.block.body.Execution()
if err != nil {
if !errors.Is(err, consensus_types.ErrUnsupportedField) {
log.WithError(err).Warn("failed to retrieve execution payload")
}
return 0
}
val, err := exec.ValueInGwei()
if err != nil {
if !errors.Is(err, consensus_types.ErrUnsupportedField) {
log.WithError(err).Warn("failed to retrieve execution payload")
}
return 0
}
return val
}
// Header converts the underlying protobuf object from blinded block to header format.
func (b *SignedBeaconBlock) Header() (*eth.SignedBeaconBlockHeader, error) {
if b.IsNil() {

View File

@@ -1,7 +1,6 @@
package blocks
import (
"math/big"
"testing"
ssz "github.com/prysmaticlabs/fastssz"
@@ -215,9 +214,9 @@ func Test_BeaconBlock_Copy(t *testing.T) {
payload := &pb.ExecutionPayloadDeneb{ExcessBlobGas: 123}
header := &pb.ExecutionPayloadHeaderDeneb{ExcessBlobGas: 223}
payloadInterface, err := WrappedExecutionPayloadDeneb(payload, big.NewInt(123))
payloadInterface, err := WrappedExecutionPayloadDeneb(payload)
require.NoError(t, err)
headerInterface, err := WrappedExecutionPayloadHeaderDeneb(header, big.NewInt(123))
headerInterface, err := WrappedExecutionPayloadHeaderDeneb(header)
require.NoError(t, err)
bb = &BeaconBlockBody{executionPayload: payloadInterface, executionPayloadHeader: headerInterface, randaoReveal: bytesutil.ToBytes96([]byte{246}), graffiti: bytesutil.ToBytes32([]byte("graffiti"))}
b = &BeaconBlock{body: bb, slot: 123, proposerIndex: 456, parentRoot: bytesutil.ToBytes32([]byte("parentroot")), stateRoot: bytesutil.ToBytes32([]byte("stateroot"))}
@@ -425,7 +424,7 @@ func Test_BeaconBlockBody_Execution(t *testing.T) {
assert.DeepEqual(t, result, e)
executionCapella := &pb.ExecutionPayloadCapella{BlockNumber: 1}
eCapella, err := WrappedExecutionPayloadCapella(executionCapella, big.NewInt(0))
eCapella, err := WrappedExecutionPayloadCapella(executionCapella)
require.NoError(t, err)
bb = &SignedBeaconBlock{version: version.Capella, block: &BeaconBlock{body: &BeaconBlockBody{version: version.Capella}}}
require.NoError(t, bb.SetExecution(eCapella))
@@ -434,7 +433,7 @@ func Test_BeaconBlockBody_Execution(t *testing.T) {
assert.DeepEqual(t, result, eCapella)
executionCapellaHeader := &pb.ExecutionPayloadHeaderCapella{BlockNumber: 1}
eCapellaHeader, err := WrappedExecutionPayloadHeaderCapella(executionCapellaHeader, big.NewInt(0))
eCapellaHeader, err := WrappedExecutionPayloadHeaderCapella(executionCapellaHeader)
require.NoError(t, err)
bb = &SignedBeaconBlock{version: version.Capella, block: &BeaconBlock{version: version.Capella, body: &BeaconBlockBody{version: version.Capella}}}
require.NoError(t, bb.SetExecution(eCapellaHeader))
@@ -443,7 +442,7 @@ func Test_BeaconBlockBody_Execution(t *testing.T) {
assert.DeepEqual(t, result, eCapellaHeader)
executionDeneb := &pb.ExecutionPayloadDeneb{BlockNumber: 1, ExcessBlobGas: 123}
eDeneb, err := WrappedExecutionPayloadDeneb(executionDeneb, big.NewInt(0))
eDeneb, err := WrappedExecutionPayloadDeneb(executionDeneb)
require.NoError(t, err)
bb = &SignedBeaconBlock{version: version.Deneb, block: &BeaconBlock{body: &BeaconBlockBody{version: version.Deneb}}}
require.NoError(t, bb.SetExecution(eDeneb))
@@ -455,7 +454,7 @@ func Test_BeaconBlockBody_Execution(t *testing.T) {
require.DeepEqual(t, gas, uint64(123))
executionDenebHeader := &pb.ExecutionPayloadHeaderDeneb{BlockNumber: 1, ExcessBlobGas: 223}
eDenebHeader, err := WrappedExecutionPayloadHeaderDeneb(executionDenebHeader, big.NewInt(0))
eDenebHeader, err := WrappedExecutionPayloadHeaderDeneb(executionDenebHeader)
require.NoError(t, err)
bb = &SignedBeaconBlock{version: version.Deneb, block: &BeaconBlock{version: version.Deneb, body: &BeaconBlockBody{version: version.Deneb}}}
require.NoError(t, bb.SetExecution(eDenebHeader))

View File

@@ -1,8 +1,6 @@
package blocks
import (
"math/big"
"github.com/pkg/errors"
consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
@@ -1031,7 +1029,7 @@ func initBlockBodyFromProtoCapella(pb *eth.BeaconBlockBodyCapella) (*BeaconBlock
return nil, errNilBlockBody
}
p, err := WrappedExecutionPayloadCapella(pb.ExecutionPayload, big.NewInt(0))
p, err := WrappedExecutionPayloadCapella(pb.ExecutionPayload)
// We allow the payload to be nil
if err != nil && err != consensus_types.ErrNilObjectWrapped {
return nil, err
@@ -1058,7 +1056,7 @@ func initBlindedBlockBodyFromProtoCapella(pb *eth.BlindedBeaconBlockBodyCapella)
return nil, errNilBlockBody
}
ph, err := WrappedExecutionPayloadHeaderCapella(pb.ExecutionPayloadHeader, big.NewInt(0))
ph, err := WrappedExecutionPayloadHeaderCapella(pb.ExecutionPayloadHeader)
// We allow the payload to be nil
if err != nil && err != consensus_types.ErrNilObjectWrapped {
return nil, err
@@ -1085,7 +1083,7 @@ func initBlockBodyFromProtoDeneb(pb *eth.BeaconBlockBodyDeneb) (*BeaconBlockBody
return nil, errNilBlockBody
}
p, err := WrappedExecutionPayloadDeneb(pb.ExecutionPayload, big.NewInt(0))
p, err := WrappedExecutionPayloadDeneb(pb.ExecutionPayload)
// We allow the payload to be nil
if err != nil && err != consensus_types.ErrNilObjectWrapped {
return nil, err
@@ -1113,7 +1111,7 @@ func initBlindedBlockBodyFromProtoDeneb(pb *eth.BlindedBeaconBlockBodyDeneb) (*B
return nil, errNilBlockBody
}
ph, err := WrappedExecutionPayloadHeaderDeneb(pb.ExecutionPayloadHeader, big.NewInt(0))
ph, err := WrappedExecutionPayloadHeaderDeneb(pb.ExecutionPayloadHeader)
// We allow the payload to be nil
if err != nil && err != consensus_types.ErrNilObjectWrapped {
return nil, err
@@ -1141,7 +1139,7 @@ func initBlockBodyFromProtoElectra(pb *eth.BeaconBlockBodyElectra) (*BeaconBlock
return nil, errNilBlockBody
}
p, err := WrappedExecutionPayloadElectra(pb.ExecutionPayload, big.NewInt(0))
p, err := WrappedExecutionPayloadElectra(pb.ExecutionPayload)
// We allow the payload to be nil
if err != nil && err != consensus_types.ErrNilObjectWrapped {
return nil, err
@@ -1170,7 +1168,7 @@ func initBlindedBlockBodyFromProtoElectra(pb *eth.BlindedBeaconBlockBodyElectra)
return nil, errNilBlockBody
}
ph, err := WrappedExecutionPayloadHeaderElectra(pb.ExecutionPayloadHeader, big.NewInt(0))
ph, err := WrappedExecutionPayloadHeaderElectra(pb.ExecutionPayloadHeader)
// We allow the payload to be nil
if err != nil && err != consensus_types.ErrNilObjectWrapped {
return nil, err

View File

@@ -1,7 +1,6 @@
package blocks
import (
"math/big"
"testing"
"github.com/prysmaticlabs/go-bitfield"
@@ -1332,7 +1331,7 @@ func bodyBlindedBellatrix(t *testing.T) *BeaconBlockBody {
func bodyCapella(t *testing.T) *BeaconBlockBody {
f := getFields()
p, err := WrappedExecutionPayloadCapella(f.execPayloadCapella, big.NewInt(0))
p, err := WrappedExecutionPayloadCapella(f.execPayloadCapella)
require.NoError(t, err)
return &BeaconBlockBody{
version: version.Capella,
@@ -1356,7 +1355,7 @@ func bodyCapella(t *testing.T) *BeaconBlockBody {
func bodyBlindedCapella(t *testing.T) *BeaconBlockBody {
f := getFields()
ph, err := WrappedExecutionPayloadHeaderCapella(f.execPayloadHeaderCapella, big.NewInt(0))
ph, err := WrappedExecutionPayloadHeaderCapella(f.execPayloadHeaderCapella)
require.NoError(t, err)
return &BeaconBlockBody{
version: version.Capella,
@@ -1380,7 +1379,7 @@ func bodyBlindedCapella(t *testing.T) *BeaconBlockBody {
func bodyDeneb(t *testing.T) *BeaconBlockBody {
f := getFields()
p, err := WrappedExecutionPayloadDeneb(f.execPayloadDeneb, big.NewInt(0))
p, err := WrappedExecutionPayloadDeneb(f.execPayloadDeneb)
require.NoError(t, err)
return &BeaconBlockBody{
version: version.Deneb,
@@ -1405,7 +1404,7 @@ func bodyDeneb(t *testing.T) *BeaconBlockBody {
func bodyBlindedDeneb(t *testing.T) *BeaconBlockBody {
f := getFields()
ph, err := WrappedExecutionPayloadHeaderDeneb(f.execPayloadHeaderDeneb, big.NewInt(0))
ph, err := WrappedExecutionPayloadHeaderDeneb(f.execPayloadHeaderDeneb)
require.NoError(t, err)
return &BeaconBlockBody{
version: version.Deneb,

View File

@@ -27,8 +27,6 @@ type ReadOnlySignedBeaconBlock interface {
ssz.Unmarshaler
Version() int
IsBlinded() bool
ValueInWei() primitives.Wei
ValueInGwei() uint64
Header() (*ethpb.SignedBeaconBlockHeader, error)
}
@@ -128,8 +126,6 @@ type ExecutionData interface {
TransactionsRoot() ([]byte, error)
Withdrawals() ([]*enginev1.Withdrawal, error)
WithdrawalsRoot() ([]byte, error)
ValueInWei() (primitives.Wei, error)
ValueInGwei() (uint64, error)
}
type ExecutionDataElectra interface {

View File

@@ -75,14 +75,6 @@ func (SignedBeaconBlock) Header() (*eth.SignedBeaconBlockHeader, error) {
panic("implement me")
}
func (SignedBeaconBlock) ValueInWei() primitives.Wei {
panic("implement me")
}
func (SignedBeaconBlock) ValueInGwei() uint64 {
panic("implement me")
}
type BeaconBlock struct {
Htr [field_params.RootLength]byte
HtrErr error

View File

@@ -71,12 +71,18 @@ func Uint64ToWei(v uint64) Wei {
return big.NewInt(0).SetUint64(v)
}
// BigEndianBytesToWei returns a Wei value given a big-endian binary representation (eg engine api payload bids).
func BigEndianBytesToWei(value []byte) Wei {
// LittleEndianBytesToWei returns a Wei value given a little-endian binary representation.
// The only places we use this representation are in protobuf types that hold either the
// local execution payload bid or the builder bid. Going forward we should avoid that representation
// so this function being used in new places should be considered a code smell.
func LittleEndianBytesToWei(value []byte) Wei {
if len(value) == 0 {
return big.NewInt(0)
}
v := make([]byte, len(value))
copy(v, value)
// SetBytes expects a big-endian representation of the value, so we reverse the byte slice.
slices.Reverse(v)
// We have to convert big endian to little endian because the value is coming from the execution layer.
return big.NewInt(0).SetBytes(v)
}

View File

@@ -39,3 +39,8 @@ func TestWeiToGwei_CopyOk(t *testing.T) {
require.Equal(t, primitives.Gwei(1), got)
require.Equal(t, big.NewInt(1e9).Uint64(), v.Uint64())
}
func TestZero(t *testing.T) {
z := primitives.ZeroWei
require.Equal(t, 0, big.NewInt(0).Cmp(z))
}

View File

@@ -14,7 +14,6 @@ go_test(
srcs = ["math_helper_test.go"],
deps = [
":go_default_library",
"//consensus-types/primitives:go_default_library",
"//testing/require:go_default_library",
],
)

View File

@@ -3,10 +3,8 @@ package math_test
import (
"fmt"
stdmath "math"
"math/big"
"testing"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/math"
"github.com/prysmaticlabs/prysm/v5/testing/require"
)
@@ -551,28 +549,3 @@ func TestAddInt(t *testing.T) {
})
}
}
func TestWeiToGwei(t *testing.T) {
tests := []struct {
v *big.Int
want primitives.Gwei
}{
{big.NewInt(1e9 - 1), 0},
{big.NewInt(1e9), 1},
{big.NewInt(1e10), 10},
{big.NewInt(239489233849348394), 239489233},
}
for _, tt := range tests {
if got := primitives.WeiToGwei(tt.v); got != tt.want {
t.Errorf("WeiToGwei() = %v, want %v", got, tt.want)
}
}
}
func TestWeiToGwei_CopyOk(t *testing.T) {
v := big.NewInt(1e9)
got := primitives.WeiToGwei(v)
require.Equal(t, primitives.Gwei(1), got)
require.Equal(t, big.NewInt(1e9).Uint64(), v.Uint64())
}

View File

@@ -2,7 +2,6 @@ package interop
import (
"context"
"math/big"
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
@@ -596,7 +595,7 @@ func (s *PremineGenesisConfig) setExecutionPayload(g state.BeaconState) error {
Transactions: make([][]byte, 0),
Withdrawals: make([]*enginev1.Withdrawal, 0),
}
wep, err := blocks.WrappedExecutionPayloadCapella(payload, big.NewInt(0))
wep, err := blocks.WrappedExecutionPayloadCapella(payload)
if err != nil {
return err
}
@@ -604,7 +603,7 @@ func (s *PremineGenesisConfig) setExecutionPayload(g state.BeaconState) error {
if err != nil {
return err
}
ed, err = blocks.WrappedExecutionPayloadHeaderCapella(eph, big.NewInt(0))
ed, err = blocks.WrappedExecutionPayloadHeaderCapella(eph)
if err != nil {
return err
}
@@ -628,7 +627,7 @@ func (s *PremineGenesisConfig) setExecutionPayload(g state.BeaconState) error {
ExcessBlobGas: *gb.ExcessBlobGas(),
BlobGasUsed: *gb.BlobGasUsed(),
}
wep, err := blocks.WrappedExecutionPayloadDeneb(payload, big.NewInt(0))
wep, err := blocks.WrappedExecutionPayloadDeneb(payload)
if err != nil {
return err
}
@@ -636,7 +635,7 @@ func (s *PremineGenesisConfig) setExecutionPayload(g state.BeaconState) error {
if err != nil {
return err
}
ed, err = blocks.WrappedExecutionPayloadHeaderDeneb(eph, big.NewInt(0))
ed, err = blocks.WrappedExecutionPayloadHeaderDeneb(eph)
if err != nil {
return err
}

View File

@@ -423,11 +423,7 @@ func (p *Builder) handleHeaderRequestCapella(w http.ResponseWriter) {
v := big.NewInt(0).SetBytes(bytesutil.ReverseByteOrder(b.Value))
// we set the payload value as twice its actual one so that it always chooses builder payloads vs local payloads
v = v.Mul(v, big.NewInt(2))
// Is used as the helper modifies the big.Int
weiVal := big.NewInt(0).SetBytes(bytesutil.ReverseByteOrder(b.Value))
// we set the payload value as twice its actual one so that it always chooses builder payloads vs local payloads
weiVal = weiVal.Mul(weiVal, big.NewInt(2))
wObj, err := blocks.WrappedExecutionPayloadCapella(b.Payload, weiVal)
wObj, err := blocks.WrappedExecutionPayloadCapella(b.Payload)
if err != nil {
p.cfg.logger.WithError(err).Error("Could not wrap execution payload")
http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -504,11 +500,7 @@ func (p *Builder) handleHeaderRequestDeneb(w http.ResponseWriter) {
v := big.NewInt(0).SetBytes(bytesutil.ReverseByteOrder(b.Value))
// we set the payload value as twice its actual one so that it always chooses builder payloads vs local payloads
v = v.Mul(v, big.NewInt(2))
// Is used as the helper modifies the big.Int
weiVal := big.NewInt(0).SetBytes(bytesutil.ReverseByteOrder(b.Value))
// we set the payload value as twice its actual one so that it always chooses builder payloads vs local payloads
weiVal = weiVal.Mul(weiVal, big.NewInt(2))
wObj, err := blocks.WrappedExecutionPayloadDeneb(b.Payload, weiVal)
wObj, err := blocks.WrappedExecutionPayloadDeneb(b.Payload)
if err != nil {
p.cfg.logger.WithError(err).Error("Could not wrap execution payload")
http.Error(w, err.Error(), http.StatusInternalServerError)

View File

@@ -1,7 +1,6 @@
package operations
import (
"math/big"
"os"
"path"
"strings"
@@ -54,7 +53,7 @@ func RunExecutionPayloadTest(t *testing.T, config string) {
require.NoError(t, err)
}
payload, err := blocks2.WrappedExecutionPayloadCapella(block.ExecutionPayload, big.NewInt(0))
payload, err := blocks2.WrappedExecutionPayloadCapella(block.ExecutionPayload)
require.NoError(t, err)
file, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "execution.yaml")

View File

@@ -2,7 +2,6 @@ package operations
import (
"context"
"math/big"
"path"
"testing"
@@ -44,7 +43,7 @@ func RunWithdrawalsTest(t *testing.T, config string) {
if err != nil {
return nil, err
}
p, err := consensusblocks.WrappedExecutionPayloadCapella(&enginev1.ExecutionPayloadCapella{Withdrawals: withdrawals}, big.NewInt(0))
p, err := consensusblocks.WrappedExecutionPayloadCapella(&enginev1.ExecutionPayloadCapella{Withdrawals: withdrawals})
require.NoError(t, err)
return blocks.ProcessWithdrawals(s, p)
})

View File

@@ -22,6 +22,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/startup"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
payloadattribute "github.com/prysmaticlabs/prysm/v5/consensus-types/payload-attribute"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
@@ -92,8 +93,8 @@ type engineMock struct {
payloadStatus error
}
func (m *engineMock) GetPayload(context.Context, [8]byte, primitives.Slot) (interfaces.ExecutionData, *pb.BlobsBundle, bool, error) {
return nil, nil, false, nil
func (m *engineMock) GetPayload(context.Context, [8]byte, primitives.Slot) (*blocks.GetPayloadResponse, error) {
return nil, nil
}
func (m *engineMock) GetPayloadV2(context.Context, [8]byte) (*pb.ExecutionPayloadCapella, error) {
return nil, nil

View File

@@ -1,7 +1,6 @@
package operations
import (
"math/big"
"os"
"path"
"strings"
@@ -57,7 +56,7 @@ func RunExecutionPayloadTest(t *testing.T, config string) {
require.NoError(t, err)
}
payload, err := blocks2.WrappedExecutionPayloadDeneb(body.ExecutionPayload, big.NewInt(0))
payload, err := blocks2.WrappedExecutionPayloadDeneb(body.ExecutionPayload)
require.NoError(t, err)
file, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "execution.yaml")

View File

@@ -2,7 +2,6 @@ package operations
import (
"context"
"math/big"
"path"
"testing"
@@ -41,7 +40,7 @@ func RunWithdrawalsTest(t *testing.T, config string) {
if err != nil {
return nil, err
}
p, err := consensusblocks.WrappedExecutionPayloadDeneb(&enginev1.ExecutionPayloadDeneb{Withdrawals: withdrawals}, big.NewInt(0))
p, err := consensusblocks.WrappedExecutionPayloadDeneb(&enginev1.ExecutionPayloadDeneb{Withdrawals: withdrawals})
require.NoError(t, err)
return blocks.ProcessWithdrawals(s, p)
})

View File

@@ -1,7 +1,6 @@
package operations
import (
"math/big"
"os"
"path"
"strings"
@@ -59,7 +58,7 @@ func RunExecutionPayloadTest(t *testing.T, config string) {
require.NoError(t, err)
}
payload, err := blocks2.WrappedExecutionPayloadElectra(body.ExecutionPayload, big.NewInt(0))
payload, err := blocks2.WrappedExecutionPayloadElectra(body.ExecutionPayload)
require.NoError(t, err)
file, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "execution.yaml")

View File

@@ -2,7 +2,6 @@ package operations
import (
"context"
"math/big"
"path"
"testing"
@@ -41,7 +40,7 @@ func RunWithdrawalsTest(t *testing.T, config string) {
if err != nil {
return nil, err
}
p, err := consensusblocks.WrappedExecutionPayloadElectra(&enginev1.ExecutionPayloadElectra{Withdrawals: withdrawals}, big.NewInt(0))
p, err := consensusblocks.WrappedExecutionPayloadElectra(&enginev1.ExecutionPayloadElectra{Withdrawals: withdrawals})
require.NoError(t, err)
return blocks.ProcessWithdrawals(s, p)
})