diff --git a/simulators/ethereum/engine/enginetests.go b/simulators/ethereum/engine/enginetests.go index c29f9b6471..28e000c85f 100644 --- a/simulators/ethereum/engine/enginetests.go +++ b/simulators/ethereum/engine/enginetests.go @@ -183,44 +183,104 @@ var engineTests = []TestSpec{ Run: invalidPayloadTestCaseGen(RemoveTransaction, true, false), }, { - Name: "Invalid Transaction Signature NewPayload", - Run: invalidPayloadTestCaseGen(InvalidTransactionSignature, false, false), + Name: "Invalid Transaction Signature NewPayload", + Run: invalidPayloadTestCaseGen(InvalidTransactionSignature, false, false), + TestTransactionType: LegacyTxOnly, }, { - Name: "Invalid Transaction Signature NewPayload (Syncing)", - Run: invalidPayloadTestCaseGen(InvalidTransactionSignature, true, false), + Name: "Invalid Transaction Signature NewPayload (EIP-1559)", + Run: invalidPayloadTestCaseGen(InvalidTransactionSignature, false, false), + TestTransactionType: DynamicFeeTxOnly, }, { - Name: "Invalid Transaction Nonce NewPayload", - Run: invalidPayloadTestCaseGen(InvalidTransactionNonce, false, false), + Name: "Invalid Transaction Signature NewPayload (Syncing)", + Run: invalidPayloadTestCaseGen(InvalidTransactionSignature, true, false), + TestTransactionType: LegacyTxOnly, }, { - Name: "Invalid Transaction Nonce NewPayload (Syncing)", - Run: invalidPayloadTestCaseGen(InvalidTransactionNonce, true, false), + Name: "Invalid Transaction Nonce NewPayload", + Run: invalidPayloadTestCaseGen(InvalidTransactionNonce, false, false), + TestTransactionType: LegacyTxOnly, }, { - Name: "Invalid Transaction GasPrice NewPayload", - Run: invalidPayloadTestCaseGen(InvalidTransactionGasPrice, false, false), + Name: "Invalid Transaction Nonce NewPayload (EIP-1559)", + Run: invalidPayloadTestCaseGen(InvalidTransactionNonce, false, false), + TestTransactionType: DynamicFeeTxOnly, }, { - Name: "Invalid Transaction GasPrice NewPayload (Syncing)", - Run: invalidPayloadTestCaseGen(InvalidTransactionGasPrice, true, false), + Name: "Invalid Transaction Nonce NewPayload (Syncing)", + Run: invalidPayloadTestCaseGen(InvalidTransactionNonce, true, false), + TestTransactionType: LegacyTxOnly, }, { - Name: "Invalid Transaction Gas NewPayload", - Run: invalidPayloadTestCaseGen(InvalidTransactionGas, false, false), + Name: "Invalid Transaction GasPrice NewPayload", + Run: invalidPayloadTestCaseGen(InvalidTransactionGasPrice, false, false), + TestTransactionType: LegacyTxOnly, }, { - Name: "Invalid Transaction Gas NewPayload (Syncing)", - Run: invalidPayloadTestCaseGen(InvalidTransactionGas, true, false), + Name: "Invalid Transaction GasPrice NewPayload (EIP-1559)", + Run: invalidPayloadTestCaseGen(InvalidTransactionGasPrice, false, false), + TestTransactionType: DynamicFeeTxOnly, }, { - Name: "Invalid Transaction Value NewPayload", - Run: invalidPayloadTestCaseGen(InvalidTransactionValue, false, false), + Name: "Invalid Transaction GasPrice NewPayload (Syncing)", + Run: invalidPayloadTestCaseGen(InvalidTransactionGasPrice, true, false), + TestTransactionType: LegacyTxOnly, }, { - Name: "Invalid Transaction Value NewPayload (Syncing)", - Run: invalidPayloadTestCaseGen(InvalidTransactionValue, true, false), + Name: "Invalid Transaction Gas Tip NewPayload (EIP-1559)", + Run: invalidPayloadTestCaseGen(InvalidTransactionGasTipPrice, false, false), + TestTransactionType: DynamicFeeTxOnly, + }, + { + Name: "Invalid Transaction Gas Tip NewPayload (EIP-1559, Syncing)", + Run: invalidPayloadTestCaseGen(InvalidTransactionGasTipPrice, true, false), + TestTransactionType: DynamicFeeTxOnly, + }, + { + Name: "Invalid Transaction Gas NewPayload", + Run: invalidPayloadTestCaseGen(InvalidTransactionGas, false, false), + TestTransactionType: LegacyTxOnly, + }, + { + Name: "Invalid Transaction Gas NewPayload (EIP-1559)", + Run: invalidPayloadTestCaseGen(InvalidTransactionGas, false, false), + TestTransactionType: DynamicFeeTxOnly, + }, + { + Name: "Invalid Transaction Gas NewPayload (Syncing)", + Run: invalidPayloadTestCaseGen(InvalidTransactionGas, true, false), + TestTransactionType: LegacyTxOnly, + }, + { + Name: "Invalid Transaction Value NewPayload", + Run: invalidPayloadTestCaseGen(InvalidTransactionValue, false, false), + TestTransactionType: LegacyTxOnly, + }, + { + Name: "Invalid Transaction Value NewPayload (EIP-1559)", + Run: invalidPayloadTestCaseGen(InvalidTransactionValue, false, false), + TestTransactionType: DynamicFeeTxOnly, + }, + { + Name: "Invalid Transaction Value NewPayload (Syncing)", + Run: invalidPayloadTestCaseGen(InvalidTransactionValue, true, false), + TestTransactionType: LegacyTxOnly, + }, + { + Name: "Invalid Transaction ChainID NewPayload", + Run: invalidPayloadTestCaseGen(InvalidTransactionChainID, false, false), + TestTransactionType: LegacyTxOnly, + }, + { + Name: "Invalid Transaction ChainID NewPayload (EIP-1559)", + Run: invalidPayloadTestCaseGen(InvalidTransactionChainID, false, false), + TestTransactionType: DynamicFeeTxOnly, + }, + { + Name: "Invalid Transaction ChainID NewPayload (Syncing)", + Run: invalidPayloadTestCaseGen(InvalidTransactionChainID, true, false), + TestTransactionType: LegacyTxOnly, }, // Invalid Ancestor Re-Org Tests (Reveal via newPayload) @@ -393,6 +453,16 @@ var engineTests = []TestSpec{ Name: "Payload Build after New Invalid Payload", Run: payloadBuildAfterNewInvalidPayload, }, + { + Name: "Build Payload with Invalid ChainID Transaction (Legacy Tx)", + Run: buildPayloadWithInvalidChainIDTx, + TestTransactionType: LegacyTxOnly, + }, + { + Name: "Build Payload with Invalid ChainID Transaction (EIP-1559)", + Run: buildPayloadWithInvalidChainIDTx, + TestTransactionType: DynamicFeeTxOnly, + }, // Re-org using Engine API { @@ -428,15 +498,28 @@ var engineTests = []TestSpec{ // Suggested Fee Recipient in Payload creation { - Name: "Suggested Fee Recipient Test", - Run: suggestedFeeRecipient, + Name: "Suggested Fee Recipient Test", + Run: suggestedFeeRecipient, + TestTransactionType: LegacyTxOnly, + }, + { + Name: "Suggested Fee Recipient Test (EIP-1559 Transactions)", + Run: suggestedFeeRecipient, + TestTransactionType: DynamicFeeTxOnly, }, // PrevRandao opcode tests { - Name: "PrevRandao Opcode Transactions", - Run: prevRandaoOpcodeTx, - TTD: 10, + Name: "PrevRandao Opcode Transactions", + Run: prevRandaoOpcodeTx, + TTD: 10, + TestTransactionType: LegacyTxOnly, + }, + { + Name: "PrevRandao Opcode Transactions (EIP-1559 Transactions)", + Run: prevRandaoOpcodeTx, + TTD: 10, + TestTransactionType: DynamicFeeTxOnly, }, // Multi-Client Sync tests @@ -2349,6 +2432,49 @@ func payloadBuildAfterNewInvalidPayload(t *TestEnv) { }) } +// Send a valid `newPayload` in correct order but skip `forkchoiceUpdated` until the last payload +func buildPayloadWithInvalidChainIDTx(t *TestEnv) { + // Wait until TTD is reached by this client + t.CLMock.waitForTTD() + + // Produce blocks before starting the test + t.CLMock.produceBlocks(5, BlockProcessCallbacks{}) + + // Send a transaction with an incorrect ChainID. + // Transaction must be not be included in payload creation. + var invalidChainIDTx *types.Transaction + t.CLMock.produceSingleBlock(BlockProcessCallbacks{ + // Run test after a new payload has been broadcast + OnPayloadProducerSelected: func() { + txData := &types.LegacyTx{ + Nonce: t.nonce, + To: &prevRandaoContractAddr, + Value: big0, + Gas: 75000, + GasPrice: gasPrice, + Data: nil, + } + invalidChainID := new(big.Int).Set(chainID) + invalidChainID.Add(invalidChainID, big1) + invalidChainIDTx, err := types.SignTx(types.NewTx(txData), types.NewLondonSigner(invalidChainID), vaultKey) + if err != nil { + t.Fatalf("FAIL(%s): Unable to sign tx with invalid chain ID: %v", t.TestName, err) + } + err = t.Engine.Eth.SendTransaction(t.Engine.Ctx(), invalidChainIDTx) + if err != nil { + t.Logf("INFO (%s): Error on sending transaction with incorrect chain ID (Expected): %v", t.TestName, err) + } + }, + }) + + // Verify that the latest payload built does NOT contain the invalid chain Tx + if TransactionInPayload(&t.CLMock.LatestPayloadBuilt, invalidChainIDTx) { + p, _ := json.MarshalIndent(t.CLMock.LatestPayloadBuilt, "", " ") + t.Fatalf("FAIL (%s): Invalid chain ID tx was included in payload: %s", t.TestName, p) + } + +} + // Fee Recipient Tests func suggestedFeeRecipient(t *TestEnv) { // Wait until this client catches up with latest PoS diff --git a/simulators/ethereum/engine/helper.go b/simulators/ethereum/engine/helper.go index 211bd88f9e..f078270027 100644 --- a/simulators/ethereum/engine/helper.go +++ b/simulators/ethereum/engine/helper.go @@ -91,61 +91,127 @@ func SignatureValuesFromRaw(v *big.Int, r *big.Int, s *big.Int) SignatureValues } type CustomTransactionData struct { - Nonce *uint64 - GasPrice *big.Int - Gas *uint64 - To *common.Address - Value *big.Int - Data *[]byte - Signature *SignatureValues + Nonce *uint64 + GasPriceOrGasFeeCap *big.Int + GasTipCap *big.Int + Gas *uint64 + To *common.Address + Value *big.Int + Data *[]byte + ChainID *big.Int + Signature *SignatureValues } func customizeTransaction(baseTransaction *types.Transaction, pk *ecdsa.PrivateKey, customData *CustomTransactionData) (*types.Transaction, error) { // Create a modified transaction base, from the base transaction and customData mix - modifiedTxBase := &types.LegacyTx{} - - if customData.Nonce != nil { - modifiedTxBase.Nonce = *customData.Nonce - } else { - modifiedTxBase.Nonce = baseTransaction.Nonce() - } - if customData.GasPrice != nil { - modifiedTxBase.GasPrice = customData.GasPrice - } else { - modifiedTxBase.GasPrice = baseTransaction.GasPrice() - } - if customData.Gas != nil { - modifiedTxBase.Gas = *customData.Gas - } else { - modifiedTxBase.Gas = baseTransaction.Gas() - } - if customData.To != nil { - modifiedTxBase.To = customData.To - } else { - modifiedTxBase.To = baseTransaction.To() - } - if customData.Value != nil { - modifiedTxBase.Value = customData.Value - } else { - modifiedTxBase.Value = baseTransaction.Value() - } - if customData.Data != nil { - modifiedTxBase.Data = *customData.Data - } else { - modifiedTxBase.Data = baseTransaction.Data() - } - var modifiedTx *types.Transaction - if customData.Signature != nil { - modifiedTxBase.V = customData.Signature.V - modifiedTxBase.R = customData.Signature.R - modifiedTxBase.S = customData.Signature.S - modifiedTx = types.NewTx(modifiedTxBase) - } else { - // If a custom signature was not specified, simply sign the transaction again - signer := types.NewEIP155Signer(chainID) + var ( + modifiedTxData types.TxData + ) + + switch baseTransaction.Type() { + case types.LegacyTxType: + modifiedLegacyTxBase := &types.LegacyTx{} + + if customData.Nonce != nil { + modifiedLegacyTxBase.Nonce = *customData.Nonce + } else { + modifiedLegacyTxBase.Nonce = baseTransaction.Nonce() + } + if customData.GasPriceOrGasFeeCap != nil { + modifiedLegacyTxBase.GasPrice = customData.GasPriceOrGasFeeCap + } else { + modifiedLegacyTxBase.GasPrice = baseTransaction.GasPrice() + } + if customData.GasTipCap != nil { + return nil, fmt.Errorf("GasTipCap is not supported for LegacyTx type") + } + if customData.Gas != nil { + modifiedLegacyTxBase.Gas = *customData.Gas + } else { + modifiedLegacyTxBase.Gas = baseTransaction.Gas() + } + if customData.To != nil { + modifiedLegacyTxBase.To = customData.To + } else { + modifiedLegacyTxBase.To = baseTransaction.To() + } + if customData.Value != nil { + modifiedLegacyTxBase.Value = customData.Value + } else { + modifiedLegacyTxBase.Value = baseTransaction.Value() + } + if customData.Data != nil { + modifiedLegacyTxBase.Data = *customData.Data + } else { + modifiedLegacyTxBase.Data = baseTransaction.Data() + } + + if customData.Signature != nil { + modifiedLegacyTxBase.V = customData.Signature.V + modifiedLegacyTxBase.R = customData.Signature.R + modifiedLegacyTxBase.S = customData.Signature.S + } + + modifiedTxData = modifiedLegacyTxBase + + case types.DynamicFeeTxType: + modifiedDynamicFeeTxBase := &types.DynamicFeeTx{} + + if customData.Nonce != nil { + modifiedDynamicFeeTxBase.Nonce = *customData.Nonce + } else { + modifiedDynamicFeeTxBase.Nonce = baseTransaction.Nonce() + } + if customData.GasPriceOrGasFeeCap != nil { + modifiedDynamicFeeTxBase.GasFeeCap = customData.GasPriceOrGasFeeCap + } else { + modifiedDynamicFeeTxBase.GasFeeCap = baseTransaction.GasFeeCap() + } + if customData.GasTipCap != nil { + modifiedDynamicFeeTxBase.GasTipCap = customData.GasTipCap + } else { + modifiedDynamicFeeTxBase.GasTipCap = baseTransaction.GasTipCap() + } + if customData.Gas != nil { + modifiedDynamicFeeTxBase.Gas = *customData.Gas + } else { + modifiedDynamicFeeTxBase.Gas = baseTransaction.Gas() + } + if customData.To != nil { + modifiedDynamicFeeTxBase.To = customData.To + } else { + modifiedDynamicFeeTxBase.To = baseTransaction.To() + } + if customData.Value != nil { + modifiedDynamicFeeTxBase.Value = customData.Value + } else { + modifiedDynamicFeeTxBase.Value = baseTransaction.Value() + } + if customData.Data != nil { + modifiedDynamicFeeTxBase.Data = *customData.Data + } else { + modifiedDynamicFeeTxBase.Data = baseTransaction.Data() + } + if customData.Signature != nil { + modifiedDynamicFeeTxBase.V = customData.Signature.V + modifiedDynamicFeeTxBase.R = customData.Signature.R + modifiedDynamicFeeTxBase.S = customData.Signature.S + } + + modifiedTxData = modifiedDynamicFeeTxBase + + } + + modifiedTx := types.NewTx(modifiedTxData) + if customData.Signature == nil { + // If a custom invalid signature was not specified, simply sign the transaction again + if customData.ChainID == nil { + // Use the default value if an invaild chain ID was not specified + customData.ChainID = chainID + } + signer := types.NewLondonSigner(customData.ChainID) var err error - modifiedTx, err = types.SignTx(types.NewTx(modifiedTxBase), signer, pk) - if err != nil { + if modifiedTx, err = types.SignTx(modifiedTx, signer, pk); err != nil { return nil, err } } @@ -318,20 +384,22 @@ func (customData *CustomPayloadData) String() string { type InvalidPayloadField string const ( - InvalidParentHash InvalidPayloadField = "ParentHash" - InvalidStateRoot = "StateRoot" - InvalidReceiptsRoot = "ReceiptsRoot" - InvalidNumber = "Number" - InvalidGasLimit = "GasLimit" - InvalidGasUsed = "GasUsed" - InvalidTimestamp = "Timestamp" - InvalidPrevRandao = "PrevRandao" - RemoveTransaction = "Incomplete Transactions" - InvalidTransactionSignature = "Transaction Signature" - InvalidTransactionNonce = "Transaction Nonce" - InvalidTransactionGas = "Transaction Gas" - InvalidTransactionGasPrice = "Transaction GasPrice" - InvalidTransactionValue = "Transaction Value" + InvalidParentHash InvalidPayloadField = "ParentHash" + InvalidStateRoot = "StateRoot" + InvalidReceiptsRoot = "ReceiptsRoot" + InvalidNumber = "Number" + InvalidGasLimit = "GasLimit" + InvalidGasUsed = "GasUsed" + InvalidTimestamp = "Timestamp" + InvalidPrevRandao = "PrevRandao" + RemoveTransaction = "Incomplete Transactions" + InvalidTransactionSignature = "Transaction Signature" + InvalidTransactionNonce = "Transaction Nonce" + InvalidTransactionGas = "Transaction Gas" + InvalidTransactionGasPrice = "Transaction GasPrice" + InvalidTransactionGasTipPrice = "Transaction GasTipCapPrice" + InvalidTransactionValue = "Transaction Value" + InvalidTransactionChainID = "Transaction ChainID" ) // This function generates an invalid payload by taking a base payload and modifying the specified field such that it ends up being invalid. @@ -395,7 +463,9 @@ func generateInvalidPayload(basePayload *ExecutableDataV1, payloadField InvalidP InvalidTransactionNonce, InvalidTransactionGas, InvalidTransactionGasPrice, - InvalidTransactionValue: + InvalidTransactionGasTipPrice, + InvalidTransactionValue, + InvalidTransactionChainID: if len(basePayload.Transactions) == 0 { return nil, fmt.Errorf("No transactions available for modification") @@ -409,32 +479,26 @@ func generateInvalidPayload(basePayload *ExecutableDataV1, payloadField InvalidP case InvalidTransactionSignature: modifiedSignature := SignatureValuesFromRaw(baseTx.RawSignatureValues()) modifiedSignature.R = modifiedSignature.R.Sub(modifiedSignature.R, big1) - customTxData = CustomTransactionData{ - Signature: &modifiedSignature, - } + customTxData.Signature = &modifiedSignature case InvalidTransactionNonce: customNonce := baseTx.Nonce() - 1 - customTxData = CustomTransactionData{ - Nonce: &customNonce, - } + customTxData.Nonce = &customNonce case InvalidTransactionGas: customGas := uint64(0) - customTxData = CustomTransactionData{ - Gas: &customGas, - } + customTxData.Gas = &customGas case InvalidTransactionGasPrice: - customTxData = CustomTransactionData{ - GasPrice: big0, - } + customTxData.GasPriceOrGasFeeCap = big0 + case InvalidTransactionGasTipPrice: + invalidGasTip := new(big.Int).Set(gasTipPrice) + invalidGasTip.Mul(invalidGasTip, big.NewInt(2)) + customTxData.GasTipCap = invalidGasTip case InvalidTransactionValue: // Vault account initially has 0x123450000000000000000, so this value should overflow - customValue, err := hexutil.DecodeBig("0x123450000000000000001") - if err != nil { - return nil, err - } - customTxData = CustomTransactionData{ - Value: customValue, - } + customTxData.Value, _ = hexutil.DecodeBig("0x123450000000000000001") + case InvalidTransactionChainID: + customChainID := new(big.Int).Set(chainID) + customChainID.Add(customChainID, big1) + customTxData.ChainID = customChainID } modifiedTx, err := customizeTransaction(&baseTx, vaultKey, &customTxData) @@ -444,6 +508,7 @@ func generateInvalidPayload(basePayload *ExecutableDataV1, payloadField InvalidP modifiedTxBytes, err := modifiedTx.MarshalBinary() if err != nil { + return nil, err } modifiedTransactions := [][]byte{ modifiedTxBytes, diff --git a/simulators/ethereum/engine/main.go b/simulators/ethereum/engine/main.go index cde0c66f77..3d1bcd5571 100644 --- a/simulators/ethereum/engine/main.go +++ b/simulators/ethereum/engine/main.go @@ -12,9 +12,10 @@ import ( var ( // Test chain parameters - chainID = big.NewInt(7) - gasPrice = big.NewInt(30 * params.GWei) - networkID = big.NewInt(7) + chainID = big.NewInt(7) + gasPrice = big.NewInt(30 * params.GWei) + gasTipPrice = big.NewInt(1 * params.GWei) + networkID = big.NewInt(7) // Time between checks of a client reaching Terminal Total Difficulty tTDCheckPeriod = time.Second * 1 @@ -94,6 +95,9 @@ type TestSpec struct { // When used, clique consensus mechanism is disabled. // Default: None ChainFile string + + // Transaction type to use throughout the test + TestTransactionType TestTransactionType } func main() { @@ -165,7 +169,7 @@ func addTestsToSuite(suite *hivesim.Suite, tests []TestSpec) { timeout = time.Second * time.Duration(currentTest.TimeoutSeconds) } // Run the test case - RunTest(currentTest.Name, big.NewInt(ttd), currentTest.SlotsToSafe, currentTest.SlotsToFinalized, timeout, t, c, currentTest.Run, newParams, testFiles) + RunTest(currentTest.Name, big.NewInt(ttd), currentTest.SlotsToSafe, currentTest.SlotsToFinalized, timeout, t, c, currentTest.Run, newParams, testFiles, currentTest.TestTransactionType) }, }) } diff --git a/simulators/ethereum/engine/mergetests.go b/simulators/ethereum/engine/mergetests.go index 2471cb82d7..8fe9a0027f 100644 --- a/simulators/ethereum/engine/mergetests.go +++ b/simulators/ethereum/engine/mergetests.go @@ -442,7 +442,7 @@ func GenerateMergeTestSpec(mergeTestSpec MergeTestSpec) TestSpec { return } t.nonce = nonce - tx := t.makeNextTransaction(prevRandaoContractAddr, big0, nil) + tx := t.makeNextTransaction(&prevRandaoContractAddr, 75000, big0, nil) err = t.CLMock.NextBlockProducer.Eth.SendTransaction(t.CLMock.NextBlockProducer.Ctx(), tx) if err != nil { t.Logf("INFO (%s): Unable to send tx (address=%v): %v", t.TestName, vaultAccountAddr, err) diff --git a/simulators/ethereum/engine/testenv.go b/simulators/ethereum/engine/testenv.go index 23058569cd..b94c7da36b 100644 --- a/simulators/ethereum/engine/testenv.go +++ b/simulators/ethereum/engine/testenv.go @@ -23,6 +23,14 @@ var ( vaultKey, _ = crypto.HexToECDSA("63b508a03c3b5937ceb903af8b1b0c191012ef6eb7e9c3fb7afa94e5d214d376") ) +type TestTransactionType int + +const ( + UnspecifiedTransactionType TestTransactionType = iota + LegacyTxOnly + DynamicFeeTxOnly +) + // TestEnv is the environment of a single test. type TestEnv struct { *hivesim.T @@ -49,6 +57,9 @@ type TestEnv struct { // This tracks the account nonce of the vault account. nonce uint64 + // Sets the type of transactions to use during the test + TestTransactionType TestTransactionType + // This holds most recent context created by the Ctx method. // Every time Ctx is called, it creates a new context with the default // timeout and cancels the previous one. @@ -57,7 +68,7 @@ type TestEnv struct { syncCancel context.CancelFunc } -func RunTest(testName string, ttd *big.Int, slotsToSafe *big.Int, slotsToFinalized *big.Int, timeout time.Duration, t *hivesim.T, c *hivesim.Client, fn func(*TestEnv), cParams hivesim.Params, cFiles hivesim.Params) { +func RunTest(testName string, ttd *big.Int, slotsToSafe *big.Int, slotsToFinalized *big.Int, timeout time.Duration, t *hivesim.T, c *hivesim.Client, fn func(*TestEnv), cParams hivesim.Params, cFiles hivesim.Params, testTransactionType TestTransactionType) { // Setup the CL Mocker for this test clMocker := NewCLMocker(t, slotsToSafe, slotsToFinalized) // Defer closing all clients @@ -84,15 +95,16 @@ func RunTest(testName string, ttd *big.Int, slotsToSafe *big.Int, slotsToFinaliz rpcClient, _ := rpc.DialHTTPWithClient(fmt.Sprintf("http://%v:%v/", c.IP, EthPortHTTP), client) defer rpcClient.Close() env := &TestEnv{ - T: t, - TestName: testName, - Client: c, - RPC: rpcClient, - Eth: ethclient.NewClient(rpcClient), - Engine: ec, - CLMock: clMocker, - ClientParams: cParams, - ClientFiles: cFiles, + T: t, + TestName: testName, + Client: c, + RPC: rpcClient, + Eth: ethclient.NewClient(rpcClient), + Engine: ec, + CLMock: clMocker, + ClientParams: cParams, + ClientFiles: cFiles, + TestTransactionType: testTransactionType, } env.TestEngine = NewTestEngineClient(env, ec) env.TestEth = NewTestEthClient(env, env.Eth) @@ -176,22 +188,67 @@ func CheckEthEngineLive(c *hivesim.Client) error { return nil } -func (t *TestEnv) makeNextTransaction(recipient common.Address, amount *big.Int, payload []byte) *types.Transaction { +func (t *TestEnv) makeNextTransaction(recipient *common.Address, gasLimit uint64, amount *big.Int, payload []byte) *types.Transaction { + var ( + newTxData types.TxData + txType string + ) + var txTypeToUse int + switch t.TestTransactionType { + case UnspecifiedTransactionType: + // Test case has no specific type of transaction to use. + // Select the type of tx based on the nonce. + switch t.nonce % 2 { + case 0: + txTypeToUse = types.LegacyTxType + case 1: + txTypeToUse = types.DynamicFeeTxType + } + case LegacyTxOnly: + txTypeToUse = types.LegacyTxType + case DynamicFeeTxOnly: + txTypeToUse = types.DynamicFeeTxType + } - gasLimit := uint64(75000) - tx := types.NewTransaction(t.nonce, recipient, amount, gasLimit, gasPrice, payload) - signer := types.NewEIP155Signer(chainID) - signedTx, err := types.SignTx(tx, signer, vaultKey) + // Build the transaction depending on the specified type + switch txTypeToUse { + case types.LegacyTxType: + newTxData = &types.LegacyTx{ + Nonce: t.nonce, + To: recipient, + Value: amount, + Gas: gasLimit, + GasPrice: gasPrice, + Data: payload, + } + txType = "Legacy" + case types.DynamicFeeTxType: + gasFeeCap := new(big.Int).Set(gasPrice) + gasTipCap := new(big.Int).Set(gasTipPrice) + newTxData = &types.DynamicFeeTx{ + Nonce: t.nonce, + Gas: gasLimit, + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + To: recipient, + Value: amount, + Data: payload, + } + txType = "DynamicFeeTx" + } + + tx := types.NewTx(newTxData) + signedTx, err := types.SignTx(tx, types.NewLondonSigner(chainID), vaultKey) if err != nil { - t.Fatal("FAIL (%s): could not sign new tx: %v", t.TestName, err) + t.Fatalf("FAIL (%s): could not sign new tx: %v", t.TestName, err) } - t.Logf("INFO (%s): Built next transaction: hash=%s, nonce=%d, recipient=%s", t.TestName, signedTx.Hash(), t.nonce, recipient) + t.Logf("INFO (%s): Built next transaction: hash=%s, nonce=%d, recipient=%s, type=%s", t.TestName, signedTx.Hash(), t.nonce, recipient, txType) t.nonce++ return signedTx } func (t *TestEnv) sendNextTransaction(node *EngineClient, recipient common.Address, amount *big.Int, payload []byte) *types.Transaction { - tx := t.makeNextTransaction(recipient, amount, payload) + tx := t.makeNextTransaction(&recipient, 75000, amount, payload) for { err := node.Eth.SendTransaction(node.Ctx(), tx) if err == nil { @@ -226,18 +283,7 @@ func (t *TestEnv) makeNextBigContractTransaction(gasLimit uint64) *types.Transac initCode = append(initCode, 0x38) // CODESIZE == 0x00 initCode = append(initCode, 0xF3) // RETURN(offset, length) - txData := types.LegacyTx{ - Nonce: t.nonce, - GasPrice: gasPrice, - Gas: gasLimit, - To: nil, - Value: big0, - Data: initCode, - } - signer := types.NewEIP155Signer(chainID) - signedTx := types.MustSignNewTx(vaultKey, signer, &txData) - t.nonce++ - return signedTx + return t.makeNextTransaction(nil, gasLimit, big0, initCode) } func (t *TestEnv) sendNextBigContractTransaction(sender *EngineClient, gasLimit uint64) *types.Transaction {