Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simulators/ethereum/engine: Add incorrect engine versions tests #834

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion simulators/ethereum/engine/client/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type Engine interface {
GetPayloadV1(ctx context.Context, payloadId *api.PayloadID) (typ.ExecutableData, error)
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, *bool, error)
GetPayload(ctx context.Context, version int, payloadId *api.PayloadID) (typ.ExecutableData, *big.Int, *typ.BlobsBundle, *bool, 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)
Expand Down Expand Up @@ -85,6 +86,6 @@ var (
Pending = big.NewInt(-2)
Finalized = big.NewInt(-3)
Safe = big.NewInt(-4)
LatestForkchoiceUpdatedVersion = 2
LatestForkchoiceUpdatedVersion = 3
LatestNewPayloadVersion = 3
)
10 changes: 10 additions & 0 deletions simulators/ethereum/engine/client/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,16 @@ func (n *GethNode) GetPayloadV3(ctx context.Context, payloadId *beacon.PayloadID
return ed, p.BlockValue, nil, &p.Override, err
}

func (n *GethNode) GetPayload(ctx context.Context, version int, payloadId *beacon.PayloadID) (typ.ExecutableData, *big.Int, *typ.BlobsBundle, *bool, error) {
p, err := n.api.GetPayloadV3(*payloadId)
if p == nil || err != nil {
return typ.ExecutableData{}, nil, nil, nil, err
}
ed, err := typ.FromBeaconExecutableData(p.ExecutionPayload)
// TODO: Convert and return the blobs bundle
return ed, p.BlockValue, nil, &p.Override, err
}

func (n *GethNode) GetPayloadBodiesByRangeV1(ctx context.Context, start uint64, count uint64) ([]*typ.ExecutionPayloadBodyV1, error) {
return nil, fmt.Errorf("not implemented")
}
Expand Down
61 changes: 40 additions & 21 deletions simulators/ethereum/engine/clmock/clmock.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"crypto/sha256"
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"math/big"
"math/rand"
Expand All @@ -23,6 +22,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/hive/hivesim"
"github.com/pkg/errors"
)

var (
Expand Down Expand Up @@ -89,6 +89,9 @@ type CLMocker struct {
// Chain History
HeaderHistory map[uint64]*types.Header

// Payload ID History
PayloadIDHistory map[api.PayloadID]interface{}

// PoS Chain History Information
PrevRandaoHistory map[uint64]common.Hash
ExecutedPayloadHistory ExecutableDataHistory
Expand Down Expand Up @@ -147,6 +150,7 @@ func NewCLMocker(t *hivesim.T, genesis *core.Genesis, slotsToSafe, slotsToFinali
SlotsToFinalized: slotsToFinalized,
SafeSlotsToImportOptimistically: safeSlotsToImportOptimistically,
PayloadProductionClientDelay: DefaultPayloadProductionClientDelay,
PayloadIDHistory: make(map[api.PayloadID]interface{}),
LatestHeader: nil,
FirstPoSBlockNumber: nil,
LatestHeadNumber: nil,
Expand Down Expand Up @@ -392,7 +396,7 @@ func TimestampToBeaconRoot(timestamp uint64) common.Hash {
return beaconRoot
}

func (cl *CLMocker) RequestNextPayload() {
func (cl *CLMocker) GeneratePayloadAttributes() {
// Generate a random value for the PrevRandao field
nextPrevRandao := common.Hash{}
rand.Read(nextPrevRandao[:])
Expand All @@ -415,10 +419,23 @@ func (cl *CLMocker) RequestNextPayload() {

// Save random value
cl.PrevRandaoHistory[cl.LatestHeader.Number.Uint64()+1] = nextPrevRandao
}

func (cl *CLMocker) AddPayloadID(newPayloadID *api.PayloadID) error {
if newPayloadID == nil {
return errors.New("nil payload ID")
}
if _, ok := cl.PayloadIDHistory[*newPayloadID]; ok {
return fmt.Errorf("Reused payload ID: %v", *newPayloadID)
}
cl.PayloadIDHistory[*newPayloadID] = nil
return nil
}

func (cl *CLMocker) RequestNextPayload() {
ctx, cancel := context.WithTimeout(cl.TestContext, globals.RPCTimeout)
defer cancel()
fcUVersion := cl.ForkchoiceUpdatedVersion(cl.LatestPayloadAttributes.Timestamp)
fcUVersion := cl.ForkchoiceUpdatedVersion(cl.LatestHeader.Time, &cl.LatestPayloadAttributes.Timestamp)
resp, err := cl.NextBlockProducer.ForkchoiceUpdated(ctx, fcUVersion, &cl.LatestForkchoice, &cl.LatestPayloadAttributes)
if err != nil {
cl.Fatalf("CLMocker: Could not send forkchoiceUpdatedV%d (%v): %v", fcUVersion, cl.NextBlockProducer.ID(), err)
Expand All @@ -429,23 +446,18 @@ func (cl *CLMocker) RequestNextPayload() {
if resp.PayloadStatus.LatestValidHash == nil || *resp.PayloadStatus.LatestValidHash != cl.LatestForkchoice.HeadBlockHash {
cl.Fatalf("CLMocker: Unexpected forkchoiceUpdated LatestValidHash Response from Payload builder: %v != %v", resp.PayloadStatus.LatestValidHash, cl.LatestForkchoice.HeadBlockHash)
}
if err = cl.AddPayloadID(resp.PayloadID); err != nil {
cl.Fatalf("CLMocker: Payload ID failure: %v", err)
}
cl.NextPayloadID = resp.PayloadID
}

func (cl *CLMocker) GetNextPayload() {
var err error
ctx, cancel := context.WithTimeout(cl.TestContext, globals.RPCTimeout)
defer cancel()
if cl.IsCancun(cl.LatestPayloadAttributes.Timestamp) {
cl.LatestPayloadBuilt, cl.LatestBlockValue, cl.LatestBlobBundle, cl.LatestShouldOverrideBuilder, err = cl.NextBlockProducer.GetPayloadV3(ctx, cl.NextPayloadID)
} else if cl.IsShanghai(cl.LatestPayloadAttributes.Timestamp) {
cl.LatestPayloadBuilt, cl.LatestBlockValue, err = cl.NextBlockProducer.GetPayloadV2(ctx, cl.NextPayloadID)
cl.LatestBlobBundle = nil
} else {
cl.LatestPayloadBuilt, err = cl.NextBlockProducer.GetPayloadV1(ctx, cl.NextPayloadID)
cl.LatestBlockValue = nil
cl.LatestBlobBundle = nil
}
version := cl.ForkConfig.GetPayloadVersion(cl.LatestPayloadAttributes.Timestamp)
cl.LatestPayloadBuilt, cl.LatestBlockValue, cl.LatestBlobBundle, cl.LatestShouldOverrideBuilder, err = cl.NextBlockProducer.GetPayload(ctx, version, cl.NextPayloadID)
if err != nil {
cl.Fatalf("CLMocker: Could not getPayload (%v, %v): %v", cl.NextBlockProducer.ID(), cl.NextPayloadID, err)
}
Expand Down Expand Up @@ -519,7 +531,7 @@ func (cl *CLMocker) broadcastNextNewPayload() {
}

func (cl *CLMocker) broadcastLatestForkchoice() {
version := cl.ForkchoiceUpdatedVersion(cl.LatestExecutedPayload.Timestamp)
version := cl.ForkchoiceUpdatedVersion(cl.LatestExecutedPayload.Timestamp, nil)
for _, resp := range cl.BroadcastForkchoiceUpdated(&cl.LatestForkchoice, nil, version) {
if resp.Error != nil {
cl.Logf("CLMocker: BroadcastForkchoiceUpdated Error (%v): %v\n", resp.Container, resp.Error)
Expand All @@ -543,13 +555,14 @@ func (cl *CLMocker) broadcastLatestForkchoice() {
}

type BlockProcessCallbacks struct {
OnPayloadProducerSelected func()
OnRequestNextPayload func()
OnGetPayload func()
OnNewPayloadBroadcast func()
OnForkchoiceBroadcast func()
OnSafeBlockChange func()
OnFinalizedBlockChange func()
OnPayloadProducerSelected func()
OnPayloadAttributesGenerated func()
OnRequestNextPayload func()
OnGetPayload func()
OnNewPayloadBroadcast func()
OnForkchoiceBroadcast func()
OnSafeBlockChange func()
OnFinalizedBlockChange func()
}

func (cl *CLMocker) ProduceSingleBlock(callbacks BlockProcessCallbacks) {
Expand All @@ -576,6 +589,12 @@ func (cl *CLMocker) ProduceSingleBlock(callbacks BlockProcessCallbacks) {
callbacks.OnPayloadProducerSelected()
}

cl.GeneratePayloadAttributes()

if callbacks.OnPayloadAttributesGenerated != nil {
callbacks.OnPayloadAttributesGenerated()
}

cl.RequestNextPayload()

cl.SetNextWithdrawals(nil)
Expand Down
9 changes: 8 additions & 1 deletion simulators/ethereum/engine/globals/globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,14 @@ func (f *ForkConfig) IsCancun(blockTimestamp uint64) bool {
return f.CancunTimestamp != nil && new(big.Int).SetUint64(blockTimestamp).Cmp(f.CancunTimestamp) >= 0
}

func (f *ForkConfig) ForkchoiceUpdatedVersion(timestamp uint64) int {
func (f *ForkConfig) ForkchoiceUpdatedVersion(headTimestamp uint64, payloadAttributesTimestamp *uint64) int {
// If the payload attributes timestamp is nil, use the head timestamp
// to calculate the FcU version.
timestamp := headTimestamp
if payloadAttributesTimestamp != nil {
timestamp = *payloadAttributesTimestamp
}

if f.IsCancun(timestamp) {
return 3
} else if f.IsShanghai(timestamp) {
Expand Down
Loading