Skip to content

Commit dd4f8a0

Browse files
fjlmarioevz
authored andcommitted
simulators/ethereum/engine: adding tests for Shanghai (ethereum#676)
* simulators/ethereum/engine: Withdrawals Sanity test * simulators/ethereum/engine: CLMock changes * simulators/ethereum/engine: Add timestamp global * simulators/ethereum/engine: Withdrawals required changes * simulators/ethereum/engine: Fix request payload * simulators/ethereum/engine: Withdrawals tests * simulators/ethereum/engine: Withdrawals tests update * simulators/ethereum/engine: Test spec interface * simulators/ethereum/engine: Add withdrawals test cases * simulators/ethereum/engine: Withdraw many accounts fix * simulators/ethereum/engine: Withdrawals sync tests * simulators/ethereum/engine: Withdrawals re-org * simulators/ethereum/engine: More withdrawals tests * simulators/ethereum/engine: Variable timestamp increments on CLMock * simulators/ethereum/engine: Withdrawals reorg changes * simulators/ethereum/engine: withdrawals reorg tests * simulators/ethereum/engine: Add LVH check * simulators/ethereum/engine: Dynamic genesis * simulators/ethereum/engine: Fix HTTP Transport usage * simulators/ethereum/engine: Roundtrip change * simulator/ethereum/engine: Add txs to withdrawal tests * simulators/ethereum/engine: Decrease withdrawals count * simulators/ethereum/engine: Withdrawals test change * simulators/ethereum/engine: Withdrawals, comments * simulators/ethereum/engine: fix lvh in withdrawals * simulators/ethereum/engine: go mod tidy * simulators/ethereum/engine: Fix lvh check on genesis * simulators/ethereum/engine: Fix long sync test * simulators/ethereum/engine: Fix sync tests take 2 * simulators/ethereum/engine: Add blockValue to getPayload * simulators/ethereum/engine: withdrawals, wei to gwei * simulators/ethereum/engine: fix genesis block * simulators/ethereum/engine: implement error code expect check * simulators/ethereum/engine: withdrawals, expect errors on invalid version * simulators/ethereum/engine: Withdrawals readme * simulators/ethereum/engine: update withdrawals readme * simulators/ethereum/engine: update test parameter, description * simulators/ethereum/engine: update branch * simulators/ethereum/engine: Support querying txs from client * simulators/ethereum/engine: Add eip 3860 invalid tx test * simulators/ethereum/engine: fix gaslimit everywhere Co-authored-by: marioevz <marioevz@gmail.com>
1 parent 07c9174 commit dd4f8a0

File tree

21 files changed

+2799
-392
lines changed

21 files changed

+2799
-392
lines changed

simulators/ethereum/engine/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,4 +455,7 @@ Invalid token error is expected.
455455

456456
- Positive time drift, within limit, correct secret:
457457
Engine API call where the `iat` claim contains a positive time drift smaller than the maximum threshold, and the secret to calculate the token is correct.
458-
No error is expected.
458+
No error is expected.
459+
460+
## Engine API Shanghai Upgrade Tests:
461+
See [withdrawals](suites/withdrawals/README.md).

simulators/ethereum/engine/client/engine.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"math/big"
66

7+
"github.com/ethereum/go-ethereum/core"
78
api "github.com/ethereum/go-ethereum/core/beacon"
89
"github.com/ethereum/hive/hivesim"
910

@@ -21,15 +22,20 @@ type Eth interface {
2122
StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error)
2223
TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
2324
NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error)
25+
TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error)
2426
}
2527

2628
type Engine interface {
27-
ForkchoiceUpdatedV1(ctx context.Context, fcState *api.ForkchoiceStateV1, pAttributes *api.PayloadAttributesV1) (api.ForkChoiceResponse, error)
28-
GetPayloadV1(ctx context.Context, payloadId *api.PayloadID) (api.ExecutableDataV1, error)
29-
NewPayloadV1(ctx context.Context, payload *api.ExecutableDataV1) (api.PayloadStatusV1, error)
29+
ForkchoiceUpdatedV1(ctx context.Context, fcState *api.ForkchoiceStateV1, pAttributes *api.PayloadAttributes) (api.ForkChoiceResponse, error)
30+
ForkchoiceUpdatedV2(ctx context.Context, fcState *api.ForkchoiceStateV1, pAttributes *api.PayloadAttributes) (api.ForkChoiceResponse, error)
3031

31-
LatestForkchoiceSent() (fcState *api.ForkchoiceStateV1, pAttributes *api.PayloadAttributesV1)
32-
LatestNewPayloadSent() (payload *api.ExecutableDataV1)
32+
GetPayloadV1(ctx context.Context, payloadId *api.PayloadID) (api.ExecutableData, error)
33+
GetPayloadV2(ctx context.Context, payloadId *api.PayloadID) (api.ExecutableData, *big.Int, error)
34+
NewPayloadV1(ctx context.Context, payload *api.ExecutableData) (api.PayloadStatusV1, error)
35+
NewPayloadV2(ctx context.Context, payload *api.ExecutableData) (api.PayloadStatusV1, error)
36+
37+
LatestForkchoiceSent() (fcState *api.ForkchoiceStateV1, pAttributes *api.PayloadAttributes)
38+
LatestNewPayloadSent() (payload *api.ExecutableData)
3339

3440
LatestForkchoiceResponse() (fcuResponse *api.ForkChoiceResponse)
3541
LatestNewPayloadResponse() (payloadResponse *api.PayloadStatusV1)
@@ -57,7 +63,7 @@ type EngineClient interface {
5763
}
5864

5965
type EngineStarter interface {
60-
StartClient(T *hivesim.T, testContext context.Context, ClientParams hivesim.Params, ClientFiles hivesim.Params, bootClients ...EngineClient) (EngineClient, error)
66+
StartClient(T *hivesim.T, testContext context.Context, genesis *core.Genesis, ClientParams hivesim.Params, ClientFiles hivesim.Params, bootClients ...EngineClient) (EngineClient, error)
6167
}
6268

6369
var (

simulators/ethereum/engine/client/hive_rpc/hive_rpc.go

Lines changed: 87 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/ethereum/go-ethereum"
1414
"github.com/ethereum/go-ethereum/common"
1515
"github.com/ethereum/go-ethereum/common/hexutil"
16+
"github.com/ethereum/go-ethereum/core"
1617
api "github.com/ethereum/go-ethereum/core/beacon"
1718
"github.com/ethereum/go-ethereum/core/types"
1819
"github.com/ethereum/go-ethereum/ethclient"
@@ -34,7 +35,7 @@ type HiveRPCEngineStarter struct {
3435
JWTSecret []byte
3536
}
3637

37-
func (s HiveRPCEngineStarter) StartClient(T *hivesim.T, testContext context.Context, ClientParams hivesim.Params, ClientFiles hivesim.Params, bootClients ...client.EngineClient) (client.EngineClient, error) {
38+
func (s HiveRPCEngineStarter) StartClient(T *hivesim.T, testContext context.Context, genesis *core.Genesis, ClientParams hivesim.Params, ClientFiles hivesim.Params, bootClients ...client.EngineClient) (client.EngineClient, error) {
3839
var (
3940
clientType = s.ClientType
4041
enginePort = s.EnginePort
@@ -45,10 +46,10 @@ func (s HiveRPCEngineStarter) StartClient(T *hivesim.T, testContext context.Cont
4546
if clientType == "" {
4647
cs, err := T.Sim.ClientTypes()
4748
if err != nil {
48-
return nil, fmt.Errorf("Client type was not supplied and simulator returned error on trying to get all client types: %v", err)
49+
return nil, fmt.Errorf("client type was not supplied and simulator returned error on trying to get all client types: %v", err)
4950
}
50-
if cs == nil || len(cs) == 0 {
51-
return nil, fmt.Errorf("Client type was not supplied and simulator returned empty client types: %v", cs)
51+
if len(cs) == 0 {
52+
return nil, fmt.Errorf("client type was not supplied and simulator returned empty client types: %v", cs)
5253
}
5354
clientType = cs[0].Name
5455
}
@@ -64,47 +65,48 @@ func (s HiveRPCEngineStarter) StartClient(T *hivesim.T, testContext context.Cont
6465
if s.ChainFile != "" {
6566
ClientFiles = ClientFiles.Set("/chain.rlp", "./chains/"+s.ChainFile)
6667
}
67-
if _, ok := ClientFiles["/genesis.json"]; !ok {
68-
return nil, fmt.Errorf("Cannot start without genesis file")
69-
}
7068
if ttd == nil {
7169
if ttdStr, ok := ClientParams["HIVE_TERMINAL_TOTAL_DIFFICULTY"]; ok {
7270
// Retrieve TTD from parameters
7371
ttd, ok = new(big.Int).SetString(ttdStr, 10)
7472
if !ok {
75-
return nil, fmt.Errorf("Unable to parse TTD from parameters")
73+
return nil, fmt.Errorf("unable to parse TTD from parameters")
7674
}
7775
}
7876
} else {
7977
// Real TTD must be calculated adding the genesis difficulty
80-
ttdInt := helper.CalculateRealTTD(ClientFiles["/genesis.json"], ttd.Int64())
78+
ttdInt := helper.CalculateRealTTD(genesis, ttd.Int64())
8179
ClientParams = ClientParams.Set("HIVE_TERMINAL_TOTAL_DIFFICULTY", fmt.Sprintf("%d", ttdInt))
8280
ttd = big.NewInt(ttdInt)
8381
}
84-
if bootClients != nil && len(bootClients) > 0 {
82+
if len(bootClients) > 0 {
8583
var (
8684
enodes = make([]string, len(bootClients))
8785
err error
8886
)
8987
for i, bootClient := range bootClients {
9088
enodes[i], err = bootClient.EnodeURL()
9189
if err != nil {
92-
return nil, fmt.Errorf("Unable to obtain bootnode: %v", err)
90+
return nil, fmt.Errorf("unable to obtain bootnode: %v", err)
9391
}
9492
}
9593
enodeString := strings.Join(enodes, ",")
9694
ClientParams = ClientParams.Set("HIVE_BOOTNODE", enodeString)
9795
}
9896

9997
// Start the client and create the engine client object
100-
c := T.StartClient(clientType, ClientParams, hivesim.WithStaticFiles(ClientFiles))
98+
genesisStart, err := helper.GenesisStartOption(genesis)
99+
if err != nil {
100+
return nil, err
101+
}
102+
c := T.StartClient(clientType, genesisStart, ClientParams, hivesim.WithStaticFiles(ClientFiles))
101103
if err := CheckEthEngineLive(c); err != nil {
102104
return nil, fmt.Errorf("Engine/Eth ports were never open for client: %v", err)
103105
}
104106
ec := NewHiveRPCEngineClient(c, enginePort, ethPort, jwtSecret, ttd, &helper.LoggingRoundTrip{
105-
T: T,
106-
Hc: c,
107-
Inner: http.DefaultTransport,
107+
Logger: T,
108+
ID: c.Container,
109+
Inner: http.DefaultTransport,
108110
})
109111
return ec, nil
110112
}
@@ -152,10 +154,10 @@ type HiveRPCEngineClient struct {
152154

153155
// Engine updates info
154156
latestFcUStateSent *api.ForkchoiceStateV1
155-
latestPAttrSent *api.PayloadAttributesV1
157+
latestPAttrSent *api.PayloadAttributes
156158
latestFcUResponse *api.ForkChoiceResponse
157159

158-
latestPayloadSent *api.ExecutableDataV1
160+
latestPayloadSent *api.ExecutableData
159161
latestPayloadStatusReponse *api.PayloadStatusV1
160162

161163
// Test account nonces
@@ -164,23 +166,25 @@ type HiveRPCEngineClient struct {
164166

165167
// NewClient creates a engine client that uses the given RPC client.
166168
func NewHiveRPCEngineClient(h *hivesim.Client, enginePort int, ethPort int, jwtSecretBytes []byte, ttd *big.Int, transport http.RoundTripper) *HiveRPCEngineClient {
167-
client := &http.Client{
168-
Transport: transport,
169-
}
170169
// Prepare HTTP Client
171-
rpcHttpClient, _ := rpc.DialHTTPWithClient(fmt.Sprintf("http://%s:%d/", h.IP, enginePort), client)
170+
httpClient := rpc.WithHTTPClient(&http.Client{Transport: transport})
171+
172+
engineRpcClient, err := rpc.DialOptions(context.Background(), fmt.Sprintf("http://%s:%d/", h.IP, enginePort), httpClient)
173+
if err != nil {
174+
panic(err)
175+
}
172176

173177
// Prepare ETH Client
174-
client = &http.Client{
175-
Transport: transport,
178+
ethRpcClient, err := rpc.DialOptions(context.Background(), fmt.Sprintf("http://%s:%d/", h.IP, ethPort), httpClient)
179+
if err != nil {
180+
panic(err)
176181
}
177-
rpcClient, _ := rpc.DialHTTPWithClient(fmt.Sprintf("http://%s:%d/", h.IP, ethPort), client)
178-
eth := ethclient.NewClient(rpcClient)
182+
eth := ethclient.NewClient(ethRpcClient)
179183
return &HiveRPCEngineClient{
180184
h: h,
181-
c: rpcHttpClient,
185+
c: engineRpcClient,
182186
Client: eth,
183-
cEth: rpcClient,
187+
cEth: ethRpcClient,
184188
ttd: ttd,
185189
JWTSecretBytes: jwtSecretBytes,
186190
accTxInfoMap: make(map[common.Address]*AccountTransactionInfo),
@@ -293,38 +297,82 @@ func (ec *HiveRPCEngineClient) PrepareDefaultAuthCallToken() error {
293297
}
294298

295299
// Engine API Call Methods
296-
func (ec *HiveRPCEngineClient) ForkchoiceUpdatedV1(ctx context.Context, fcState *api.ForkchoiceStateV1, pAttributes *api.PayloadAttributesV1) (api.ForkChoiceResponse, error) {
300+
func (ec *HiveRPCEngineClient) ForkchoiceUpdated(ctx context.Context, version int, fcState *api.ForkchoiceStateV1, pAttributes *api.PayloadAttributes) (api.ForkChoiceResponse, error) {
297301
var result api.ForkChoiceResponse
298302
if err := ec.PrepareDefaultAuthCallToken(); err != nil {
299303
return result, err
300304
}
301305
ec.latestFcUStateSent = fcState
302306
ec.latestPAttrSent = pAttributes
303-
err := ec.c.CallContext(ctx, &result, "engine_forkchoiceUpdatedV1", fcState, pAttributes)
307+
err := ec.c.CallContext(ctx,
308+
&result,
309+
fmt.Sprintf("engine_forkchoiceUpdatedV%d", version),
310+
fcState,
311+
pAttributes)
304312
ec.latestFcUResponse = &result
305313
return result, err
306314
}
307315

308-
func (ec *HiveRPCEngineClient) GetPayloadV1(ctx context.Context, payloadId *api.PayloadID) (api.ExecutableDataV1, error) {
309-
var result api.ExecutableDataV1
310-
if err := ec.PrepareDefaultAuthCallToken(); err != nil {
311-
return result, err
316+
func (ec *HiveRPCEngineClient) ForkchoiceUpdatedV1(ctx context.Context, fcState *api.ForkchoiceStateV1, pAttributes *api.PayloadAttributes) (api.ForkChoiceResponse, error) {
317+
return ec.ForkchoiceUpdated(ctx, 1, fcState, pAttributes)
318+
}
319+
320+
func (ec *HiveRPCEngineClient) ForkchoiceUpdatedV2(ctx context.Context, fcState *api.ForkchoiceStateV1, pAttributes *api.PayloadAttributes) (api.ForkChoiceResponse, error) {
321+
return ec.ForkchoiceUpdated(ctx, 2, fcState, pAttributes)
322+
}
323+
324+
func (ec *HiveRPCEngineClient) GetPayload(ctx context.Context, version int, payloadId *api.PayloadID) (api.ExecutableData, *big.Int, error) {
325+
var (
326+
executableData api.ExecutableData
327+
blockValue *big.Int
328+
err error
329+
rpcString = fmt.Sprintf("engine_getPayloadV%d", version)
330+
)
331+
332+
if err = ec.PrepareDefaultAuthCallToken(); err != nil {
333+
return executableData, nil, err
312334
}
313-
err := ec.c.CallContext(ctx, &result, "engine_getPayloadV1", payloadId)
314-
return result, err
335+
336+
if version == 2 {
337+
var response api.ExecutableDataV2
338+
err = ec.c.CallContext(ctx, &response, rpcString, payloadId)
339+
executableData = *response.ExecutionPayload
340+
blockValue = response.BlockValue
341+
} else {
342+
err = ec.c.CallContext(ctx, &executableData, rpcString, payloadId)
343+
}
344+
345+
return executableData, blockValue, err
315346
}
316347

317-
func (ec *HiveRPCEngineClient) NewPayloadV1(ctx context.Context, payload *api.ExecutableDataV1) (api.PayloadStatusV1, error) {
348+
func (ec *HiveRPCEngineClient) GetPayloadV1(ctx context.Context, payloadId *api.PayloadID) (api.ExecutableData, error) {
349+
ed, _, err := ec.GetPayload(ctx, 1, payloadId)
350+
return ed, err
351+
}
352+
353+
func (ec *HiveRPCEngineClient) GetPayloadV2(ctx context.Context, payloadId *api.PayloadID) (api.ExecutableData, *big.Int, error) {
354+
return ec.GetPayload(ctx, 2, payloadId)
355+
}
356+
357+
func (ec *HiveRPCEngineClient) NewPayload(ctx context.Context, version int, payload *api.ExecutableData) (api.PayloadStatusV1, error) {
318358
var result api.PayloadStatusV1
319359
if err := ec.PrepareDefaultAuthCallToken(); err != nil {
320360
return result, err
321361
}
322362
ec.latestPayloadSent = payload
323-
err := ec.c.CallContext(ctx, &result, "engine_newPayloadV1", payload)
363+
err := ec.c.CallContext(ctx, &result, fmt.Sprintf("engine_newPayloadV%d", version), payload)
324364
ec.latestPayloadStatusReponse = &result
325365
return result, err
326366
}
327367

368+
func (ec *HiveRPCEngineClient) NewPayloadV1(ctx context.Context, payload *api.ExecutableData) (api.PayloadStatusV1, error) {
369+
return ec.NewPayload(ctx, 1, payload)
370+
}
371+
372+
func (ec *HiveRPCEngineClient) NewPayloadV2(ctx context.Context, payload *api.ExecutableData) (api.PayloadStatusV1, error) {
373+
return ec.NewPayload(ctx, 2, payload)
374+
}
375+
328376
func (ec *HiveRPCEngineClient) ExchangeTransitionConfigurationV1(ctx context.Context, tConf *api.TransitionConfigurationV1) (api.TransitionConfigurationV1, error) {
329377
var result api.TransitionConfigurationV1
330378
err := ec.c.CallContext(ctx, &result, "engine_exchangeTransitionConfigurationV1", tConf)
@@ -366,11 +414,11 @@ func (ec *HiveRPCEngineClient) PostRunVerifications() error {
366414
return nil
367415
}
368416

369-
func (ec *HiveRPCEngineClient) LatestForkchoiceSent() (fcState *api.ForkchoiceStateV1, pAttributes *api.PayloadAttributesV1) {
417+
func (ec *HiveRPCEngineClient) LatestForkchoiceSent() (fcState *api.ForkchoiceStateV1, pAttributes *api.PayloadAttributes) {
370418
return ec.latestFcUStateSent, ec.latestPAttrSent
371419
}
372420

373-
func (ec *HiveRPCEngineClient) LatestNewPayloadSent() *api.ExecutableDataV1 {
421+
func (ec *HiveRPCEngineClient) LatestNewPayloadSent() *api.ExecutableData {
374422
return ec.latestPayloadSent
375423
}
376424

0 commit comments

Comments
 (0)