@@ -2,6 +2,7 @@ package helper
22
33import (
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 ):
0 commit comments