Skip to content

Commit

Permalink
simulators/ethereum/engine: beaconRoot everywhere
Browse files Browse the repository at this point in the history
  • Loading branch information
marioevz authored and fjl committed Aug 1, 2023
1 parent 5bc099c commit e702282
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 97 deletions.
4 changes: 2 additions & 2 deletions simulators/ethereum/engine/client/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ type Engine interface {
GetPayloadV2(ctx context.Context, payloadId *api.PayloadID) (typ.ExecutableData, *big.Int, error)
GetPayloadV3(ctx context.Context, payloadId *api.PayloadID) (typ.ExecutableData, *big.Int, *typ.BlobsBundle, error)

NewPayload(ctx context.Context, version int, payload interface{}, versionedHashes *[]common.Hash) (api.PayloadStatusV1, error)
NewPayload(ctx context.Context, version int, payload interface{}, versionedHashes *[]common.Hash, beaconRoot *common.Hash) (api.PayloadStatusV1, error)
NewPayloadV1(ctx context.Context, payload *typ.ExecutableDataV1) (api.PayloadStatusV1, error)
NewPayloadV2(ctx context.Context, payload *typ.ExecutableData) (api.PayloadStatusV1, error)
NewPayloadV3(ctx context.Context, payload *typ.ExecutableData, versionedHashes *[]common.Hash) (api.PayloadStatusV1, error)
NewPayloadV3(ctx context.Context, payload *typ.ExecutableData, versionedHashes *[]common.Hash, beaconRoot *common.Hash) (api.PayloadStatusV1, error)

GetPayloadBodiesByRangeV1(ctx context.Context, start uint64, count uint64) ([]*typ.ExecutionPayloadBodyV1, error)
GetPayloadBodiesByHashV1(ctx context.Context, hashes []common.Hash) ([]*typ.ExecutionPayloadBodyV1, error)
Expand Down
12 changes: 6 additions & 6 deletions simulators/ethereum/engine/client/hive_rpc/hive_rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,13 +452,13 @@ func (ec *HiveRPCEngineClient) GetBlobsBundleV1(ctx context.Context, payloadId *
}

// New Payload API Call Methods
func (ec *HiveRPCEngineClient) NewPayload(ctx context.Context, version int, payload interface{}, versionedHashes *[]common.Hash) (result api.PayloadStatusV1, err error) {
func (ec *HiveRPCEngineClient) NewPayload(ctx context.Context, version int, payload interface{}, versionedHashes *[]common.Hash, beaconRoot *common.Hash) (result api.PayloadStatusV1, err error) {
if err := ec.PrepareDefaultAuthCallToken(); err != nil {
return result, err
}

if version >= 3 {
err = ec.c.CallContext(ctx, &result, fmt.Sprintf("engine_newPayloadV%d", version), payload, versionedHashes)
err = ec.c.CallContext(ctx, &result, fmt.Sprintf("engine_newPayloadV%d", version), payload, versionedHashes, beaconRoot)
} else {
err = ec.c.CallContext(ctx, &result, fmt.Sprintf("engine_newPayloadV%d", version), payload)
}
Expand All @@ -469,17 +469,17 @@ func (ec *HiveRPCEngineClient) NewPayload(ctx context.Context, version int, payl
func (ec *HiveRPCEngineClient) NewPayloadV1(ctx context.Context, payload *typ.ExecutableDataV1) (api.PayloadStatusV1, error) {
ed := payload.ToExecutableData()
ec.latestPayloadSent = &ed
return ec.NewPayload(ctx, 1, payload, nil)
return ec.NewPayload(ctx, 1, payload, nil, nil)
}

func (ec *HiveRPCEngineClient) NewPayloadV2(ctx context.Context, payload *typ.ExecutableData) (api.PayloadStatusV1, error) {
ec.latestPayloadSent = payload
return ec.NewPayload(ctx, 2, payload, nil)
return ec.NewPayload(ctx, 2, payload, nil, nil)
}

func (ec *HiveRPCEngineClient) NewPayloadV3(ctx context.Context, payload *typ.ExecutableData, versionedHashes *[]common.Hash) (api.PayloadStatusV1, error) {
func (ec *HiveRPCEngineClient) NewPayloadV3(ctx context.Context, payload *typ.ExecutableData, versionedHashes *[]common.Hash, beaconRoot *common.Hash) (api.PayloadStatusV1, error) {
ec.latestPayloadSent = payload
return ec.NewPayload(ctx, 3, payload, versionedHashes)
return ec.NewPayload(ctx, 3, payload, versionedHashes, beaconRoot)
}

// Exchange Transition Configuration API Call Methods
Expand Down
8 changes: 4 additions & 4 deletions simulators/ethereum/engine/client/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ func (n *GethNode) SetBlock(block *types.Block, parentNumber uint64, parentRoot
}

// Engine API
func (n *GethNode) NewPayload(ctx context.Context, version int, pl interface{}, vh *[]common.Hash) (beacon.PayloadStatusV1, error) {
func (n *GethNode) NewPayload(ctx context.Context, version int, pl interface{}, vh *[]common.Hash, beaconRoot *common.Hash) (beacon.PayloadStatusV1, error) {
switch version {
case 1:
if c, ok := pl.(*typ.ExecutableDataV1); ok {
Expand All @@ -448,7 +448,7 @@ func (n *GethNode) NewPayload(ctx context.Context, version int, pl interface{},
}
case 3:
if c, ok := pl.(*typ.ExecutableData); ok {
return n.NewPayloadV3(ctx, c, vh)
return n.NewPayloadV3(ctx, c, vh, beaconRoot)
} else {
return beacon.PayloadStatusV1{}, fmt.Errorf("wrong type %T", pl)
}
Expand Down Expand Up @@ -479,13 +479,13 @@ func (n *GethNode) NewPayloadV2(ctx context.Context, pl *typ.ExecutableData) (be
return resp, err
}

func (n *GethNode) NewPayloadV3(ctx context.Context, pl *typ.ExecutableData, versionedHashes *[]common.Hash) (beacon.PayloadStatusV1, error) {
func (n *GethNode) NewPayloadV3(ctx context.Context, pl *typ.ExecutableData, versionedHashes *[]common.Hash, beaconRoot *common.Hash) (beacon.PayloadStatusV1, error) {
n.latestPayloadSent = pl
ed, err := typ.ToBeaconExecutableData(pl)
if err != nil {
return beacon.PayloadStatusV1{}, err
}
resp, err := n.api.NewPayloadV3(ed, versionedHashes)
resp, err := n.api.NewPayloadV3(ed, versionedHashes, beaconRoot)
n.latestPayloadStatusReponse = &resp
return resp, err
}
Expand Down
16 changes: 8 additions & 8 deletions simulators/ethereum/engine/clmock/clmock.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,14 +381,14 @@ func (cl *CLMocker) SetNextWithdrawals(nextWithdrawals types.Withdrawals) {

func TimestampToBeaconRoot(timestamp uint64) common.Hash {
// Generates a deterministic hash from the timestamp
beaconBlockRoot := common.Hash{}
beaconRoot := common.Hash{}
timestampBytes := make([]byte, 8)
binary.BigEndian.PutUint64(timestampBytes[:], timestamp)
md := sha256.New()
md.Write(timestampBytes)
timestampHash := md.Sum(nil)
copy(beaconBlockRoot[:], timestampHash)
return beaconBlockRoot
copy(beaconRoot[:], timestampHash)
return beaconRoot
}

func (cl *CLMocker) RequestNextPayload() {
Expand All @@ -408,8 +408,8 @@ func (cl *CLMocker) RequestNextPayload() {

if cl.IsCancun(cl.LatestPayloadAttributes.Timestamp) {
// Write a deterministic hash based on the block number
beaconBlockRoot := TimestampToBeaconRoot(cl.LatestPayloadAttributes.Timestamp)
cl.LatestPayloadAttributes.ParentBeaconBlockRoot = &beaconBlockRoot
beaconRoot := TimestampToBeaconRoot(cl.LatestPayloadAttributes.Timestamp)
cl.LatestPayloadAttributes.BeaconRoot = &beaconRoot
}

// Save random value
Expand Down Expand Up @@ -488,7 +488,7 @@ func (cl *CLMocker) broadcastNextNewPayload() {
}
}
// Broadcast the executePayload to all clients
responses := cl.BroadcastNewPayload(&cl.LatestPayloadBuilt, versionedHashes)
responses := cl.BroadcastNewPayload(&cl.LatestPayloadBuilt, versionedHashes, cl.LatestPayloadAttributes.BeaconRoot)
validations := 0
for _, resp := range responses {
if resp.Error != nil {
Expand Down Expand Up @@ -701,7 +701,7 @@ type ExecutePayloadOutcome struct {
Error error
}

func (cl *CLMocker) BroadcastNewPayload(payload *typ.ExecutableData, versionedHashes *[]common.Hash) []ExecutePayloadOutcome {
func (cl *CLMocker) BroadcastNewPayload(payload *typ.ExecutableData, versionedHashes *[]common.Hash, beaconRoot *common.Hash) []ExecutePayloadOutcome {
responses := make([]ExecutePayloadOutcome, len(cl.EngineClients))
for i, ec := range cl.EngineClients {
responses[i].Container = ec.ID()
Expand All @@ -712,7 +712,7 @@ func (cl *CLMocker) BroadcastNewPayload(payload *typ.ExecutableData, versionedHa
err error
)
if cl.IsCancun(payload.Timestamp) {
execPayloadResp, err = ec.NewPayloadV3(ctx, payload, versionedHashes)
execPayloadResp, err = ec.NewPayloadV3(ctx, payload, versionedHashes, beaconRoot)
} else if cl.IsShanghai(payload.Timestamp) {
execPayloadResp, err = ec.NewPayloadV2(ctx, payload)
} else {
Expand Down
82 changes: 39 additions & 43 deletions simulators/ethereum/engine/helper/payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,50 +12,49 @@ import (
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/hive/simulators/ethereum/engine/globals"
typ "github.com/ethereum/hive/simulators/ethereum/engine/types"
"github.com/pkg/errors"
)

type PayloadCustomizer interface {
CustomizePayload(basePayload *typ.ExecutableData) (*typ.ExecutableData, error)
CustomizePayload(basePayload *typ.ExecutableData) (modifiedPayload *typ.ExecutableData, beaconRoot *common.Hash, err error)
}

type CustomPayloadData struct {
ParentHash *common.Hash
FeeRecipient *common.Address
StateRoot *common.Hash
ReceiptsRoot *common.Hash
LogsBloom *[]byte
PrevRandao *common.Hash
Number *uint64
GasLimit *uint64
GasUsed *uint64
Timestamp *uint64
ExtraData *[]byte
BaseFeePerGas *big.Int
BlockHash *common.Hash
Transactions *[][]byte
Withdrawals types.Withdrawals
RemoveWithdrawals bool
BlobGasUsed *uint64
RemoveBlobGasUsed bool
ExcessBlobGas *uint64
RemoveExcessBlobGas bool
ParentBeaconBlockRoot *common.Hash
RemoveParentBeaconBlockRoot bool
ParentHash *common.Hash
FeeRecipient *common.Address
StateRoot *common.Hash
ReceiptsRoot *common.Hash
LogsBloom *[]byte
PrevRandao *common.Hash
Number *uint64
GasLimit *uint64
GasUsed *uint64
Timestamp *uint64
ExtraData *[]byte
BaseFeePerGas *big.Int
BlockHash *common.Hash
Transactions *[][]byte
Withdrawals types.Withdrawals
RemoveWithdrawals bool
BlobGasUsed *uint64
RemoveBlobGasUsed bool
ExcessBlobGas *uint64
RemoveExcessBlobGas bool
BeaconRoot *common.Hash
RemoveBeaconRoot bool
}

var _ PayloadCustomizer = (*CustomPayloadData)(nil)

// Construct a customized payload by taking an existing payload as base and mixing it CustomPayloadData
// BlockHash is calculated automatically.
func (customData *CustomPayloadData) CustomizePayload(basePayload *typ.ExecutableData) (*typ.ExecutableData, error) {
func (customData *CustomPayloadData) CustomizePayload(basePayload *typ.ExecutableData) (*typ.ExecutableData, *common.Hash, error) {
txs := basePayload.Transactions
if customData.Transactions != nil {
txs = *customData.Transactions
}
txsHash, err := calcTxsHash(txs)
if err != nil {
return nil, err
return nil, nil, err
}
fmt.Printf("txsHash: %v\n", txsHash)
// Start by filling the header with the basePayload information
Expand Down Expand Up @@ -137,8 +136,10 @@ func (customData *CustomPayloadData) CustomizePayload(basePayload *typ.Executabl
} else if basePayload.ExcessBlobGas != nil {
customPayloadHeader.ExcessBlobGas = basePayload.ExcessBlobGas
}
if customData.ParentBeaconBlockRoot != nil {
return nil, errors.New("ParentBeaconBlockRoot is not supported")
if customData.RemoveBeaconRoot {
customPayloadHeader.BeaconRoot = nil
} else if customData.BeaconRoot != nil {
customPayloadHeader.BeaconRoot = customData.BeaconRoot
}

// Return the new payload
Expand Down Expand Up @@ -167,15 +168,15 @@ func (customData *CustomPayloadData) CustomizePayload(basePayload *typ.Executabl
} else if basePayload.Withdrawals != nil {
result.Withdrawals = basePayload.Withdrawals
}
return result, nil
return result, customPayloadHeader.BeaconRoot, nil
}

func CustomizePayloadTransactions(basePayload *typ.ExecutableData, customTransactions types.Transactions) (*typ.ExecutableData, error) {
func CustomizePayloadTransactions(basePayload *typ.ExecutableData, customTransactions types.Transactions) (*typ.ExecutableData, *common.Hash, error) {
byteTxs := make([][]byte, 0)
for _, tx := range customTransactions {
bytes, err := tx.MarshalBinary()
if err != nil {
return nil, err
return nil, nil, err
}
byteTxs = append(byteTxs, bytes)
}
Expand Down Expand Up @@ -233,7 +234,7 @@ func (customData *CustomPayloadData) String() string {

// This function generates an invalid payload by taking a base payload and modifying the specified field such that it ends up being invalid.
// One small consideration is that the payload needs to contain transactions and specially transactions using the PREVRANDAO opcode for all the fields to be compatible with this function.
func GenerateInvalidPayload(basePayload *typ.ExecutableData, payloadField InvalidPayloadBlockField) (*typ.ExecutableData, error) {
func GenerateInvalidPayload(basePayload *typ.ExecutableData, payloadField InvalidPayloadBlockField) (*typ.ExecutableData, *common.Hash, error) {

var customPayloadMod *CustomPayloadData
switch payloadField {
Expand Down Expand Up @@ -297,11 +298,11 @@ func GenerateInvalidPayload(basePayload *typ.ExecutableData, payloadField Invali
InvalidTransactionChainID:

if len(basePayload.Transactions) == 0 {
return nil, fmt.Errorf("no transactions available for modification")
return nil, nil, fmt.Errorf("no transactions available for modification")
}
var baseTx types.Transaction
if err := baseTx.UnmarshalBinary(basePayload.Transactions[0]); err != nil {
return nil, err
return nil, nil, err
}
var customTxData CustomTransactionData
switch payloadField {
Expand Down Expand Up @@ -332,12 +333,12 @@ func GenerateInvalidPayload(basePayload *typ.ExecutableData, payloadField Invali

modifiedTx, err := customizeTransaction(&baseTx, globals.VaultKey, &customTxData)
if err != nil {
return nil, err
return nil, nil, err
}

modifiedTxBytes, err := modifiedTx.MarshalBinary()
if err != nil {
return nil, err
return nil, nil, err
}
modifiedTransactions := [][]byte{
modifiedTxBytes,
Expand All @@ -349,15 +350,10 @@ func GenerateInvalidPayload(basePayload *typ.ExecutableData, payloadField Invali

if customPayloadMod == nil {
copyPayload := *basePayload
return &copyPayload, nil
return &copyPayload, nil, nil
}

alteredPayload, err := customPayloadMod.CustomizePayload(basePayload)
if err != nil {
return nil, err
}

return alteredPayload, nil
return customPayloadMod.CustomizePayload(basePayload)
}

/*
Expand Down
22 changes: 18 additions & 4 deletions simulators/ethereum/engine/suites/blobs/steps.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ func (step NewPayloads) Execute(t *BlobTestContext) error {
var (
payload = &t.CLMock.LatestPayloadBuilt
versionedHashes *[]common.Hash = nil
beaconRoot *common.Hash = t.CLMock.LatestPayloadAttributes.BeaconRoot
r *test.NewPayloadResponseExpectObject
err error
)
Expand All @@ -447,10 +448,11 @@ func (step NewPayloads) Execute(t *BlobTestContext) error {

if step.PayloadCustomizer != nil {
// Send a custom new payload
payload, err = step.PayloadCustomizer.CustomizePayload(payload)
payload, beaconRoot, err = step.PayloadCustomizer.CustomizePayload(payload)
if err != nil {
t.Fatalf("FAIL: Error customizing payload (payload %d/%d): %v", p+1, payloadCount, err)
}

}

version := step.Version
Expand All @@ -463,7 +465,7 @@ func (step NewPayloads) Execute(t *BlobTestContext) error {
}

if version == 3 {
r = t.TestEngine.TestEngineNewPayloadV3(payload, versionedHashes)
r = t.TestEngine.TestEngineNewPayloadV3(payload, versionedHashes, beaconRoot)
} else if version == 2 {
r = t.TestEngine.TestEngineNewPayloadV2(payload)
} else {
Expand Down Expand Up @@ -604,14 +606,19 @@ type SendModifiedLatestPayload struct {
ClientID uint64
// Versioned hashes modification
VersionedHashes *VersionedHashes
// Other modifications
PayloadCustomizer helper.PayloadCustomizer
// Expected responses on the NewPayload call
ExpectedError *int
ExpectedStatus test.PayloadStatus
}

func (step SendModifiedLatestPayload) Execute(t *BlobTestContext) error {
// Get the latest payload
payload := &t.CLMock.LatestPayloadBuilt
var (
payload = &t.CLMock.LatestPayloadBuilt
beaconRoot = t.CLMock.LatestPayloadAttributes.BeaconRoot
)
if payload == nil {
return fmt.Errorf("no payload available")
}
Expand All @@ -620,12 +627,19 @@ func (step SendModifiedLatestPayload) Execute(t *BlobTestContext) error {
if err != nil {
return fmt.Errorf("error getting modified versioned hashes: %v", err)
}
// Modify the payload
if step.PayloadCustomizer != nil {
payload, beaconRoot, err = step.PayloadCustomizer.CustomizePayload(payload)
if err != nil {
return fmt.Errorf("error modifying payload: %v", err)
}
}
// Send the payload
if step.ClientID >= uint64(len(t.TestEngines)) {
return fmt.Errorf("invalid client index %d", step.ClientID)
}
testEngine := t.TestEngines[step.ClientID]
r := testEngine.TestEngineNewPayloadV3(payload, versionedHashes)
r := testEngine.TestEngineNewPayloadV3(payload, versionedHashes, beaconRoot)
if step.ExpectedError != nil {
r.ExpectErrorCode(*step.ExpectedError)
} else {
Expand Down
Loading

0 comments on commit e702282

Please sign in to comment.