Skip to content

Commit 0426639

Browse files
marioevzfjl
authored andcommitted
simulators/ethereum/engine: Add eip 3860 invalid tx test
1 parent 30ad1a2 commit 0426639

File tree

6 files changed

+394
-72
lines changed

6 files changed

+394
-72
lines changed

simulators/ethereum/engine/helper/helper.go

Lines changed: 87 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package helper
22

33
import (
44
"context"
5+
"crypto/ecdsa"
56
"strings"
67
"sync"
78
"time"
@@ -337,11 +338,24 @@ const (
337338
DynamicFeeTxOnly
338339
)
339340

340-
func MakeTransaction(nonce uint64, recipient *common.Address, gasLimit uint64, amount *big.Int, payload []byte, txType TestTransactionType) (*types.Transaction, error) {
341+
type TransactionCreator interface {
342+
MakeTransaction(nonce uint64) (*types.Transaction, error)
343+
}
344+
345+
type BaseTransactionCreator struct {
346+
Recipient *common.Address
347+
GasLimit uint64
348+
Amount *big.Int
349+
Payload []byte
350+
TxType TestTransactionType
351+
PrivateKey *ecdsa.PrivateKey
352+
}
353+
354+
func (tc *BaseTransactionCreator) MakeTransaction(nonce uint64) (*types.Transaction, error) {
341355
var newTxData types.TxData
342356

343357
var txTypeToUse int
344-
switch txType {
358+
switch tc.TxType {
345359
case UnspecifiedTransactionType:
346360
// Test case has no specific type of transaction to use.
347361
// Select the type of tx based on the nonce.
@@ -362,73 +376,48 @@ func MakeTransaction(nonce uint64, recipient *common.Address, gasLimit uint64, a
362376
case types.LegacyTxType:
363377
newTxData = &types.LegacyTx{
364378
Nonce: nonce,
365-
To: recipient,
366-
Value: amount,
367-
Gas: gasLimit,
379+
To: tc.Recipient,
380+
Value: tc.Amount,
381+
Gas: tc.GasLimit,
368382
GasPrice: globals.GasPrice,
369-
Data: payload,
383+
Data: tc.Payload,
370384
}
371385
case types.DynamicFeeTxType:
372386
gasFeeCap := new(big.Int).Set(globals.GasPrice)
373387
gasTipCap := new(big.Int).Set(globals.GasTipPrice)
374388
newTxData = &types.DynamicFeeTx{
375389
Nonce: nonce,
376-
Gas: gasLimit,
390+
Gas: tc.GasLimit,
377391
GasTipCap: gasTipCap,
378392
GasFeeCap: gasFeeCap,
379-
To: recipient,
380-
Value: amount,
381-
Data: payload,
393+
To: tc.Recipient,
394+
Value: tc.Amount,
395+
Data: tc.Payload,
382396
}
383397
}
384398

385399
tx := types.NewTx(newTxData)
386-
signedTx, err := types.SignTx(tx, types.NewLondonSigner(globals.ChainID), globals.VaultKey)
400+
key := tc.PrivateKey
401+
if key == nil {
402+
key = globals.VaultKey
403+
}
404+
signedTx, err := types.SignTx(tx, types.NewLondonSigner(globals.ChainID), key)
387405
if err != nil {
388406
return nil, err
389407
}
390408
return signedTx, nil
391409
}
392410

393-
// Determines if the error we got from sending the raw tx is because the client
394-
// already knew the tx (might happen if we produced a re-org where the tx was
395-
// unwind back into the txpool)
396-
func SentTxAlreadyKnown(err error) bool {
397-
return strings.Contains(err.Error(), "already known")
398-
}
399-
400-
func SendNextTransaction(testCtx context.Context, node client.EngineClient, recipient common.Address, amount *big.Int, payload []byte, txType TestTransactionType) (*types.Transaction, error) {
401-
nonce, err := node.GetNextAccountNonce(testCtx, globals.VaultAccountAddress)
402-
if err != nil {
403-
return nil, err
404-
}
405-
tx, err := MakeTransaction(nonce, &recipient, 75000, amount, payload, txType)
406-
if err != nil {
407-
return nil, err
408-
}
409-
for {
410-
ctx, cancel := context.WithTimeout(testCtx, globals.RPCTimeout)
411-
defer cancel()
412-
err := node.SendTransaction(ctx, tx)
413-
if err == nil {
414-
return tx, nil
415-
} else if SentTxAlreadyKnown(err) {
416-
return tx, nil
417-
}
418-
select {
419-
case <-time.After(time.Second):
420-
case <-testCtx.Done():
421-
return nil, testCtx.Err()
422-
}
423-
}
411+
// Create a contract filled with zeros without going over the specified GasLimit
412+
type BigContractTransactionCreator struct {
413+
BaseTransactionCreator
424414
}
425415

426-
// Method that attempts to create a contract filled with zeros without going over the specified gasLimit
427-
func MakeBigContractTransaction(nonce uint64, gasLimit uint64, txType TestTransactionType) (*types.Transaction, error) {
416+
func (tc *BigContractTransactionCreator) MakeTransaction(nonce uint64) (*types.Transaction, error) {
428417
// Total GAS: Gtransaction == 21000, Gcreate == 32000, Gcodedeposit == 200
429418
contractLength := uint64(0)
430-
if gasLimit > (21000 + 32000) {
431-
contractLength = (gasLimit - 21000 - 32000) / 200
419+
if tc.GasLimit > (21000 + 32000) {
420+
contractLength = (tc.GasLimit - 21000 - 32000) / 200
432421
if contractLength >= 1 {
433422
// Reduce by 1 to guarantee using less gas than requested
434423
contractLength -= 1
@@ -437,22 +426,65 @@ func MakeBigContractTransaction(nonce uint64, gasLimit uint64, txType TestTransa
437426
buf := make([]byte, 8)
438427
binary.BigEndian.PutUint64(buf, contractLength)
439428

440-
initCode := []byte{
429+
tc.Payload = []byte{
441430
0x67, // PUSH8
442431
}
443-
initCode = append(initCode, buf...) // Size of the contract in byte length
444-
initCode = append(initCode, 0x38) // CODESIZE == 0x00
445-
initCode = append(initCode, 0xF3) // RETURN(offset, length)
432+
tc.Payload = append(tc.Payload, buf...) // Size of the contract in byte length
433+
tc.Payload = append(tc.Payload, 0x38) // CODESIZE == 0x00
434+
tc.Payload = append(tc.Payload, 0xF3) // RETURN(offset, length)
435+
if tc.Recipient != nil {
436+
panic("invalid configuration for big contract tx creator")
437+
}
438+
return tc.BaseTransactionCreator.MakeTransaction(nonce)
439+
}
446440

447-
return MakeTransaction(nonce, nil, gasLimit, common.Big0, initCode, txType)
441+
// Create a tx with the specified initcode length (all zeros)
442+
type BigInitcodeTransactionCreator struct {
443+
BaseTransactionCreator
444+
InitcodeLength int
445+
PadByte uint8
446+
Initcode []byte
448447
}
449448

450-
func SendNextBigContractTransaction(testCtx context.Context, node client.EngineClient, gasLimit uint64, txType TestTransactionType) (*types.Transaction, error) {
449+
func (tc *BigInitcodeTransactionCreator) MakeTransaction(nonce uint64) (*types.Transaction, error) {
450+
// This method caches the payload with the crafted initcode after first execution.
451+
if tc.Payload == nil {
452+
// Prepare initcode payload
453+
if tc.Initcode != nil {
454+
if len(tc.Initcode) > tc.InitcodeLength {
455+
panic(fmt.Errorf("invalid initcode (too big)"))
456+
}
457+
tc.Payload = tc.Initcode
458+
} else {
459+
tc.Payload = []byte{}
460+
}
461+
462+
for {
463+
if len(tc.Payload) == tc.InitcodeLength {
464+
break
465+
}
466+
tc.Payload = append(tc.Payload, tc.PadByte)
467+
}
468+
}
469+
if tc.Recipient != nil {
470+
panic("invalid configuration for big contract tx creator")
471+
}
472+
return tc.BaseTransactionCreator.MakeTransaction(nonce)
473+
}
474+
475+
// Determines if the error we got from sending the raw tx is because the client
476+
// already knew the tx (might happen if we produced a re-org where the tx was
477+
// unwind back into the txpool)
478+
func SentTxAlreadyKnown(err error) bool {
479+
return strings.Contains(err.Error(), "already known")
480+
}
481+
482+
func SendNextTransaction(testCtx context.Context, node client.EngineClient, txCreator TransactionCreator) (*types.Transaction, error) {
451483
nonce, err := node.GetNextAccountNonce(testCtx, globals.VaultAccountAddress)
452484
if err != nil {
453485
return nil, err
454486
}
455-
tx, err := MakeBigContractTransaction(nonce, gasLimit, txType)
487+
tx, err := txCreator.MakeTransaction(nonce)
456488
if err != nil {
457489
return nil, err
458490
}
@@ -462,6 +494,8 @@ func SendNextBigContractTransaction(testCtx context.Context, node client.EngineC
462494
err := node.SendTransaction(ctx, tx)
463495
if err == nil {
464496
return tx, nil
497+
} else if SentTxAlreadyKnown(err) {
498+
return tx, nil
465499
}
466500
select {
467501
case <-time.After(time.Second):

simulators/ethereum/engine/helper/payload.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,20 @@ func CustomizePayload(basePayload *api.ExecutableData, customData *CustomPayload
133133
return result, nil
134134
}
135135

136+
func CustomizePayloadTransactions(basePayload *api.ExecutableData, customTransactions types.Transactions) (*api.ExecutableData, error) {
137+
byteTxs := make([][]byte, 0)
138+
for _, tx := range customTransactions {
139+
bytes, err := tx.MarshalBinary()
140+
if err != nil {
141+
return nil, err
142+
}
143+
byteTxs = append(byteTxs, bytes)
144+
}
145+
return CustomizePayload(basePayload, &CustomPayloadData{
146+
Transactions: &byteTxs,
147+
})
148+
}
149+
136150
func (customData *CustomPayloadData) String() string {
137151
customFieldsList := make([]string, 0)
138152
if customData.ParentHash != nil {

0 commit comments

Comments
 (0)