From ca993c54d9ae4ef8a63e0d345fed4c70cb3e3821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Nosovi=C4=87?= <118283942+dusannosovic-ethernal@users.noreply.github.com> Date: Fri, 23 Feb 2024 12:10:10 +0100 Subject: [PATCH] Mixed transaction to different types of transactions (#102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Mixed transaction to different types of transactions * Ut fix * Fix for e2e test and deleted mixed_tx.go * legacy test fix * better code * lint fix * lint * comment fix * test fix * test and lint fix * Simplify 1 ETH constant * comment fix * Fix tests * Lint fix * Instantiate correct tx data * Rebase fix * Fix failing tests * Comment fix --------- Co-authored-by: Stefan Negovanović Co-authored-by: Goran Rojovic --- blockchain/blockchain.go | 4 +- blockchain/blockchain_test.go | 53 ++- blockchain/storage/leveldb/leveldb_test.go | 6 +- blockchain/storage/testing.go | 6 +- consensus/polybft/block_builder_test.go | 2 +- consensus/polybft/fsm.go | 5 +- consensus/polybft/fsm_test.go | 3 +- consensus/polybft/polybft.go | 2 +- consensus/polybft/state_sync_commitment.go | 2 +- crypto/txsigner.go | 6 +- crypto/txsigner_eip155_test.go | 4 +- crypto/txsigner_frontier_test.go | 2 +- crypto/txsigner_london_berlin.go | 4 +- crypto/txsigner_london_berlin_test.go | 37 +- e2e/framework/testserver.go | 2 +- e2e/txpool_test.go | 36 +- gasprice/feehistory_test.go | 4 +- gasprice/gasprice_test.go | 6 +- helper/tests/testing.go | 2 +- jsonrpc/debug_endpoint_test.go | 4 +- jsonrpc/dispatcher_test.go | 6 +- jsonrpc/eth_blockchain_test.go | 2 +- jsonrpc/eth_endpoint.go | 2 +- jsonrpc/eth_endpoint_test.go | 83 ++-- jsonrpc/eth_txpool_test.go | 4 +- jsonrpc/filter_manager_fuzz_test.go | 6 +- jsonrpc/filter_manager_test.go | 6 +- jsonrpc/helper.go | 28 +- jsonrpc/helper_test.go | 80 ++-- jsonrpc/txpool_endpoint_test.go | 21 +- jsonrpc/types.go | 6 +- jsonrpc/types_test.go | 12 +- state/executor.go | 10 +- state/executor_test.go | 12 +- state/transition_test.go | 2 +- tests/state_test_util.go | 55 ++- txpool/queue_priced_test.go | 105 ++--- txpool/txpool.go | 10 +- txpool/txpool_test.go | 509 +++++++++++---------- types/access_list_tx.go | 288 +++++++++++- types/buildroot/buildroot_test.go | 12 +- types/dynamic_fee_tx.go | 327 +++++++++++++ types/legacy_tx.go | 267 +++++++++++ types/mixed_tx.go | 105 ----- types/receipt.go | 2 +- types/rlp_encoding_test.go | 119 +++-- types/rlp_marshal.go | 115 +---- types/rlp_marshal_storage.go | 2 +- types/rlp_unmarshal.go | 353 +------------- types/rlp_unmarshal_storage.go | 20 +- types/state_tx.go | 280 ++++++++++++ types/transaction.go | 149 ++---- types/types_test.go | 3 +- 53 files changed, 1857 insertions(+), 1334 deletions(-) create mode 100644 types/dynamic_fee_tx.go create mode 100644 types/legacy_tx.go delete mode 100644 types/mixed_tx.go create mode 100644 types/state_tx.go diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index e9749db955..75f6e91d17 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -1020,7 +1020,7 @@ func (b *Blockchain) ReadTxLookup(hash types.Hash) (types.Hash, bool) { // return error if the invalid signature found func (b *Blockchain) recoverFromFieldsInBlock(block *types.Block) error { for _, tx := range block.Transactions { - if tx.From() != types.ZeroAddress || tx.Type() == types.StateTx { + if tx.From() != types.ZeroAddress || tx.Type() == types.StateTxType { continue } @@ -1041,7 +1041,7 @@ func (b *Blockchain) recoverFromFieldsInTransactions(transactions []*types.Trans updated := false for _, tx := range transactions { - if tx.From() != types.ZeroAddress || tx.Type() == types.StateTx { + if tx.From() != types.ZeroAddress || tx.Type() == types.StateTxType { continue } diff --git a/blockchain/blockchain_test.go b/blockchain/blockchain_test.go index 567e605944..ae301b0f6e 100644 --- a/blockchain/blockchain_test.go +++ b/blockchain/blockchain_test.go @@ -590,7 +590,7 @@ func TestBlockchainWriteBody(t *testing.T) { t.Run("should succeed if tx has from field", func(t *testing.T) { t.Parallel() - tx := types.NewTx(&types.MixedTxn{ + tx := types.NewTx(&types.LegacyTx{ Value: big.NewInt(10), V: big.NewInt(1), From: addr, @@ -622,7 +622,7 @@ func TestBlockchainWriteBody(t *testing.T) { t.Run("should return error if tx doesn't have from and recovering address fails", func(t *testing.T) { t.Parallel() - tx := types.NewTx(&types.MixedTxn{ + tx := types.NewTx(&types.LegacyTx{ Value: big.NewInt(10), V: big.NewInt(1), }) @@ -654,7 +654,7 @@ func TestBlockchainWriteBody(t *testing.T) { t.Run("should recover from address and store to storage", func(t *testing.T) { t.Parallel() - tx := types.NewTx(&types.MixedTxn{ + tx := types.NewTx(&types.LegacyTx{ Value: big.NewInt(10), V: big.NewInt(1), }) @@ -715,8 +715,8 @@ func Test_recoverFromFieldsInBlock(t *testing.T) { }, } - tx1 := types.NewTx(&types.MixedTxn{Nonce: 0, From: addr1}) - tx2 := types.NewTx(&types.MixedTxn{Nonce: 1, From: types.ZeroAddress}) + tx1 := types.NewTx(&types.LegacyTx{Nonce: 0, From: addr1}) + tx2 := types.NewTx(&types.LegacyTx{Nonce: 1, From: types.ZeroAddress}) computeTxHashes(tx1, tx2) @@ -745,9 +745,9 @@ func Test_recoverFromFieldsInBlock(t *testing.T) { }, } - tx1 := types.NewTx(&types.MixedTxn{Nonce: 0, From: types.ZeroAddress}) - tx2 := types.NewTx(&types.MixedTxn{Nonce: 1, From: types.ZeroAddress}) - tx3 := types.NewTx(&types.MixedTxn{Nonce: 2, From: types.ZeroAddress}) + tx1 := types.NewTx(&types.LegacyTx{Nonce: 0, From: types.ZeroAddress}) + tx2 := types.NewTx(&types.LegacyTx{Nonce: 1, From: types.ZeroAddress}) + tx3 := types.NewTx(&types.LegacyTx{Nonce: 2, From: types.ZeroAddress}) computeTxHashes(tx1, tx2, tx3) @@ -801,8 +801,8 @@ func Test_recoverFromFieldsInTransactions(t *testing.T) { }, } - tx1 := types.NewTx(&types.MixedTxn{Nonce: 0, From: addr1}) - tx2 := types.NewTx(&types.MixedTxn{Nonce: 1, From: types.ZeroAddress}) + tx1 := types.NewTx(&types.LegacyTx{Nonce: 0, From: addr1}) + tx2 := types.NewTx(&types.LegacyTx{Nonce: 1, From: types.ZeroAddress}) computeTxHashes(tx1, tx2) @@ -830,9 +830,9 @@ func Test_recoverFromFieldsInTransactions(t *testing.T) { }, } - tx1 := types.NewTx(&types.MixedTxn{Nonce: 0, From: types.ZeroAddress}) - tx2 := types.NewTx(&types.MixedTxn{Nonce: 1, From: types.ZeroAddress}) - tx3 := types.NewTx(&types.MixedTxn{Nonce: 2, From: types.ZeroAddress}) + tx1 := types.NewTx(&types.LegacyTx{Nonce: 0, From: types.ZeroAddress}) + tx2 := types.NewTx(&types.LegacyTx{Nonce: 1, From: types.ZeroAddress}) + tx3 := types.NewTx(&types.LegacyTx{Nonce: 2, From: types.ZeroAddress}) computeTxHashes(tx1, tx2, tx3) @@ -864,8 +864,8 @@ func Test_recoverFromFieldsInTransactions(t *testing.T) { }, } - tx1 := types.NewTx(&types.MixedTxn{Nonce: 0, From: addr1}) - tx2 := types.NewTx(&types.MixedTxn{Nonce: 1, From: addr2}) + tx1 := types.NewTx(&types.LegacyTx{Nonce: 0, From: addr1}) + tx2 := types.NewTx(&types.LegacyTx{Nonce: 1, From: addr2}) computeTxHashes(tx1, tx2) @@ -900,7 +900,7 @@ func TestBlockchainReadBody(t *testing.T) { batchWriter := storage.NewBatchWriter(b.db) - tx := types.NewTx(&types.MixedTxn{ + tx := types.NewTx(&types.LegacyTx{ Value: big.NewInt(10), V: big.NewInt(1), }) @@ -1602,7 +1602,7 @@ func TestBlockchain_WriteFullBlock(t *testing.T) { {GasUsed: 100}, {GasUsed: 200}, } - tx := types.NewTx(&types.MixedTxn{ + tx := types.NewTx(&types.LegacyTx{ Value: big.NewInt(1), }) @@ -1868,7 +1868,15 @@ func customJSONBlockUnmarshall(tb testing.TB, jsonData []byte) (*types.FullBlock for _, transactionJSON := range transactionsJSON { tr := transactionJSON.(map[string]interface{}) - transaction := types.NewTx(&types.MixedTxn{}) + + txType := tr["type"].(string) + + txTypeNumber, err := common.ParseUint64orHex(&txType) + if err != nil { + return nil, err + } + + transaction := types.NewTxWithType(types.TxType(txTypeNumber)) transaction.SetHash(types.StringToHash(tr["hash"].(string))) nonce := tr["nonce"].(string) @@ -1935,15 +1943,6 @@ func customJSONBlockUnmarshall(tb testing.TB, jsonData []byte) (*types.FullBlock transaction.SetChainID(chainIDNumber) - txType := tr["type"].(string) - - txTypeNumber, err := common.ParseUint64orHex(&txType) - if err != nil { - return nil, err - } - - transaction.SetTransactionType(types.TxType(txTypeNumber)) - gasFeeCapGeneric, ok := tr["maxFeePerGas"] if ok { gasFeeCap := gasFeeCapGeneric.(string) diff --git a/blockchain/storage/leveldb/leveldb_test.go b/blockchain/storage/leveldb/leveldb_test.go index 21136e69a7..db07be640e 100644 --- a/blockchain/storage/leveldb/leveldb_test.go +++ b/blockchain/storage/leveldb/leveldb_test.go @@ -54,13 +54,11 @@ func generateTxs(t *testing.T, startNonce, count int, from types.Address, to *ty txs := make([]*types.Transaction, count) for i := range txs { - tx := types.NewTx(&types.MixedTxn{ + tx := types.NewTx(&types.DynamicFeeTx{ Gas: types.StateTransactionGasLimit, Nonce: uint64(startNonce + i), - From: from, To: to, Value: big.NewInt(2000), - Type: types.DynamicFeeTx, GasFeeCap: big.NewInt(100), GasTipCap: big.NewInt(10), }) @@ -112,7 +110,7 @@ func generateBlock(t *testing.T, num uint64) *types.FullBlock { b.Receipts[i] = &types.Receipt{ TxHash: b.Block.Transactions[i].Hash(), Root: types.StringToHash("mockhashstring"), - TransactionType: types.LegacyTx, + TransactionType: types.LegacyTxType, GasUsed: uint64(100000), Status: &status, Logs: logs, diff --git a/blockchain/storage/testing.go b/blockchain/storage/testing.go index c947251a55..34964a3780 100644 --- a/blockchain/storage/testing.go +++ b/blockchain/storage/testing.go @@ -270,7 +270,7 @@ func testBody(t *testing.T, m PlaceholderStorage) { require.NoError(t, batch.WriteBatch()) addr1 := types.StringToAddress("11") - t0 := types.NewTx(&types.MixedTxn{ + t0 := types.NewTx(&types.LegacyTx{ Nonce: 0, To: &addr1, Value: big.NewInt(1), @@ -282,7 +282,7 @@ func testBody(t *testing.T, m PlaceholderStorage) { t0.ComputeHash() addr2 := types.StringToAddress("22") - t1 := types.NewTx(&types.MixedTxn{ + t1 := types.NewTx(&types.LegacyTx{ Nonce: 0, To: &addr2, Value: big.NewInt(1), @@ -338,7 +338,7 @@ func testReceipts(t *testing.T, m PlaceholderStorage) { body := &types.Body{ Transactions: []*types.Transaction{ - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.StateTx{ Nonce: 1000, Gas: 50, GasPrice: new(big.Int).SetUint64(100), diff --git a/consensus/polybft/block_builder_test.go b/consensus/polybft/block_builder_test.go index bce6cbb733..d2d098ede1 100644 --- a/consensus/polybft/block_builder_test.go +++ b/consensus/polybft/block_builder_test.go @@ -93,7 +93,7 @@ func TestBlockBuilder_BuildBlockTxOneFailedTxAndOneTakesTooMuchGas(t *testing.T) gas = blockGasLimit - 1 } - tx := types.NewTx(&types.MixedTxn{ + tx := types.NewTx(&types.LegacyTx{ Value: big.NewInt(amount), GasPrice: big.NewInt(gasPrice), Gas: gas, diff --git a/consensus/polybft/fsm.go b/consensus/polybft/fsm.go index ca1e81691f..b28e012947 100644 --- a/consensus/polybft/fsm.go +++ b/consensus/polybft/fsm.go @@ -433,7 +433,7 @@ func (f *fsm) VerifyStateTransactions(transactions []*types.Transaction) error { ) for _, tx := range transactions { - if tx.Type() != types.StateTx { + if tx.Type() != types.StateTxType { continue } @@ -716,10 +716,9 @@ func validateHeaderFields(parent *types.Header, header *types.Header, blockTimeD // createStateTransactionWithData creates a state transaction // with provided target address and inputData parameter which is ABI encoded byte array. func createStateTransactionWithData(target types.Address, inputData []byte) *types.Transaction { - tx := types.NewTx(&types.MixedTxn{ + tx := types.NewTx(&types.StateTx{ From: contracts.SystemCaller, To: &target, - Type: types.StateTx, Input: inputData, Gas: types.StateTransactionGasLimit, GasPrice: big.NewInt(0), diff --git a/consensus/polybft/fsm_test.go b/consensus/polybft/fsm_test.go index e65b53f4b5..b126ae74e0 100644 --- a/consensus/polybft/fsm_test.go +++ b/consensus/polybft/fsm_test.go @@ -100,11 +100,10 @@ func TestFSM_verifyCommitEpochTx(t *testing.T) { assert.NoError(t, fsm.verifyCommitEpochTx(commitEpochTx)) // submit tampered commit epoch transaction to the epoch ending block - alteredCommitEpochTx := types.NewTx(&types.MixedTxn{ + alteredCommitEpochTx := types.NewTx(&types.StateTx{ To: &contracts.EpochManagerContract, Input: []byte{}, Gas: 0, - Type: types.StateTx, }) assert.ErrorContains(t, fsm.verifyCommitEpochTx(alteredCommitEpochTx), "invalid commit epoch transaction") diff --git a/consensus/polybft/polybft.go b/consensus/polybft/polybft.go index 9c61613ecb..a9f2d5328d 100644 --- a/consensus/polybft/polybft.go +++ b/consensus/polybft/polybft.go @@ -781,7 +781,7 @@ func (p *Polybft) PreCommitState(block *types.Block, _ *state.Transition) error // validate commitment state transactions for _, tx := range block.Transactions { - if tx.Type() != types.StateTx { + if tx.Type() != types.StateTxType { continue } diff --git a/consensus/polybft/state_sync_commitment.go b/consensus/polybft/state_sync_commitment.go index f352789c0b..dd1ade9d89 100644 --- a/consensus/polybft/state_sync_commitment.go +++ b/consensus/polybft/state_sync_commitment.go @@ -165,7 +165,7 @@ func getCommitmentMessageSignedTx(txs []*types.Transaction) (*CommitmentMessageS var commitFn contractsapi.CommitStateReceiverFn for _, tx := range txs { // skip non state CommitmentMessageSigned transactions - if tx.Type() != types.StateTx || + if tx.Type() != types.StateTxType || len(tx.Input()) < abiMethodIDLength || !bytes.Equal(tx.Input()[:abiMethodIDLength], commitFn.Sig()) { continue diff --git a/crypto/txsigner.go b/crypto/txsigner.go index 530bca94ad..55aed47392 100644 --- a/crypto/txsigner.go +++ b/crypto/txsigner.go @@ -97,7 +97,7 @@ func calcTxHash(tx *types.Transaction, chainID uint64) types.Hash { var hash []byte switch tx.Type() { - case types.AccessListTx: + case types.AccessListTxType: a := signerPool.Get() v := a.NewArray() @@ -141,9 +141,9 @@ func calcTxHash(tx *types.Transaction, chainID uint64) types.Hash { return types.BytesToHash(hash) - case types.DynamicFeeTx, types.LegacyTx, types.StateTx: + case types.DynamicFeeTxType, types.LegacyTxType, types.StateTxType: a := signerPool.Get() - isDynamicFeeTx := tx.Type() == types.DynamicFeeTx + isDynamicFeeTx := tx.Type() == types.DynamicFeeTxType v := a.NewArray() diff --git a/crypto/txsigner_eip155_test.go b/crypto/txsigner_eip155_test.go index 86769d6c7d..ce6c0752a1 100644 --- a/crypto/txsigner_eip155_test.go +++ b/crypto/txsigner_eip155_test.go @@ -70,7 +70,7 @@ func TestEIP155Signer_Sender(t *testing.T) { t.Fatalf("Unable to generate key") } - txn := types.NewTx(&types.MixedTxn{ + txn := types.NewTx(&types.LegacyTx{ To: &toAddress, Value: big.NewInt(1), GasPrice: big.NewInt(0), @@ -106,7 +106,7 @@ func TestEIP155Signer_ChainIDMismatch(t *testing.T) { t.Fatalf("Unable to generate key") } - txn := types.NewTx(&types.MixedTxn{ + txn := types.NewTx(&types.LegacyTx{ To: &toAddress, Value: big.NewInt(1), GasPrice: big.NewInt(0), diff --git a/crypto/txsigner_frontier_test.go b/crypto/txsigner_frontier_test.go index aab7ffe3f6..6a82785734 100644 --- a/crypto/txsigner_frontier_test.go +++ b/crypto/txsigner_frontier_test.go @@ -15,7 +15,7 @@ func TestFrontierSigner(t *testing.T) { key, err := GenerateECDSAKey() assert.NoError(t, err) - txn := types.NewTx(&types.MixedTxn{ + txn := types.NewTx(&types.LegacyTx{ To: &toAddress, Value: big.NewInt(10), GasPrice: big.NewInt(0), diff --git a/crypto/txsigner_london_berlin.go b/crypto/txsigner_london_berlin.go index 29f9d21e70..a8030d334d 100644 --- a/crypto/txsigner_london_berlin.go +++ b/crypto/txsigner_london_berlin.go @@ -34,7 +34,7 @@ func (e *LondonOrBerlinSigner) Hash(tx *types.Transaction) types.Hash { // Sender returns the transaction sender func (e *LondonOrBerlinSigner) Sender(tx *types.Transaction) (types.Address, error) { - if tx.Type() != types.DynamicFeeTx && tx.Type() != types.AccessListTx { + if tx.Type() != types.DynamicFeeTxType && tx.Type() != types.AccessListTxType { return e.fallbackSigner.Sender(tx) } @@ -45,7 +45,7 @@ func (e *LondonOrBerlinSigner) Sender(tx *types.Transaction) (types.Address, err // SignTx signs the transaction using the passed in private key func (e *LondonOrBerlinSigner) SignTx(tx *types.Transaction, pk *ecdsa.PrivateKey) (*types.Transaction, error) { - if tx.Type() != types.DynamicFeeTx && tx.Type() != types.AccessListTx { + if tx.Type() != types.DynamicFeeTxType && tx.Type() != types.AccessListTxType { return e.fallbackSigner.SignTx(tx, pk) } diff --git a/crypto/txsigner_london_berlin_test.go b/crypto/txsigner_london_berlin_test.go index a1c989ce80..617cc351ee 100644 --- a/crypto/txsigner_london_berlin_test.go +++ b/crypto/txsigner_london_berlin_test.go @@ -23,42 +23,42 @@ func TestLondonSignerSender(t *testing.T) { { "mainnet", big.NewInt(1), - types.LegacyTx, + types.LegacyTxType, }, { "expanse mainnet", big.NewInt(2), - types.DynamicFeeTx, + types.DynamicFeeTxType, }, { "ropsten", big.NewInt(3), - types.DynamicFeeTx, + types.DynamicFeeTxType, }, { "rinkeby", big.NewInt(4), - types.AccessListTx, + types.AccessListTxType, }, { "goerli", big.NewInt(5), - types.AccessListTx, + types.AccessListTxType, }, { "kovan", big.NewInt(42), - types.StateTx, + types.StateTxType, }, { "geth private", big.NewInt(1337), - types.StateTx, + types.StateTxType, }, { "mega large", big.NewInt(0).Exp(big.NewInt(2), big.NewInt(20), nil), // 2**20 - types.AccessListTx, + types.AccessListTxType, }, } @@ -73,18 +73,29 @@ func TestLondonSignerSender(t *testing.T) { var txn *types.Transaction switch tc.txType { - case types.AccessListTx: + case types.AccessListTxType: txn = types.NewTx(&types.AccessListTxn{ To: &recipient, Value: big.NewInt(1), GasPrice: big.NewInt(5), }) - case types.DynamicFeeTx, types.LegacyTx, types.StateTx: - txn = types.NewTx(&types.MixedTxn{ + case types.LegacyTxType: + txn = types.NewTx(&types.LegacyTx{ To: &recipient, Value: big.NewInt(1), GasPrice: big.NewInt(5), }) + case types.StateTxType: + txn = types.NewTx(&types.StateTx{ + To: &recipient, + Value: big.NewInt(1), + GasPrice: big.NewInt(5), + }) + case types.DynamicFeeTxType: + txn = types.NewTx(&types.DynamicFeeTx{ + To: &recipient, + Value: big.NewInt(1), + }) } chainID := tc.chainID.Uint64() @@ -120,9 +131,7 @@ func Test_LondonSigner_Sender(t *testing.T) { }{ { name: "sender is 0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6", - tx: types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, - GasPrice: big.NewInt(1000000402), + tx: types.NewTx(&types.DynamicFeeTx{ GasTipCap: ethgo.Gwei(1), GasFeeCap: ethgo.Gwei(10), Gas: 21000, diff --git a/e2e/framework/testserver.go b/e2e/framework/testserver.go index 3419115ce6..d851382ca2 100644 --- a/e2e/framework/testserver.go +++ b/e2e/framework/testserver.go @@ -520,7 +520,7 @@ func (t *TestServer) SendRawTx( return nil, err } - signedTx, err := t.SignTx(types.NewTx(&types.MixedTxn{ + signedTx, err := t.SignTx(types.NewTx(&types.LegacyTx{ From: tx.From, GasPrice: tx.GasPrice, Gas: tx.Gas, diff --git a/e2e/txpool_test.go b/e2e/txpool_test.go index 240e13645f..cbf48e3d08 100644 --- a/e2e/txpool_test.go +++ b/e2e/txpool_test.go @@ -42,20 +42,25 @@ type generateTxReqParams struct { } func generateTx(params generateTxReqParams) *types.Transaction { - unsignedTx := types.NewTx(&types.MixedTxn{ - Nonce: params.nonce, - From: params.referenceAddr, - To: ¶ms.toAddress, - Gas: 1000000, - Value: params.value, - V: big.NewInt(27), // it is necessary to encode in rlp - }) + var unsignedTx *types.Transaction if params.gasPrice != nil { - unsignedTx.SetTransactionType(types.LegacyTx) + unsignedTx = types.NewTx(&types.LegacyTx{ + Nonce: params.nonce, + To: ¶ms.toAddress, + Gas: 1000000, + Value: params.value, + V: big.NewInt(27), // it is necessary to encode in rlp + }) unsignedTx.SetGasPrice(params.gasPrice) } else { - unsignedTx.SetTransactionType(types.DynamicFeeTx) + unsignedTx = types.NewTx(&types.DynamicFeeTx{ + Nonce: params.nonce, + To: ¶ms.toAddress, + Gas: 1000000, + Value: params.value, + V: big.NewInt(27), // it is necessary to encode in rlp + }) unsignedTx.SetGasFeeCap(params.gasFeeCap) unsignedTx.SetGasTipCap(params.gasTipCap) } @@ -236,7 +241,7 @@ func TestTxPool_RecoverableError(t *testing.T) { _, receiverAddress := tests.GenerateKeyAndAddr(t) transactions := []*types.Transaction{ - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.LegacyTx{ Nonce: 0, GasPrice: big.NewInt(framework.DefaultGasPrice), Gas: 22000, @@ -245,17 +250,15 @@ func TestTxPool_RecoverableError(t *testing.T) { V: big.NewInt(27), From: senderAddress, }), - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.LegacyTx{ Nonce: 1, GasPrice: big.NewInt(framework.DefaultGasPrice), Gas: 22000, To: &receiverAddress, Value: oneEth, V: big.NewInt(27), - From: senderAddress, }), - types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, + types.NewTx(&types.DynamicFeeTx{ Nonce: 2, GasFeeCap: big.NewInt(framework.DefaultGasPrice), GasTipCap: big.NewInt(1000000000), @@ -263,7 +266,6 @@ func TestTxPool_RecoverableError(t *testing.T) { To: &receiverAddress, Value: oneEth, V: big.NewInt(27), - From: senderAddress, }), } @@ -346,7 +348,7 @@ func TestTxPool_GetPendingTx(t *testing.T) { operator := server.TxnPoolOperator() client := server.JSONRPC() - signedTx, err := signer.SignTx(types.NewTx(&types.MixedTxn{ + signedTx, err := signer.SignTx(types.NewTx(&types.LegacyTx{ Nonce: 0, GasPrice: big.NewInt(1000000000), Gas: framework.DefaultGasLimit - 1, diff --git a/gasprice/feehistory_test.go b/gasprice/feehistory_test.go index debd24a4e7..dd2b121e13 100644 --- a/gasprice/feehistory_test.go +++ b/gasprice/feehistory_test.go @@ -194,11 +194,9 @@ func TestGasHelper_FeeHistory(t *testing.T) { b.Header.Miner = sender.Bytes() for i := 0; i < 3; i++ { - tx := types.NewTx(&types.MixedTxn{ - From: sender, + tx := types.NewTx(&types.DynamicFeeTx{ Value: ethgo.Ether(1), To: &types.ZeroAddress, - Type: types.DynamicFeeTx, GasTipCap: ethgo.Gwei(uint64(200)), GasFeeCap: ethgo.Gwei(uint64(200 + 200)), }) diff --git a/gasprice/gasprice_test.go b/gasprice/gasprice_test.go index c5df080fd0..a148f2ccad 100644 --- a/gasprice/gasprice_test.go +++ b/gasprice/gasprice_test.go @@ -84,11 +84,10 @@ func TestGasHelper_MaxPriorityFeePerGas(t *testing.T) { b.Header.Miner = sender.Bytes() for i := 0; i < 3; i++ { - tx := types.NewTx(&types.MixedTxn{ + tx := types.NewTx(&types.DynamicFeeTx{ From: sender, Value: ethgo.Ether(1), To: &types.ZeroAddress, - Type: types.DynamicFeeTx, GasTipCap: ethgo.Gwei(uint64(rand.Intn(200))), GasFeeCap: ethgo.Gwei(uint64(rand.Intn(200) + 200)), }) @@ -219,11 +218,10 @@ func createTestTxs(t *testing.T, backend *backendMock, numOfTxsPerBlock, txCap i for i := 0; i < numOfTxsPerBlock; i++ { senderKey, sender := tests.GenerateKeyAndAddr(t) - tx := types.NewTx(&types.MixedTxn{ + tx := types.NewTx(&types.DynamicFeeTx{ From: sender, Value: ethgo.Ether(1), To: &types.ZeroAddress, - Type: types.DynamicFeeTx, GasTipCap: ethgo.Gwei(uint64(rand.Intn(txCap))), GasFeeCap: ethgo.Gwei(uint64(rand.Intn(txCap) + txCap)), }) diff --git a/helper/tests/testing.go b/helper/tests/testing.go index e7ceb0c8a5..96a6ac49be 100644 --- a/helper/tests/testing.go +++ b/helper/tests/testing.go @@ -238,7 +238,7 @@ type GenerateTxReqParams struct { func generateTx(params GenerateTxReqParams) (*types.Transaction, error) { signer := crypto.NewEIP155Signer(100, true) - signedTx, signErr := signer.SignTx(types.NewTx(&types.MixedTxn{ + signedTx, signErr := signer.SignTx(types.NewTx(&types.LegacyTx{ Nonce: params.Nonce, From: params.ReferenceAddr, To: ¶ms.ToAddress, diff --git a/jsonrpc/debug_endpoint_test.go b/jsonrpc/debug_endpoint_test.go index f6e9d1603d..bf1cc5b96f 100644 --- a/jsonrpc/debug_endpoint_test.go +++ b/jsonrpc/debug_endpoint_test.go @@ -603,10 +603,10 @@ func TestTraceCall(t *testing.T) { Data: &data, Input: &input, Nonce: &nonce, + Type: toArgUint64Ptr(uint64(types.DynamicFeeTxType)), } - decodedTx = types.NewTx(&types.MixedTxn{ + decodedTx = types.NewTx(&types.DynamicFeeTx{ Nonce: uint64(nonce), - GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), GasTipCap: new(big.Int).SetBytes([]byte(gasTipCap)), GasFeeCap: new(big.Int).SetBytes([]byte(gasFeeCap)), Gas: uint64(gas), diff --git a/jsonrpc/dispatcher_test.go b/jsonrpc/dispatcher_test.go index ae0331b228..63cfc7e90d 100644 --- a/jsonrpc/dispatcher_test.go +++ b/jsonrpc/dispatcher_test.go @@ -3,7 +3,6 @@ package jsonrpc import ( "encoding/json" "fmt" - "math/big" "reflect" "testing" "time" @@ -13,12 +12,11 @@ import ( "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo" ) var ( - oneEther = new(big.Int).Mul( - big.NewInt(1), - new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) + oneEther = ethgo.Ether(1) ) func toArgUint64Ptr(value uint64) *argUint64 { diff --git a/jsonrpc/eth_blockchain_test.go b/jsonrpc/eth_blockchain_test.go index 807a0eaf6b..0ddfb86d6b 100644 --- a/jsonrpc/eth_blockchain_test.go +++ b/jsonrpc/eth_blockchain_test.go @@ -89,7 +89,7 @@ func TestEth_Block_GetBlockTransactionCountByNumber(t *testing.T) { for i := 0; i < 10; i++ { block.Transactions = append(block.Transactions, []*types.Transaction{ - types.NewTx(&types.MixedTxn{Nonce: 0, From: addr0})}...) + types.NewTx(&types.LegacyTx{Nonce: 0, From: addr0})}...) } store.add(block) diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index 5ca84c79d2..ca90e8455a 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -408,7 +408,7 @@ func (e *Eth) fillTransactionGasPrice(tx *types.Transaction) error { return err } - if tx.Type() == types.DynamicFeeTx { + if tx.Type() == types.DynamicFeeTxType { tx.SetGasFeeCap(new(big.Int).SetUint64(estimatedGasPrice)) } else { tx.SetGasPrice(new(big.Int).SetUint64(estimatedGasPrice)) diff --git a/jsonrpc/eth_endpoint_test.go b/jsonrpc/eth_endpoint_test.go index 98e3eba23b..d0ffb5d344 100644 --- a/jsonrpc/eth_endpoint_test.go +++ b/jsonrpc/eth_endpoint_test.go @@ -39,18 +39,17 @@ func TestEth_DecodeTxn(t *testing.T) { From: &addr1, To: &addr2, Gas: toArgUint64Ptr(21000), - GasPrice: toArgBytesPtr(big.NewInt(10000).Bytes()), GasTipCap: toArgBytesPtr(big.NewInt(10000).Bytes()), GasFeeCap: toArgBytesPtr(big.NewInt(10000).Bytes()), Value: toArgBytesPtr(oneEther.Bytes()), Data: nil, Nonce: toArgUint64Ptr(0), + Type: toArgUint64Ptr(uint64(types.DynamicFeeTxType)), }, - res: types.NewTx(&types.MixedTxn{ + res: types.NewTx(&types.DynamicFeeTx{ From: addr1, To: &addr2, Gas: 21000, - GasPrice: big.NewInt(10000), GasTipCap: big.NewInt(10000), GasFeeCap: big.NewInt(10000), Value: oneEther, @@ -68,16 +67,14 @@ func TestEth_DecodeTxn(t *testing.T) { Value: toArgBytesPtr(oneEther.Bytes()), Data: nil, }, - res: types.NewTx(&types.MixedTxn{ - From: types.ZeroAddress, - To: &addr2, - Gas: 21000, - GasPrice: big.NewInt(10000), - GasTipCap: new(big.Int), - GasFeeCap: new(big.Int), - Value: oneEther, - Input: []byte{}, - Nonce: 0, + res: types.NewTx(&types.LegacyTx{ + From: types.ZeroAddress, + To: &addr2, + Gas: 21000, + GasPrice: big.NewInt(10000), + Value: oneEther, + Input: []byte{}, + Nonce: 0, }), err: nil, }, @@ -96,16 +93,14 @@ func TestEth_DecodeTxn(t *testing.T) { Value: toArgBytesPtr(oneEther.Bytes()), Data: nil, }, - res: types.NewTx(&types.MixedTxn{ - From: addr1, - To: &addr2, - Gas: 21000, - GasPrice: big.NewInt(10000), - GasTipCap: new(big.Int), - GasFeeCap: new(big.Int), - Value: oneEther, - Input: []byte{}, - Nonce: 10, + res: types.NewTx(&types.LegacyTx{ + From: addr1, + To: &addr2, + Gas: 21000, + GasPrice: big.NewInt(10000), + Value: oneEther, + Input: []byte{}, + Nonce: 10, }), err: nil, }, @@ -119,16 +114,14 @@ func TestEth_DecodeTxn(t *testing.T) { Data: nil, Nonce: toArgUint64Ptr(1), }, - res: types.NewTx(&types.MixedTxn{ - From: addr1, - To: &addr2, - Gas: 21000, - GasPrice: big.NewInt(10000), - GasTipCap: new(big.Int), - GasFeeCap: new(big.Int), - Value: new(big.Int).SetBytes([]byte{}), - Input: []byte{}, - Nonce: 1, + res: types.NewTx(&types.LegacyTx{ + From: addr1, + To: &addr2, + Gas: 21000, + GasPrice: big.NewInt(10000), + Value: new(big.Int).SetBytes([]byte{}), + Input: []byte{}, + Nonce: 1, }), err: nil, }, @@ -141,16 +134,14 @@ func TestEth_DecodeTxn(t *testing.T) { Data: nil, Nonce: toArgUint64Ptr(1), }, - res: types.NewTx(&types.MixedTxn{ - From: addr1, - To: &addr2, - Gas: 0, - GasPrice: big.NewInt(10000), - GasTipCap: new(big.Int), - GasFeeCap: new(big.Int), - Value: new(big.Int).SetBytes([]byte{}), - Input: []byte{}, - Nonce: 1, + res: types.NewTx(&types.LegacyTx{ + From: addr1, + To: &addr2, + Gas: 0, + GasPrice: big.NewInt(10000), + Value: new(big.Int).SetBytes([]byte{}), + Input: []byte{}, + Nonce: 1, }), err: nil, }, @@ -275,20 +266,18 @@ func TestEth_TxnType(t *testing.T) { Value: toArgBytesPtr(oneEther.Bytes()), Data: nil, Nonce: toArgUint64Ptr(0), - Type: toArgUint64Ptr(uint64(types.DynamicFeeTx)), + Type: toArgUint64Ptr(uint64(types.DynamicFeeTxType)), } - expectedRes := types.NewTx(&types.MixedTxn{ + expectedRes := types.NewTx(&types.DynamicFeeTx{ From: addr1, To: &addr2, Gas: 21000, - GasPrice: big.NewInt(10000), GasTipCap: big.NewInt(10000), GasFeeCap: big.NewInt(10000), Value: oneEther, Input: []byte{}, Nonce: 0, - Type: types.DynamicFeeTx, }) res, err := DecodeTxn(args, 1, store, false) diff --git a/jsonrpc/eth_txpool_test.go b/jsonrpc/eth_txpool_test.go index eb3cf9e252..4eab2931df 100644 --- a/jsonrpc/eth_txpool_test.go +++ b/jsonrpc/eth_txpool_test.go @@ -11,7 +11,7 @@ import ( func TestEth_TxnPool_SendRawTransaction(t *testing.T) { store := &mockStoreTxn{} eth := newTestEthEndpoint(store) - txn := types.NewTx(&types.MixedTxn{ + txn := types.NewTx(&types.LegacyTx{ From: addr0, V: big.NewInt(1), }) @@ -32,7 +32,7 @@ func TestEth_TxnPool_SendTransaction(t *testing.T) { store := &mockStoreTxn{} store.AddAccount(addr0) eth := newTestEthEndpoint(store) - txToSend := types.NewTx(&types.MixedTxn{ + txToSend := types.NewTx(&types.LegacyTx{ From: addr0, To: argAddrPtr(addr0), Nonce: uint64(0), diff --git a/jsonrpc/filter_manager_fuzz_test.go b/jsonrpc/filter_manager_fuzz_test.go index bb52cd1472..4637a8d874 100644 --- a/jsonrpc/filter_manager_fuzz_test.go +++ b/jsonrpc/filter_manager_fuzz_test.go @@ -34,17 +34,17 @@ func FuzzGetLogsForQuery(f *testing.F) { }, Transactions: []*types.Transaction{ { - Inner: &types.MixedTxn{ + Inner: &types.LegacyTx{ Value: big.NewInt(10), }, }, { - Inner: &types.MixedTxn{ + Inner: &types.LegacyTx{ Value: big.NewInt(11), }, }, { - Inner: &types.MixedTxn{ + Inner: &types.LegacyTx{ Value: big.NewInt(12), }, }, diff --git a/jsonrpc/filter_manager_test.go b/jsonrpc/filter_manager_test.go index 7eefb8b618..c1217dd4f0 100644 --- a/jsonrpc/filter_manager_test.go +++ b/jsonrpc/filter_manager_test.go @@ -114,9 +114,9 @@ func Test_GetLogsForQuery(t *testing.T) { Hash: types.StringToHash(strconv.Itoa(i)), }, Transactions: []*types.Transaction{ - types.NewTx(&types.MixedTxn{Value: big.NewInt(10)}), - types.NewTx(&types.MixedTxn{Value: big.NewInt(11)}), - types.NewTx(&types.MixedTxn{Value: big.NewInt(12)}), + types.NewTx(&types.LegacyTx{Value: big.NewInt(10)}), + types.NewTx(&types.LegacyTx{Value: big.NewInt(11)}), + types.NewTx(&types.LegacyTx{Value: big.NewInt(12)}), }, } } diff --git a/jsonrpc/helper.go b/jsonrpc/helper.go index 5c220d1b58..618739b548 100644 --- a/jsonrpc/helper.go +++ b/jsonrpc/helper.go @@ -214,22 +214,26 @@ func DecodeTxn(arg *txnArgs, blockNumber uint64, store nonceGetter, forceSetNonc arg.Gas = argUintPtr(0) } - txType := types.LegacyTx + txType := types.LegacyTxType if arg.Type != nil { txType = types.TxType(*arg.Type) } - txn := types.NewTx(&types.MixedTxn{ - From: *arg.From, - Gas: uint64(*arg.Gas), - GasPrice: new(big.Int).SetBytes(*arg.GasPrice), - GasTipCap: new(big.Int).SetBytes(*arg.GasTipCap), - GasFeeCap: new(big.Int).SetBytes(*arg.GasFeeCap), - Value: new(big.Int).SetBytes(*arg.Value), - Input: input, - Nonce: uint64(*arg.Nonce), - Type: txType, - }) + txn := types.NewTxWithType(txType) + + switch txType { + case types.LegacyTxType: + txn.SetGasPrice(new(big.Int).SetBytes(*arg.GasPrice)) + case types.DynamicFeeTxType: + txn.SetGasTipCap(new(big.Int).SetBytes(*arg.GasTipCap)) + txn.SetGasFeeCap(new(big.Int).SetBytes(*arg.GasFeeCap)) + } + + txn.SetFrom(*arg.From) + txn.SetGas(uint64(*arg.Gas)) + txn.SetValue(new(big.Int).SetBytes(*arg.Value)) + txn.SetInput(input) + txn.SetNonce(uint64(*arg.Nonce)) if arg.To != nil { txn.SetTo(arg.To) diff --git a/jsonrpc/helper_test.go b/jsonrpc/helper_test.go index c63af1a47a..a95065d0f9 100644 --- a/jsonrpc/helper_test.go +++ b/jsonrpc/helper_test.go @@ -14,7 +14,7 @@ import ( func createTestTransaction(hash types.Hash) *types.Transaction { recipient := types.StringToAddress("2") - return types.NewTx(&types.MixedTxn{ + return types.NewTx(&types.LegacyTx{ Hash: hash, From: types.StringToAddress("1"), To: &recipient, @@ -51,7 +51,7 @@ func createTestReceipt(logs []*types.Log, cumulativeGasUsed, gasUsed uint64, txH Logs: logs, GasUsed: gasUsed, TxHash: txHash, - TransactionType: types.DynamicFeeTx, + TransactionType: types.DynamicFeeTxType, } } @@ -705,13 +705,13 @@ func TestDecodeTxn(t *testing.T) { Value: &value, Input: &input, Nonce: &nonce, + Type: toArgUint64Ptr(uint64(types.DynamicFeeTxType)), }, store: &debugEndpointMockStore{}, - expected: types.NewTx(&types.MixedTxn{ + expected: types.NewTx(&types.DynamicFeeTx{ From: from, To: &to, Gas: uint64(gas), - GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), GasTipCap: new(big.Int).SetBytes([]byte(gasTipCap)), GasFeeCap: new(big.Int).SetBytes([]byte(gasFeeCap)), Value: new(big.Int).SetBytes([]byte(value)), @@ -731,16 +731,14 @@ func TestDecodeTxn(t *testing.T) { Nonce: &nonce, }, store: &debugEndpointMockStore{}, - expected: types.NewTx(&types.MixedTxn{ - From: types.ZeroAddress, - To: &to, - Gas: uint64(gas), - GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), - GasTipCap: new(big.Int), - GasFeeCap: new(big.Int), - Value: new(big.Int).SetBytes([]byte(value)), - Input: input, - Nonce: uint64(0), + expected: types.NewTx(&types.LegacyTx{ + From: types.ZeroAddress, + To: &to, + Gas: uint64(gas), + Value: new(big.Int).SetBytes([]byte(value)), + GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), + Input: input, + Nonce: uint64(0), }), err: false, }, @@ -766,16 +764,14 @@ func TestDecodeTxn(t *testing.T) { }, nil }, }, - expected: types.NewTx(&types.MixedTxn{ - From: from, - To: &to, - Gas: uint64(gas), - GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), - GasTipCap: new(big.Int), - GasFeeCap: new(big.Int), - Value: new(big.Int).SetBytes([]byte(value)), - Input: input, - Nonce: uint64(stateNonce), + expected: types.NewTx(&types.LegacyTx{ + From: from, + To: &to, + Gas: uint64(gas), + Value: new(big.Int).SetBytes([]byte(value)), + GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), + Input: input, + Nonce: uint64(stateNonce), }), err: false, }, @@ -792,16 +788,14 @@ func TestDecodeTxn(t *testing.T) { Nonce: &nonce, }, store: &debugEndpointMockStore{}, - expected: types.NewTx(&types.MixedTxn{ - From: from, - To: &to, - Gas: uint64(gas), - GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), - GasTipCap: new(big.Int), - GasFeeCap: new(big.Int), - Value: new(big.Int).SetBytes([]byte(value)), - Input: data, - Nonce: uint64(nonce), + expected: types.NewTx(&types.LegacyTx{ + From: from, + To: &to, + Gas: uint64(gas), + Value: new(big.Int).SetBytes([]byte(value)), + GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), + Input: data, + Nonce: uint64(nonce), }), err: false, }, @@ -813,16 +807,14 @@ func TestDecodeTxn(t *testing.T) { Nonce: &nonce, }, store: &debugEndpointMockStore{}, - expected: types.NewTx(&types.MixedTxn{ - From: from, - To: &to, - Gas: uint64(0), - GasPrice: new(big.Int), - GasTipCap: new(big.Int), - GasFeeCap: new(big.Int), - Value: new(big.Int), - Input: []byte{}, - Nonce: uint64(nonce), + expected: types.NewTx(&types.LegacyTx{ + From: from, + To: &to, + Gas: uint64(0), + Value: new(big.Int), + GasPrice: new(big.Int), + Input: []byte{}, + Nonce: uint64(nonce), }), err: false, }, diff --git a/jsonrpc/txpool_endpoint_test.go b/jsonrpc/txpool_endpoint_test.go index 5d892f4249..5173bb8955 100644 --- a/jsonrpc/txpool_endpoint_test.go +++ b/jsonrpc/txpool_endpoint_test.go @@ -49,8 +49,8 @@ func TestContentEndpoint(t *testing.T) { assert.NotNil(t, txData) assert.Equal(t, testTx1.Gas(), uint64(txData.Gas)) assert.Equal(t, *(testTx1.GasPrice()), big.Int(*txData.GasPrice)) - assert.Equal(t, (*argBig)(nil), txData.GasFeeCap) - assert.Equal(t, (*argBig)(nil), txData.GasTipCap) + assert.Equal(t, *(testTx1.GasFeeCap()), big.Int(*txData.GasPrice)) + assert.Equal(t, *(testTx1.GasTipCap()), big.Int(*txData.GasPrice)) assert.Equal(t, testTx1.To(), txData.To) assert.Equal(t, testTx1.From(), txData.From) assert.Equal(t, *(testTx1.Value()), big.Int(txData.Value)) @@ -60,9 +60,9 @@ func TestContentEndpoint(t *testing.T) { txData = response.Pending[address1][testTx2.Nonce()] assert.NotNil(t, txData) - assert.Equal(t, (argUint64)(types.DynamicFeeTx), txData.Type) + assert.Equal(t, (argUint64)(types.DynamicFeeTxType), txData.Type) assert.Equal(t, testTx2.Gas(), uint64(txData.Gas)) - assert.Equal(t, (*argBig)(nil), txData.GasPrice) + assert.Nil(t, testTx2.GasPrice()) assert.Equal(t, *(testTx2.GasFeeCap()), big.Int(*txData.GasFeeCap)) assert.Equal(t, *(testTx2.GasTipCap()), big.Int(*txData.GasTipCap)) assert.Equal(t, testTx2.To(), txData.To) @@ -98,8 +98,8 @@ func TestContentEndpoint(t *testing.T) { assert.NotNil(t, txData) assert.Equal(t, testTx1.Gas(), uint64(txData.Gas)) assert.Equal(t, *(testTx1.GasPrice()), big.Int(*txData.GasPrice)) - assert.Equal(t, (*argBig)(nil), txData.GasFeeCap) - assert.Equal(t, (*argBig)(nil), txData.GasTipCap) + assert.Equal(t, *(testTx1.GasFeeCap()), big.Int(*txData.GasPrice)) + assert.Equal(t, *(testTx1.GasTipCap()), big.Int(*txData.GasPrice)) assert.Equal(t, testTx1.To(), txData.To) assert.Equal(t, testTx1.From(), txData.From) assert.Equal(t, *(testTx1.Value()), big.Int(txData.Value)) @@ -109,9 +109,9 @@ func TestContentEndpoint(t *testing.T) { txData = response.Queued[address2][testTx2.Nonce()] assert.NotNil(t, txData) - assert.Equal(t, (argUint64)(types.DynamicFeeTx), txData.Type) + assert.Equal(t, (argUint64)(types.DynamicFeeTxType), txData.Type) assert.Equal(t, testTx2.Gas(), uint64(txData.Gas)) - assert.Equal(t, (*argBig)(nil), txData.GasPrice) + assert.Nil(t, testTx2.GasPrice()) assert.Equal(t, *(testTx2.GasFeeCap()), big.Int(*txData.GasFeeCap)) assert.Equal(t, *(testTx2.GasTipCap()), big.Int(*txData.GasTipCap)) assert.Equal(t, testTx2.To(), txData.To) @@ -294,7 +294,7 @@ func (s *mockTxPoolStore) GetBaseFee() uint64 { } func newTestTransaction(nonce uint64, from types.Address) *types.Transaction { - txn := types.NewTx(&types.MixedTxn{ + txn := types.NewTx(&types.LegacyTx{ Nonce: nonce, GasPrice: big.NewInt(1), Gas: nonce * 100, @@ -313,8 +313,7 @@ func newTestTransaction(nonce uint64, from types.Address) *types.Transaction { } func newTestDynamicFeeTransaction(nonce uint64, from types.Address) *types.Transaction { - txn := types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, + txn := types.NewTx(&types.DynamicFeeTx{ Nonce: nonce, GasTipCap: big.NewInt(2), GasFeeCap: big.NewInt(4), diff --git a/jsonrpc/types.go b/jsonrpc/types.go index b1a842eab9..fdb34b7323 100644 --- a/jsonrpc/types.go +++ b/jsonrpc/types.go @@ -77,17 +77,17 @@ func toTransaction( BlockHash: blockHash, } - if t.GasPrice() != nil { + if t.GasPrice() != nil && t.Type() != types.DynamicFeeTxType { gasPrice := argBig(*(t.GasPrice())) res.GasPrice = &gasPrice } - if t.GasTipCap() != nil { + if t.GasTipCap() != nil && t.Type() == types.DynamicFeeTxType { gasTipCap := argBig(*(t.GasTipCap())) res.GasTipCap = &gasTipCap } - if t.GasFeeCap() != nil { + if t.GasFeeCap() != nil && t.Type() == types.DynamicFeeTxType { gasFeeCap := argBig(*(t.GasFeeCap())) res.GasFeeCap = &gasFeeCap } diff --git a/jsonrpc/types_test.go b/jsonrpc/types_test.go index b3a0f9e738..d0fa5fa30c 100644 --- a/jsonrpc/types_test.go +++ b/jsonrpc/types_test.go @@ -103,7 +103,7 @@ func TestToTransaction_Returns_V_R_S_ValuesWithoutLeading0(t *testing.T) { v, _ := hex.DecodeHex(hexWithLeading0) r, _ := hex.DecodeHex(hexWithLeading0) s, _ := hex.DecodeHex(hexWithLeading0) - txn := types.NewTx(&types.MixedTxn{ + txn := types.NewTx(&types.LegacyTx{ Nonce: 0, GasPrice: big.NewInt(0), Gas: 0, @@ -134,9 +134,8 @@ func TestToTransaction_EIP1559(t *testing.T) { v, _ := hex.DecodeHex(hexWithLeading0) r, _ := hex.DecodeHex(hexWithLeading0) s, _ := hex.DecodeHex(hexWithLeading0) - txn := types.NewTx(&types.MixedTxn{ + txn := types.NewTx(&types.DynamicFeeTx{ Nonce: 0, - GasPrice: nil, GasTipCap: big.NewInt(10), GasFeeCap: big.NewInt(10), Gas: 0, @@ -251,7 +250,7 @@ func mockTxn() *transaction { BlockHash: &types.ZeroHash, BlockNumber: argUintPtr(1), TxIndex: argUintPtr(2), - Type: argUint64(types.LegacyTx), + Type: argUint64(types.LegacyTxType), } return tt @@ -288,7 +287,7 @@ func TestTransaction_Encoding(t *testing.T) { tt := mockTxn() tt.GasTipCap = &gasTipCap tt.GasFeeCap = &gasFeeCap - tt.Type = argUint64(types.DynamicFeeTx) + tt.Type = argUint64(types.DynamicFeeTxType) testTransaction("testsuite/transaction-eip1559.json", tt) }) @@ -366,7 +365,8 @@ func Test_toBlock(t *testing.T) { require.NoError(t, err) expectedJSON := loadTestData(t, "testsuite/block-with-txn-full.json") - require.JSONEq(t, expectedJSON, string(res)) + str := string(res) + require.JSONEq(t, expectedJSON, str) } func loadTestData(t *testing.T, name string) string { diff --git a/state/executor.go b/state/executor.go index 362b103ad6..6331204d6a 100644 --- a/state/executor.go +++ b/state/executor.go @@ -327,7 +327,7 @@ var emptyFrom = types.Address{} // Write writes another transaction to the executor func (t *Transition) Write(txn *types.Transaction) error { - if txn.From() == emptyFrom && txn.Type() != types.StateTx { + if txn.From() == emptyFrom && txn.Type() != types.StateTxType { // Decrypt the from address signer := crypto.NewSigner(t.config, uint64(t.ctx.ChainID)) @@ -464,7 +464,7 @@ func (t *Transition) subGasLimitPrice(msg *types.Transaction) error { upfrontGasCost := new(big.Int).Mul(new(big.Int).SetUint64(msg.Gas()), msg.GetGasPrice(t.ctx.BaseFee.Uint64())) balanceCheck := new(big.Int).Set(upfrontGasCost) - if msg.Type() == types.DynamicFeeTx { + if msg.Type() == types.DynamicFeeTxType { balanceCheck.Add(balanceCheck, msg.Value()) balanceCheck.SetUint64(msg.Gas()) balanceCheck = balanceCheck.Mul(balanceCheck, msg.GasFeeCap()) @@ -510,7 +510,7 @@ func (t *Transition) checkDynamicFees(msg *types.Transaction) error { return nil } - if msg.Type() == types.DynamicFeeTx { + if msg.Type() == types.DynamicFeeTxType { if msg.GasFeeCap().BitLen() == 0 && msg.GasTipCap().BitLen() == 0 { return nil } @@ -604,7 +604,7 @@ func NewGasLimitReachedTransitionApplicationError(err error) *GasLimitReachedTra func (t *Transition) apply(msg *types.Transaction) (*runtime.ExecutionResult, error) { var err error - if msg.Type() == types.StateTx { + if msg.Type() == types.StateTxType { err = checkAndProcessStateTx(msg) } else { err = checkAndProcessTx(msg, t) @@ -702,7 +702,7 @@ func (t *Transition) apply(msg *types.Transaction) (*runtime.ExecutionResult, er // TODO - burning of base fee should not be done in the EVM // Burn some amount if the london hardfork is applied. // Basically, burn amount is just transferred to the current burn contract. - // if t.config.London && msg.Type() != types.StateTx { + // if t.config.London && msg.Type() != types.StateTxType { // burnAmount := new(big.Int).Mul(new(big.Int).SetUint64(result.GasUsed), t.ctx.BaseFee) // t.state.AddBalance(t.ctx.BurnContract, burnAmount) // } diff --git a/state/executor_test.go b/state/executor_test.go index 31428cbab5..cb04b09b2b 100644 --- a/state/executor_test.go +++ b/state/executor_test.go @@ -80,8 +80,7 @@ func Test_Transition_checkDynamicFees(t *testing.T) { { name: "happy path", baseFee: big.NewInt(100), - tx: types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, + tx: types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(100), GasTipCap: big.NewInt(100), }), @@ -94,8 +93,7 @@ func Test_Transition_checkDynamicFees(t *testing.T) { { name: "happy path with empty values", baseFee: big.NewInt(0), - tx: types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, + tx: types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(0), GasTipCap: big.NewInt(0), }), @@ -108,8 +106,7 @@ func Test_Transition_checkDynamicFees(t *testing.T) { { name: "gas fee cap less than base fee", baseFee: big.NewInt(20), - tx: types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, + tx: types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(10), GasTipCap: big.NewInt(0), }), @@ -124,8 +121,7 @@ func Test_Transition_checkDynamicFees(t *testing.T) { { name: "gas fee cap less than tip cap", baseFee: big.NewInt(5), - tx: types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, + tx: types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(10), GasTipCap: big.NewInt(15), }), diff --git a/state/transition_test.go b/state/transition_test.go index 1779d38c72..a7a64e0274 100644 --- a/state/transition_test.go +++ b/state/transition_test.go @@ -70,7 +70,7 @@ func TestSubGasLimitPrice(t *testing.T) { t.Parallel() transition := newTestTransition(tt.preState) - msg := types.NewTx(&types.MixedTxn{ + msg := types.NewTx(&types.LegacyTx{ From: tt.from, Gas: tt.gas, GasPrice: big.NewInt(tt.gasPrice), diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 41f1d1cc30..afcf3a3d40 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -334,9 +334,11 @@ func (t *stTransaction) At(i indexes, baseFee *big.Int) (*types.Transaction, err value = v } + var txData types.TxData + // if tx is not dynamic and accessList is not nil, create an access list transaction if !isDynamiFeeTx && accessList != nil { - return types.NewTx(&types.AccessListTxn{ + txData = &types.AccessListTxn{ From: t.From, To: t.To, Nonce: t.Nonce, @@ -345,27 +347,36 @@ func (t *stTransaction) At(i indexes, baseFee *big.Int) (*types.Transaction, err GasPrice: gasPrice, Input: hex.MustDecodeHex(t.Data[i.Data]), AccessList: accessList, - }), nil - } - - txType := types.LegacyTx - if isDynamiFeeTx { - txType = types.DynamicFeeTx - } - - return types.NewTx(&types.MixedTxn{ - Type: txType, - From: t.From, - To: t.To, - Nonce: t.Nonce, - Value: value, - Gas: t.GasLimit[i.Gas], - GasPrice: gasPrice, - GasFeeCap: t.MaxFeePerGas, - GasTipCap: t.MaxPriorityFeePerGas, - Input: hex.MustDecodeHex(t.Data[i.Data]), - AccessList: accessList, - }), nil + } + } + + if txData == nil { + if isDynamiFeeTx { + txData = &types.DynamicFeeTx{ + From: t.From, + To: t.To, + Nonce: t.Nonce, + Value: value, + Gas: t.GasLimit[i.Gas], + GasFeeCap: t.MaxFeePerGas, + GasTipCap: t.MaxPriorityFeePerGas, + Input: hex.MustDecodeHex(t.Data[i.Data]), + AccessList: accessList, + } + } else { + txData = &types.LegacyTx{ + From: t.From, + To: t.To, + Nonce: t.Nonce, + Value: value, + Gas: t.GasLimit[i.Gas], + GasPrice: gasPrice, + Input: hex.MustDecodeHex(t.Data[i.Data]), + } + } + } + + return types.NewTx(txData), nil } func (t *stTransaction) UnmarshalJSON(input []byte) error { diff --git a/txpool/queue_priced_test.go b/txpool/queue_priced_test.go index b619068454..4e172ff71f 100644 --- a/txpool/queue_priced_test.go +++ b/txpool/queue_priced_test.go @@ -23,43 +23,33 @@ func Test_maxPriceQueue(t *testing.T) { baseFee: 1000, unsorted: []*types.Transaction{ // Highest tx fee - types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, - GasPrice: big.NewInt(0), + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(2000), GasTipCap: big.NewInt(500), }), // Lowest tx fee - types.NewTx(&types.MixedTxn{ - Type: types.LegacyTx, + types.NewTx(&types.LegacyTx{ GasPrice: big.NewInt(100), }), // Middle tx fee - types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, - GasPrice: big.NewInt(0), + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(1500), GasTipCap: big.NewInt(200), }), }, sorted: []*types.Transaction{ // Highest tx fee - types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, - GasPrice: big.NewInt(0), + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(2000), GasTipCap: big.NewInt(500), }), // Middle tx fee - types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, - GasPrice: big.NewInt(0), + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(1500), GasTipCap: big.NewInt(200), }), // Lowest tx fee - types.NewTx(&types.MixedTxn{ - Type: types.LegacyTx, + types.NewTx(&types.LegacyTx{ GasPrice: big.NewInt(100), }), }, @@ -69,22 +59,19 @@ func Test_maxPriceQueue(t *testing.T) { baseFee: 1000, unsorted: []*types.Transaction{ // Highest tx fee - types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(2000), GasTipCap: big.NewInt(500), Nonce: 3, }), // Lowest tx fee - types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(2000), GasTipCap: big.NewInt(500), Nonce: 1, }), // Middle tx fee - types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(2000), GasTipCap: big.NewInt(500), Nonce: 2, @@ -92,105 +79,96 @@ func Test_maxPriceQueue(t *testing.T) { }, sorted: []*types.Transaction{ // Highest tx fee - types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(2000), GasTipCap: big.NewInt(500), Nonce: 1, }), // Middle tx fee - types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(2000), GasTipCap: big.NewInt(500), Nonce: 2, }), // Lowest tx fee - types.NewTx(&types.MixedTxn{ - Type: types.DynamicFeeTx, + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(2000), GasTipCap: big.NewInt(500), Nonce: 3, }), }, }, - { + { //nolint:dupl name: "sort txs without base fee by fee cap", baseFee: 0, unsorted: []*types.Transaction{ // Highest tx fee - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(3000), GasTipCap: big.NewInt(100), }), // Lowest tx fee - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(1000), GasTipCap: big.NewInt(100), }), // Middle tx fee - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(2000), GasTipCap: big.NewInt(100), }), }, sorted: []*types.Transaction{ // Highest tx fee - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.DynamicFeeTx{ GasTipCap: big.NewInt(100), GasFeeCap: big.NewInt(3000), }), // Middle tx fee - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(2000), GasTipCap: big.NewInt(100), }), // Lowest tx fee - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(1000), GasTipCap: big.NewInt(100), }), }, }, - { + { //nolint:dupl name: "sort txs without base fee by tip cap", baseFee: 0, unsorted: []*types.Transaction{ // Highest tx fee - types.NewTx(&types.MixedTxn{ - GasPrice: nil, + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(1000), GasTipCap: big.NewInt(300), }), // Lowest tx fee - types.NewTx(&types.MixedTxn{ - GasPrice: nil, + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(1000), GasTipCap: big.NewInt(100), }), // Middle tx fee - types.NewTx(&types.MixedTxn{ - GasPrice: nil, + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(1000), GasTipCap: big.NewInt(200), }), }, sorted: []*types.Transaction{ // Highest tx fee - types.NewTx(&types.MixedTxn{ - GasPrice: nil, + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(1000), GasTipCap: big.NewInt(300), }), // Middle tx fee - types.NewTx(&types.MixedTxn{ - GasPrice: nil, + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(1000), GasTipCap: big.NewInt(200), }), // Lowest tx fee - types.NewTx(&types.MixedTxn{ - GasPrice: nil, + types.NewTx(&types.DynamicFeeTx{ GasFeeCap: big.NewInt(1000), GasTipCap: big.NewInt(100), }), @@ -201,29 +179,29 @@ func Test_maxPriceQueue(t *testing.T) { baseFee: 0, unsorted: []*types.Transaction{ // Highest tx fee - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.LegacyTx{ GasPrice: big.NewInt(1000), }), // Lowest tx fee - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.LegacyTx{ GasPrice: big.NewInt(100), }), // Middle tx fee - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.LegacyTx{ GasPrice: big.NewInt(500), }), }, sorted: []*types.Transaction{ // Highest tx fee - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.LegacyTx{ GasPrice: big.NewInt(1000), }), // Middle tx fee - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.LegacyTx{ GasPrice: big.NewInt(500), }), // Lowest tx fee - types.NewTx(&types.MixedTxn{ + types.NewTx(&types.LegacyTx{ GasPrice: big.NewInt(100), }), }, @@ -298,21 +276,24 @@ func generateTx(i int) *types.Transaction { s := rand.NewSource(int64(i)) r := rand.New(s) + var tx *types.Transaction + txTypes := []types.TxType{ - types.LegacyTx, - types.DynamicFeeTx, + types.LegacyTxType, + types.DynamicFeeTxType, } - tx := types.NewTx(&types.MixedTxn{ - Type: txTypes[r.Intn(len(txTypes))], - }) + txType := txTypes[r.Intn(len(txTypes))] - switch tx.Type() { - case types.LegacyTx: + switch txType { + case types.LegacyTxType: minGasPrice := 1000 * i maxGasPrice := 100000 * i + tx = types.NewTx(&types.LegacyTx{}) tx.SetGasPrice(new(big.Int).SetInt64(int64(rand.Intn(maxGasPrice-minGasPrice) + minGasPrice))) - case types.DynamicFeeTx: + case types.DynamicFeeTxType: + tx = types.NewTx(&types.DynamicFeeTx{}) + minGasFeeCap := 1000 * i maxGasFeeCap := 100000 * i tx.SetGasFeeCap(new(big.Int).SetInt64(int64(rand.Intn(maxGasFeeCap-minGasFeeCap) + minGasFeeCap))) diff --git a/txpool/txpool.go b/txpool/txpool.go index 53b041e7d1..3fcba4a526 100644 --- a/txpool/txpool.go +++ b/txpool/txpool.go @@ -544,7 +544,7 @@ func (p *TxPool) processEvent(event *blockchain.Event) { // constraints before entering the pool. func (p *TxPool) validateTx(tx *types.Transaction) error { // Check the transaction type. State transactions are not expected to be added to the pool - if tx.Type() == types.StateTx { + if tx.Type() == types.StateTxType { metrics.IncrCounter([]string{txPoolMetrics, "invalid_tx_type"}, 1) return fmt.Errorf("%w: type %d rejected, state transactions are not expected to be added to the pool", @@ -608,7 +608,7 @@ func (p *TxPool) validateTx(tx *types.Transaction) error { latestBlockGasLimit := currentHeader.GasLimit baseFee := p.GetBaseFee() // base fee is calculated for the next block - if tx.Type() == types.AccessListTx { + if tx.Type() == types.AccessListTxType { // Reject access list tx if berlin hardfork(eip-2930) is not enabled if !forks.Berlin { metrics.IncrCounter([]string{txPoolMetrics, "invalid_tx_type"}, 1) @@ -622,7 +622,7 @@ func (p *TxPool) validateTx(tx *types.Transaction) error { return ErrUnderpriced } - } else if tx.Type() == types.DynamicFeeTx { + } else if tx.Type() == types.DynamicFeeTxType { // Reject dynamic fee tx if london hardfork is not enabled if !forks.London { metrics.IncrCounter([]string{txPoolMetrics, "tx_type"}, 1) @@ -670,8 +670,8 @@ func (p *TxPool) validateTx(tx *types.Transaction) error { } } - // Check if the given tx is not underpriced if tx.GetGasPrice(baseFee).Cmp(new(big.Int).SetUint64(p.priceLimit)) < 0 { + // Make sure that the transaction is not underpriced metrics.IncrCounter([]string{txPoolMetrics, "underpriced_tx"}, 1) return ErrUnderpriced @@ -775,7 +775,7 @@ func (p *TxPool) addTx(origin txOrigin, tx *types.Transaction) error { } // add chainID to the tx - only dynamic fee tx - if tx.Type() == types.DynamicFeeTx { + if tx.Type() == types.DynamicFeeTxType { tx.SetChainID(p.chainID) } diff --git a/txpool/txpool_test.go b/txpool/txpool_test.go index 4e1ae0e369..72fc1af1f4 100644 --- a/txpool/txpool_test.go +++ b/txpool/txpool_test.go @@ -44,7 +44,7 @@ var ( ) // returns a new valid tx of slots size with the given nonce -func newTx(addr types.Address, nonce, slots uint64) *types.Transaction { +func newTx(addr types.Address, nonce, slots uint64, txType types.TxType) *types.Transaction { // base field should take 1 slot at least size := txSlotSize * (slots - 1) if size <= 0 { @@ -56,14 +56,24 @@ func newTx(addr types.Address, nonce, slots uint64) *types.Transaction { return nil } - return types.NewTx(&types.MixedTxn{ - From: addr, - Nonce: nonce, - Value: big.NewInt(1), - GasPrice: big.NewInt(0).SetUint64(defaultPriceLimit), - Gas: validGasLimit, - Input: input, - }) + tx := types.NewTxWithType(txType) + + switch txType { + case types.DynamicFeeTxType: + tx.SetGasFeeCap(big.NewInt(100)) + tx.SetGasTipCap(big.NewInt(100)) + + default: + tx.SetGasPrice(big.NewInt(0).SetUint64(defaultPriceLimit)) + } + + tx.SetFrom(addr) + tx.SetNonce(nonce) + tx.SetValue(big.NewInt(1)) + tx.SetGas(validGasLimit) + tx.SetInput(input) + + return tx } // returns a new txpool with default test config @@ -140,8 +150,7 @@ func TestAddTxErrors(t *testing.T) { t.Parallel() pool := setupPool() - tx := newTx(defaultAddr, 0, 1) - tx.SetTransactionType(types.StateTx) + tx := newTx(defaultAddr, 0, 1, types.StateTxType) err := pool.addTx(local, signTx(tx)) @@ -160,8 +169,7 @@ func TestAddTxErrors(t *testing.T) { pool := setupPool() pool.forks.RemoveFork(chain.London) - tx := newTx(defaultAddr, 0, 1) - tx.SetTransactionType(types.DynamicFeeTx) + tx := newTx(defaultAddr, 0, 1, types.DynamicFeeTxType) err := pool.addTx(local, signTx(tx)) @@ -179,7 +187,7 @@ func TestAddTxErrors(t *testing.T) { t.Parallel() pool := setupPool() - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) tx.SetValue(big.NewInt(-5)) assert.ErrorIs(t, @@ -192,7 +200,7 @@ func TestAddTxErrors(t *testing.T) { t.Parallel() pool := setupPool() - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) tx.SetValue(big.NewInt(1)) tx.SetGas(10000000000001) @@ -208,7 +216,7 @@ func TestAddTxErrors(t *testing.T) { t.Parallel() pool := setupPool() - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) assert.ErrorIs(t, pool.addTx(local, tx), @@ -220,7 +228,7 @@ func TestAddTxErrors(t *testing.T) { t.Parallel() pool := setupPool() - tx := newTx(addr1, 0, 1) + tx := newTx(addr1, 0, 1, types.LegacyTxType) // Sign with a private key that corresponds // to a different address @@ -237,7 +245,7 @@ func TestAddTxErrors(t *testing.T) { pool := setupPool() pool.priceLimit = 1000000 - tx := newTx(defaultAddr, 0, 1) // gasPrice == 1 + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) // gasPrice == 1 tx = signTx(tx) assert.ErrorIs(t, @@ -253,7 +261,7 @@ func TestAddTxErrors(t *testing.T) { // nonce is 1000000 so ErrNonceTooLow // doesn't get triggered - tx := newTx(defaultAddr, 1000000, 1) + tx := newTx(defaultAddr, 1000000, 1, types.LegacyTxType) tx = signTx(tx) assert.ErrorIs(t, @@ -269,7 +277,7 @@ func TestAddTxErrors(t *testing.T) { // fill the pool pool.gauge.increase(defaultMaxSlots) - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) tx = signTx(tx) assert.ErrorIs(t, @@ -286,7 +294,7 @@ func TestAddTxErrors(t *testing.T) { pool.gauge.increase(defaultMaxSlots - 1) // create tx requiring 1 slot - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) tx = signTx(tx) // enqueue tx @@ -298,7 +306,7 @@ func TestAddTxErrors(t *testing.T) { t.Parallel() pool := setupPool() - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) tx.SetGas(1) tx = signTx(tx) @@ -312,7 +320,7 @@ func TestAddTxErrors(t *testing.T) { t.Parallel() pool := setupPool() - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) tx = signTx(tx) // send the tx beforehand @@ -329,7 +337,7 @@ func TestAddTxErrors(t *testing.T) { t.Parallel() pool := setupPool() - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) tx.SetGasPrice(big.NewInt(200)) tx = signTx(tx) @@ -337,7 +345,7 @@ func TestAddTxErrors(t *testing.T) { assert.NoError(t, pool.addTx(local, tx)) <-pool.promoteReqCh - tx = newTx(defaultAddr, 0, 1) + tx = newTx(defaultAddr, 0, 1, types.LegacyTxType) tx.SetGasPrice(big.NewInt(100)) tx = signTx(tx) @@ -351,7 +359,7 @@ func TestAddTxErrors(t *testing.T) { t.Parallel() pool := setupPool() - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) // set oversized Input field data := make([]byte, 989898) @@ -373,7 +381,7 @@ func TestAddTxErrors(t *testing.T) { // faultyMockStore.GetNonce() == 99999 pool.store = faultyMockStore{} - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) tx = signTx(tx) assert.ErrorIs(t, @@ -386,7 +394,7 @@ func TestAddTxErrors(t *testing.T) { t.Parallel() pool := setupPool() - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) tx.GasPrice().SetUint64(1000000000000) tx = signTx(tx) @@ -432,7 +440,7 @@ func TestPruneAccountsWithNonceHoles(t *testing.T) { assert.NoError(t, err) pool.SetSigner(&mockSigner{}) - tx := newTx(addr1, 0, 1) + tx := newTx(addr1, 0, 1, types.LegacyTxType) // enqueue tx assert.NoError(t, pool.addTx(local, tx)) @@ -466,7 +474,7 @@ func TestPruneAccountsWithNonceHoles(t *testing.T) { assert.NoError(t, err) pool.SetSigner(&mockSigner{}) - tx := newTx(addr1, 5, 1) + tx := newTx(addr1, 5, 1, types.LegacyTxType) // enqueue tx assert.NoError(t, pool.addTx(local, tx)) @@ -510,7 +518,7 @@ func TestAddTxHighPressure(t *testing.T) { // enqueue tx go func() { assert.NoError(t, - pool.addTx(local, newTx(addr1, 0, 1)), + pool.addTx(local, newTx(addr1, 0, 1, types.LegacyTxType)), ) }() @@ -538,7 +546,7 @@ func TestAddTxHighPressure(t *testing.T) { assert.ErrorIs(t, ErrRejectFutureTx, - pool.addTx(local, newTx(addr1, 8, 1)), + pool.addTx(local, newTx(addr1, 8, 1, types.LegacyTxType)), ) acc := pool.accounts.get(addr1) @@ -564,7 +572,7 @@ func TestAddTxHighPressure(t *testing.T) { println("slots", slots, "max", pool.gauge.max) pool.gauge.increase(slots) - tx := newTx(addr1, 5, 1) + tx := newTx(addr1, 5, 1, types.LegacyTxType) assert.NoError(t, pool.addTx(local, tx)) _, exists := pool.index.get(tx.Hash()) @@ -582,7 +590,7 @@ func TestAddGossipTx(t *testing.T) { key, sender := tests.GenerateKeyAndAddr(t) signer := crypto.NewEIP155Signer(100, true) - tx := newTx(types.ZeroAddress, 1, 1) + tx := newTx(types.ZeroAddress, 1, 1, types.LegacyTxType) t.Run("node is a validator", func(t *testing.T) { t.Parallel() @@ -644,7 +652,7 @@ func TestDropKnownGossipTx(t *testing.T) { assert.NoError(t, err) pool.SetSigner(&mockSigner{}) - tx := newTx(addr1, 1, 1) + tx := newTx(addr1, 1, 1, types.LegacyTxType) // send tx as local assert.NoError(t, pool.addTx(local, tx)) @@ -676,7 +684,7 @@ func TestEnqueueHandler(t *testing.T) { pool.SetSigner(&mockSigner{}) // send higher nonce tx - err = pool.addTx(local, newTx(addr1, 10, 1)) // 10 > 0 + err = pool.addTx(local, newTx(addr1, 10, 1, types.LegacyTxType)) // 10 > 0 assert.NoError(t, err) assert.Equal(t, uint64(1), pool.gauge.read()) @@ -699,7 +707,7 @@ func TestEnqueueHandler(t *testing.T) { // send tx go func() { - err := pool.addTx(local, newTx(addr1, 10, 1)) // 10 < 20 + err := pool.addTx(local, newTx(addr1, 10, 1, types.LegacyTxType)) // 10 < 20 assert.EqualError(t, err, "nonce too low") }() @@ -722,7 +730,7 @@ func TestEnqueueHandler(t *testing.T) { pool.SetSigner(&mockSigner{}) // send tx - err = pool.addTx(local, newTx(addr1, 0, 1)) // 0 == 0 + err = pool.addTx(local, newTx(addr1, 0, 1, types.LegacyTxType)) // 0 == 0 assert.NoError(t, err) // catch pending promotion @@ -747,14 +755,14 @@ func TestEnqueueHandler(t *testing.T) { fillEnqueued := func(pool *TxPool, num uint64) { // first tx will signal promotion, grab the signal // but don't execute the handler - err := pool.addTx(local, newTx(addr1, 0, 1)) + err := pool.addTx(local, newTx(addr1, 0, 1, types.LegacyTxType)) assert.NoError(t, err) // catch pending promotion <-pool.promoteReqCh for i := uint64(1); i < num; i++ { - err := pool.addTx(local, newTx(addr1, i, 1)) + err := pool.addTx(local, newTx(addr1, i, 1, types.LegacyTxType)) assert.NoError(t, err) } } @@ -773,7 +781,7 @@ func TestEnqueueHandler(t *testing.T) { // send next expected tx go func() { - err := pool.addTx(local, newTx(addr1, 1, 1)) + err := pool.addTx(local, newTx(addr1, 1, 1, types.LegacyTxType)) assert.True(t, errors.Is(err, ErrMaxEnqueuedLimitReached)) }() @@ -803,7 +811,7 @@ func TestEnqueueHandler(t *testing.T) { // add 10 transaction in txpool i.e. max enqueued transactions for i := uint64(1); i <= 10; i++ { - err := pool.addTx(local, newTx(addr1, i, 1)) + err := pool.addTx(local, newTx(addr1, i, 1, types.LegacyTxType)) assert.NoError(t, err) } @@ -811,11 +819,11 @@ func TestEnqueueHandler(t *testing.T) { assert.Equal(t, uint64(0), pool.accounts.get(addr1).promoted.length()) assert.Equal(t, uint64(0), pool.accounts.get(addr1).getNonce()) - err = pool.addTx(local, newTx(addr1, 11, 1)) + err = pool.addTx(local, newTx(addr1, 11, 1, types.LegacyTxType)) assert.True(t, errors.Is(err, ErrMaxEnqueuedLimitReached)) // add the transaction with nextNonce i.e. nonce=0 - err = pool.addTx(local, newTx(addr1, uint64(0), 1)) + err = pool.addTx(local, newTx(addr1, uint64(0), 1, types.LegacyTxType)) assert.NoError(t, err) pool.handlePromoteRequest(<-pool.promoteReqCh) @@ -842,7 +850,7 @@ func TestAddTx(t *testing.T) { gasPrice, slots uint64, ) *types.Transaction { - tx := newTx(addr, nonce, slots) + tx := newTx(addr, nonce, slots, types.LegacyTxType) tx.GasPrice().SetUint64(gasPrice) return tx @@ -903,7 +911,7 @@ func TestAddTx(t *testing.T) { gasPrice, slots uint64, ) *types.Transaction { - tx := newTx(addr, nonce, slots) + tx := newTx(addr, nonce, slots, types.LegacyTxType) tx.GasPrice().SetUint64(gasPrice) return tx @@ -959,7 +967,7 @@ func TestAddTx(t *testing.T) { gasPrice, slots uint64, ) *types.Transaction { - tx := newTx(addr, nonce, slots) + tx := newTx(addr, nonce, slots, types.LegacyTxType) tx.GasPrice().SetUint64(gasPrice) return tx @@ -1060,7 +1068,7 @@ func TestAddTx(t *testing.T) { gasPrice, slots uint64, ) *types.Transaction { - tx := newTx(addr, nonce, slots) + tx := newTx(addr, nonce, slots, types.LegacyTxType) tx.GasPrice().SetUint64(gasPrice) return tx @@ -1119,7 +1127,7 @@ func TestAddTx(t *testing.T) { gasPrice, slots uint64, ) *types.Transaction { - tx := newTx(addr, nonce, slots) + tx := newTx(addr, nonce, slots, types.LegacyTxType) tx.GasPrice().SetUint64(gasPrice) return tx @@ -1218,7 +1226,7 @@ func TestPromoteHandler(t *testing.T) { assert.Equal(t, uint64(0), pool.accounts.get(addr1).promoted.length()) // enqueue higher nonce tx - tx := newTx(addr1, 10, 1) + tx := newTx(addr1, 10, 1, types.LegacyTxType) err = pool.addTx(local, tx) assert.NoError(t, err) @@ -1251,7 +1259,7 @@ func TestPromoteHandler(t *testing.T) { assert.NoError(t, err) pool.SetSigner(&mockSigner{}) - tx := newTx(addr1, 0, 1) + tx := newTx(addr1, 0, 1, types.LegacyTxType) err = pool.addTx(local, tx) assert.NoError(t, err) @@ -1294,7 +1302,7 @@ func TestPromoteHandler(t *testing.T) { txs := make([]*types.Transaction, 10) for i := 0; i < 10; i++ { - txs[i] = newTx(addr1, uint64(i), 1) + txs[i] = newTx(addr1, uint64(i), 1, types.LegacyTxType) } // send the first (expected) tx -> signals promotion @@ -1352,7 +1360,7 @@ func TestPromoteHandler(t *testing.T) { txs := make([]*types.Transaction, 20) for i := 0; i < 20; i++ { - txs[i] = newTx(addr1, uint64(i), 1) + txs[i] = newTx(addr1, uint64(i), 1, types.LegacyTxType) } for _, tx := range txs { @@ -1393,11 +1401,11 @@ func TestResetAccount(t *testing.T) { { name: "prune all txs with low nonce", txs: []*types.Transaction{ - newTx(addr1, 0, 1), - newTx(addr1, 1, 1), - newTx(addr1, 2, 1), - newTx(addr1, 3, 1), - newTx(addr1, 4, 1), + newTx(addr1, 0, 1, types.LegacyTxType), + newTx(addr1, 1, 1, types.LegacyTxType), + newTx(addr1, 2, 1, types.LegacyTxType), + newTx(addr1, 3, 1, types.LegacyTxType), + newTx(addr1, 4, 1, types.LegacyTxType), }, newNonce: 5, expected: result{ @@ -1412,9 +1420,9 @@ func TestResetAccount(t *testing.T) { { name: "no low nonce txs to prune", txs: []*types.Transaction{ - newTx(addr1, 2, 1), - newTx(addr1, 3, 1), - newTx(addr1, 4, 1), + newTx(addr1, 2, 1, types.LegacyTxType), + newTx(addr1, 3, 1, types.LegacyTxType), + newTx(addr1, 4, 1, types.LegacyTxType), }, newNonce: 1, expected: result{ @@ -1429,9 +1437,9 @@ func TestResetAccount(t *testing.T) { { name: "prune some txs with low nonce", txs: []*types.Transaction{ - newTx(addr1, 7, 1), - newTx(addr1, 8, 1), - newTx(addr1, 9, 1), + newTx(addr1, 7, 1, types.LegacyTxType), + newTx(addr1, 8, 1, types.LegacyTxType), + newTx(addr1, 9, 1, types.LegacyTxType), }, newNonce: 8, expected: result{ @@ -1512,10 +1520,10 @@ func TestResetAccount(t *testing.T) { { name: "prune all txs with low nonce", txs: []*types.Transaction{ - newTx(addr1, 5, 1), - newTx(addr1, 6, 1), - newTx(addr1, 7, 1), - newTx(addr1, 8, 1), + newTx(addr1, 5, 1, types.LegacyTxType), + newTx(addr1, 6, 1, types.LegacyTxType), + newTx(addr1, 7, 1, types.LegacyTxType), + newTx(addr1, 8, 1, types.LegacyTxType), }, newNonce: 10, expected: result{ @@ -1530,9 +1538,9 @@ func TestResetAccount(t *testing.T) { { name: "no low nonce txs to prune", txs: []*types.Transaction{ - newTx(addr1, 2, 1), - newTx(addr1, 3, 1), - newTx(addr1, 4, 1), + newTx(addr1, 2, 1, types.LegacyTxType), + newTx(addr1, 3, 1, types.LegacyTxType), + newTx(addr1, 4, 1, types.LegacyTxType), }, newNonce: 1, expected: result{ @@ -1547,10 +1555,10 @@ func TestResetAccount(t *testing.T) { { name: "prune some txs with low nonce", txs: []*types.Transaction{ - newTx(addr1, 4, 1), - newTx(addr1, 5, 1), - newTx(addr1, 8, 1), - newTx(addr1, 9, 1), + newTx(addr1, 4, 1, types.LegacyTxType), + newTx(addr1, 5, 1, types.LegacyTxType), + newTx(addr1, 8, 1, types.LegacyTxType), + newTx(addr1, 9, 1, types.LegacyTxType), }, newNonce: 6, expected: result{ @@ -1566,9 +1574,9 @@ func TestResetAccount(t *testing.T) { name: "pruning low nonce signals promotion", signal: true, txs: []*types.Transaction{ - newTx(addr1, 8, 1), - newTx(addr1, 9, 1), - newTx(addr1, 10, 1), + newTx(addr1, 8, 1, types.LegacyTxType), + newTx(addr1, 9, 1, types.LegacyTxType), + newTx(addr1, 10, 1, types.LegacyTxType), }, newNonce: 9, expected: result{ @@ -1649,14 +1657,14 @@ func TestResetAccount(t *testing.T) { name: "prune all txs with low nonce", txs: []*types.Transaction{ // promoted - newTx(addr1, 0, 1), - newTx(addr1, 1, 1), - newTx(addr1, 2, 1), - newTx(addr1, 3, 1), + newTx(addr1, 0, 1, types.LegacyTxType), + newTx(addr1, 1, 1, types.LegacyTxType), + newTx(addr1, 2, 1, types.LegacyTxType), + newTx(addr1, 3, 1, types.LegacyTxType), // enqueued - newTx(addr1, 5, 1), - newTx(addr1, 6, 1), - newTx(addr1, 8, 1), + newTx(addr1, 5, 1, types.LegacyTxType), + newTx(addr1, 6, 1, types.LegacyTxType), + newTx(addr1, 8, 1, types.LegacyTxType), }, newNonce: 10, expected: result{ @@ -1673,11 +1681,11 @@ func TestResetAccount(t *testing.T) { name: "no low nonce txs to prune", txs: []*types.Transaction{ // promoted - newTx(addr1, 5, 1), - newTx(addr1, 6, 1), + newTx(addr1, 5, 1, types.LegacyTxType), + newTx(addr1, 6, 1, types.LegacyTxType), // enqueued - newTx(addr1, 9, 1), - newTx(addr1, 10, 1), + newTx(addr1, 9, 1, types.LegacyTxType), + newTx(addr1, 10, 1, types.LegacyTxType), }, newNonce: 3, expected: result{ @@ -1694,13 +1702,13 @@ func TestResetAccount(t *testing.T) { name: "prune all promoted and 1 enqueued", txs: []*types.Transaction{ // promoted - newTx(addr1, 1, 1), - newTx(addr1, 2, 1), - newTx(addr1, 3, 1), + newTx(addr1, 1, 1, types.LegacyTxType), + newTx(addr1, 2, 1, types.LegacyTxType), + newTx(addr1, 3, 1, types.LegacyTxType), // enqueued - newTx(addr1, 5, 1), - newTx(addr1, 8, 1), - newTx(addr1, 9, 1), + newTx(addr1, 5, 1, types.LegacyTxType), + newTx(addr1, 8, 1, types.LegacyTxType), + newTx(addr1, 9, 1, types.LegacyTxType), }, newNonce: 6, expected: result{ @@ -1718,14 +1726,14 @@ func TestResetAccount(t *testing.T) { signal: true, txs: []*types.Transaction{ // promoted - newTx(addr1, 2, 1), - newTx(addr1, 3, 1), - newTx(addr1, 4, 1), - newTx(addr1, 5, 1), + newTx(addr1, 2, 1, types.LegacyTxType), + newTx(addr1, 3, 1, types.LegacyTxType), + newTx(addr1, 4, 1, types.LegacyTxType), + newTx(addr1, 5, 1, types.LegacyTxType), // enqueued - newTx(addr1, 8, 1), - newTx(addr1, 9, 1), - newTx(addr1, 10, 1), + newTx(addr1, 8, 1, types.LegacyTxType), + newTx(addr1, 9, 1, types.LegacyTxType), + newTx(addr1, 10, 1, types.LegacyTxType), }, newNonce: 8, expected: result{ @@ -1811,7 +1819,7 @@ func TestPop(t *testing.T) { pool.SetSigner(&mockSigner{}) // send 1 tx and promote it - tx1 := newTx(addr1, 0, 1) + tx1 := newTx(addr1, 0, 1, types.LegacyTxType) err = pool.addTx(local, tx1) assert.NoError(t, err) @@ -1847,7 +1855,7 @@ func TestDrop(t *testing.T) { pool.SetSigner(&mockSigner{}) // send 1 tx and promote it - tx1 := newTx(addr1, 0, 1) + tx1 := newTx(addr1, 0, 1, types.LegacyTxType) err = pool.addTx(local, tx1) assert.NoError(t, err) @@ -1884,7 +1892,7 @@ func TestDemote(t *testing.T) { pool.SetSigner(&mockSigner{}) // send tx - err = pool.addTx(local, newTx(addr1, 0, 1)) + err = pool.addTx(local, newTx(addr1, 0, 1, types.LegacyTxType)) assert.NoError(t, err) pool.handlePromoteRequest(<-pool.promoteReqCh) @@ -1916,7 +1924,7 @@ func TestDemote(t *testing.T) { pool.SetSigner(&mockSigner{}) // send tx - err = pool.addTx(local, newTx(addr1, 0, 1)) + err = pool.addTx(local, newTx(addr1, 0, 1, types.LegacyTxType)) assert.NoError(t, err) pool.handlePromoteRequest(<-pool.promoteReqCh) @@ -1978,7 +1986,7 @@ func Test_updateAccountSkipsCounts(t *testing.T) { pool.SetSigner(&mockSigner{}) - tx := newTx(addr1, 0, 1) + tx := newTx(addr1, 0, 1, types.LegacyTxType) sendTx(t, pool, tx, true) accountMap := pool.accounts.get(addr1) @@ -2013,7 +2021,7 @@ func Test_updateAccountSkipsCounts(t *testing.T) { pool.SetSigner(&mockSigner{}) - tx := newTx(addr1, 1, 1) // set non-zero nonce to prevent the tx from being added + tx := newTx(addr1, 1, 1, types.LegacyTxType) // set non-zero nonce to prevent the tx from being added sendTx(t, pool, tx, false) accountMap := pool.accounts.get(addr1) @@ -2048,7 +2056,7 @@ func Test_updateAccountSkipsCounts(t *testing.T) { pool.SetSigner(&mockSigner{}) - tx := newTx(addr1, 0, 1) + tx := newTx(addr1, 0, 1, types.LegacyTxType) sendTx(t, pool, tx, true) accountMap := pool.accounts.get(addr1) @@ -2093,25 +2101,25 @@ func Test_updateAccountSkipsCounts(t *testing.T) { accountMap := pool.accounts.initOnce(addr1, storeNonce) accountMap.enqueued.push(&types.Transaction{ - Inner: &types.MixedTxn{ + Inner: &types.LegacyTx{ Nonce: storeNonce + 2, Hash: types.StringToHash("0xffa"), }, }) accountMap.enqueued.push(&types.Transaction{ - Inner: &types.MixedTxn{ + Inner: &types.LegacyTx{ Nonce: storeNonce + 4, Hash: types.StringToHash("0xff1"), }, }) accountMap.promoted.push(&types.Transaction{ - Inner: &types.MixedTxn{ + Inner: &types.LegacyTx{ Nonce: storeNonce, Hash: types.StringToHash("0xff2"), }, }) accountMap.promoted.push(&types.Transaction{ - Inner: &types.MixedTxn{ + Inner: &types.LegacyTx{ Nonce: storeNonce + 1, Hash: types.StringToHash("0xff3"), }, @@ -2169,7 +2177,7 @@ func Test_TxPool_validateTx(t *testing.T) { _, err := rand.Read(input) require.NoError(t, err) - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) tx.SetTo(nil) tx.SetInput(input) @@ -2188,7 +2196,7 @@ func Test_TxPool_validateTx(t *testing.T) { _, err := rand.Read(input) require.NoError(t, err) - tx := newTx(defaultAddr, 0, 1) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) tx.SetTo(nil) tx.SetInput(input) tx.SetGasPrice(new(big.Int).SetUint64(pool.GetBaseFee())) @@ -2204,8 +2212,7 @@ func Test_TxPool_validateTx(t *testing.T) { pool := setupPool() - tx := newTx(defaultAddr, 0, 1) - tx.SetTransactionType(types.DynamicFeeTx) + tx := newTx(defaultAddr, 0, 1, types.DynamicFeeTxType) tx.SetGasFeeCap(big.NewInt(1100)) tx.SetGasTipCap(big.NewInt(10)) @@ -2217,8 +2224,7 @@ func Test_TxPool_validateTx(t *testing.T) { pool := setupPool() - tx := newTx(defaultAddr, 0, 1) - tx.SetTransactionType(types.DynamicFeeTx) + tx := newTx(defaultAddr, 0, 1, types.DynamicFeeTxType) tx.SetGasFeeCap(big.NewInt(100)) tx.SetGasTipCap(big.NewInt(10)) @@ -2233,8 +2239,7 @@ func Test_TxPool_validateTx(t *testing.T) { pool := setupPool() - tx := newTx(defaultAddr, 0, 1) - tx.SetTransactionType(types.DynamicFeeTx) + tx := newTx(defaultAddr, 0, 1, types.DynamicFeeTxType) tx.SetGasFeeCap(big.NewInt(10000)) tx.SetGasTipCap(big.NewInt(100000)) @@ -2250,8 +2255,7 @@ func Test_TxPool_validateTx(t *testing.T) { pool := setupPool() // undefined gas tip cap - tx := newTx(defaultAddr, 0, 1) - tx.SetTransactionType(types.DynamicFeeTx) + tx := newTx(defaultAddr, 0, 1, types.LegacyTxType) tx.SetGasFeeCap(big.NewInt(10000)) signedTx := signTx(tx) @@ -2263,8 +2267,7 @@ func Test_TxPool_validateTx(t *testing.T) { ) // undefined gas fee cap - tx = newTx(defaultAddr, 1, 1) - tx.SetTransactionType(types.DynamicFeeTx) + tx = newTx(defaultAddr, 1, 1, types.LegacyTxType) tx.SetGasTipCap(big.NewInt(1000)) signedTx = signTx(tx) @@ -2284,8 +2287,7 @@ func Test_TxPool_validateTx(t *testing.T) { pool := setupPool() // very high gas fee cap - tx := newTx(defaultAddr, 0, 1) - tx.SetTransactionType(types.DynamicFeeTx) + tx := newTx(defaultAddr, 0, 1, types.DynamicFeeTxType) tx.SetGasFeeCap(new(big.Int).SetBit(new(big.Int), bitLength, 1)) tx.SetGasTipCap(new(big.Int)) @@ -2295,8 +2297,7 @@ func Test_TxPool_validateTx(t *testing.T) { ) // very high gas tip cap - tx = newTx(defaultAddr, 1, 1) - tx.SetTransactionType(types.DynamicFeeTx) + tx = newTx(defaultAddr, 1, 1, types.DynamicFeeTxType) tx.SetGasTipCap(new(big.Int).SetBit(new(big.Int), bitLength, 1)) tx.SetGasFeeCap(new(big.Int)) @@ -2312,8 +2313,7 @@ func Test_TxPool_validateTx(t *testing.T) { pool.forks = chain.AllForksEnabled.Copy() pool.forks.RemoveFork(chain.London) - tx := newTx(defaultAddr, 0, 1) - tx.SetTransactionType(types.DynamicFeeTx) + tx := newTx(defaultAddr, 0, 1, types.DynamicFeeTxType) tx.SetGasFeeCap(big.NewInt(10000)) tx.SetGasTipCap(big.NewInt(100000)) @@ -2397,30 +2397,30 @@ func TestResetAccounts_Promoted(t *testing.T) { allTxs := map[types.Address][]*types.Transaction{ addr1: { - eoa1.signTx(t, newTx(addr1, 0, 1), signerEIP155), // will be pruned - eoa1.signTx(t, newTx(addr1, 1, 1), signerEIP155), // will be pruned - eoa1.signTx(t, newTx(addr1, 2, 1), signerEIP155), // will be pruned - eoa1.signTx(t, newTx(addr1, 3, 1), signerEIP155), // will be pruned + eoa1.signTx(t, newTx(addr1, 0, 1, types.LegacyTxType), signerEIP155), // will be pruned + eoa1.signTx(t, newTx(addr1, 1, 1, types.LegacyTxType), signerEIP155), // will be pruned + eoa1.signTx(t, newTx(addr1, 2, 1, types.LegacyTxType), signerEIP155), // will be pruned + eoa1.signTx(t, newTx(addr1, 3, 1, types.LegacyTxType), signerEIP155), // will be pruned }, addr2: { - eoa2.signTx(t, newTx(addr2, 0, 1), signerEIP155), // will be pruned - eoa2.signTx(t, newTx(addr2, 1, 1), signerEIP155), // will be pruned + eoa2.signTx(t, newTx(addr2, 0, 1, types.LegacyTxType), signerEIP155), // will be pruned + eoa2.signTx(t, newTx(addr2, 1, 1, types.LegacyTxType), signerEIP155), // will be pruned }, addr3: { - eoa3.signTx(t, newTx(addr3, 0, 1), signerEIP155), // will be pruned - eoa3.signTx(t, newTx(addr3, 1, 1), signerEIP155), // will be pruned - eoa3.signTx(t, newTx(addr3, 2, 1), signerEIP155), // will be pruned + eoa3.signTx(t, newTx(addr3, 0, 1, types.LegacyTxType), signerEIP155), // will be pruned + eoa3.signTx(t, newTx(addr3, 1, 1, types.LegacyTxType), signerEIP155), // will be pruned + eoa3.signTx(t, newTx(addr3, 2, 1, types.LegacyTxType), signerEIP155), // will be pruned }, addr4: { // all txs will be pruned - eoa4.signTx(t, newTx(addr4, 0, 1), signerEIP155), // will be pruned - eoa4.signTx(t, newTx(addr4, 1, 1), signerEIP155), // will be pruned - eoa4.signTx(t, newTx(addr4, 2, 1), signerEIP155), // will be pruned - eoa4.signTx(t, newTx(addr4, 3, 1), signerEIP155), // will be pruned - eoa4.signTx(t, newTx(addr4, 4, 1), signerEIP155), // will be pruned + eoa4.signTx(t, newTx(addr4, 0, 1, types.LegacyTxType), signerEIP155), // will be pruned + eoa4.signTx(t, newTx(addr4, 1, 1, types.LegacyTxType), signerEIP155), // will be pruned + eoa4.signTx(t, newTx(addr4, 2, 1, types.LegacyTxType), signerEIP155), // will be pruned + eoa4.signTx(t, newTx(addr4, 3, 1, types.LegacyTxType), signerEIP155), // will be pruned + eoa4.signTx(t, newTx(addr4, 4, 1, types.LegacyTxType), signerEIP155), // will be pruned }, } @@ -2535,22 +2535,22 @@ func TestResetAccounts_Enqueued(t *testing.T) { allTxs := map[types.Address][]*types.Transaction{ addr1: { - eoa1.signTx(t, newTx(addr1, 3, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 4, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 5, 1), signerEIP155), + eoa1.signTx(t, newTx(addr1, 3, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 4, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 5, 1, types.LegacyTxType), signerEIP155), }, addr2: { - eoa2.signTx(t, newTx(addr2, 2, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 3, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 4, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 5, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 6, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 7, 1), signerEIP155), + eoa2.signTx(t, newTx(addr2, 2, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 3, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 4, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 5, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 6, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 7, 1, types.LegacyTxType), signerEIP155), }, addr3: { - eoa3.signTx(t, newTx(addr3, 7, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 8, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 9, 1), signerEIP155), + eoa3.signTx(t, newTx(addr3, 7, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 8, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 9, 1, types.LegacyTxType), signerEIP155), }, } newNonces := map[types.Address]uint64{ @@ -2637,21 +2637,21 @@ func TestResetAccounts_Enqueued(t *testing.T) { allTxs := map[types.Address][]*types.Transaction{ addr1: { - newTx(addr1, 1, 1), - newTx(addr1, 2, 1), - newTx(addr1, 3, 1), - newTx(addr1, 4, 1), + newTx(addr1, 1, 1, types.LegacyTxType), + newTx(addr1, 2, 1, types.LegacyTxType), + newTx(addr1, 3, 1, types.LegacyTxType), + newTx(addr1, 4, 1, types.LegacyTxType), }, addr2: { - newTx(addr2, 3, 3), - newTx(addr2, 4, 3), - newTx(addr2, 5, 3), - newTx(addr2, 6, 3), + newTx(addr2, 3, 3, types.LegacyTxType), + newTx(addr2, 4, 3, types.LegacyTxType), + newTx(addr2, 5, 3, types.LegacyTxType), + newTx(addr2, 6, 3, types.LegacyTxType), }, addr3: { - newTx(addr3, 7, 1), - newTx(addr3, 8, 1), - newTx(addr3, 9, 1), + newTx(addr3, 7, 1, types.LegacyTxType), + newTx(addr3, 8, 1, types.LegacyTxType), + newTx(addr3, 9, 1, types.LegacyTxType), }, } newNonces := map[types.Address]uint64{ @@ -2728,19 +2728,19 @@ func TestExecutablesOrder(t *testing.T) { newPricedTx := func( addr types.Address, nonce, gasPrice uint64, gasFeeCap uint64, value uint64) *types.Transaction { - tx := newTx(addr, nonce, 1) - tx.SetValue(new(big.Int).SetUint64(value)) + var tx *types.Transaction if gasPrice == 0 { - tx.SetTransactionType(types.DynamicFeeTx) + tx = newTx(addr, nonce, 1, types.DynamicFeeTxType) tx.SetGasFeeCap(new(big.Int).SetUint64(gasFeeCap)) tx.SetGasTipCap(new(big.Int).SetUint64(2)) - tx.SetGasPrice(big.NewInt(0)) } else { - tx.SetTransactionType(types.LegacyTx) + tx = newTx(addr, nonce, 1, types.LegacyTxType) tx.SetGasPrice(new(big.Int).SetUint64(gasPrice)) } + tx.SetValue(new(big.Int).SetUint64(value)) + return tx } @@ -2915,8 +2915,10 @@ func TestExecutablesOrder(t *testing.T) { // verify the highest priced transactions // were processed first for i, tx := range successful { - require.Equal(t, test.expectedPriceOrder[i][0], tx.GasPrice().Uint64()) - require.Equal(t, test.expectedPriceOrder[i][1], tx.Value().Uint64()) + if tx.Type() != types.DynamicFeeTxType { + require.Equal(t, test.expectedPriceOrder[i][0], tx.GasPrice().Uint64()) + require.Equal(t, test.expectedPriceOrder[i][1], tx.Value().Uint64()) + } } }) } @@ -2972,23 +2974,23 @@ func TestRecovery(t *testing.T) { name: "unrecoverable drops account", allTxs: map[types.Address][]statusTx{ addr1: { - {newTx(addr1, 0, 1), ok}, - {newTx(addr1, 1, 1), unrecoverable}, - {newTx(addr1, 2, 1), recoverable}, - {newTx(addr1, 3, 1), recoverable}, - {newTx(addr1, 4, 1), recoverable}, + {newTx(addr1, 0, 1, types.LegacyTxType), ok}, + {newTx(addr1, 1, 1, types.LegacyTxType), unrecoverable}, + {newTx(addr1, 2, 1, types.LegacyTxType), recoverable}, + {newTx(addr1, 3, 1, types.LegacyTxType), recoverable}, + {newTx(addr1, 4, 1, types.LegacyTxType), recoverable}, }, addr2: { - {newTx(addr2, 9, 1), unrecoverable}, - {newTx(addr2, 10, 1), recoverable}, + {newTx(addr2, 9, 1, types.LegacyTxType), unrecoverable}, + {newTx(addr2, 10, 1, types.LegacyTxType), recoverable}, }, addr3: { - {newTx(addr3, 5, 1), ok}, - {newTx(addr3, 6, 1), recoverable}, - {newTx(addr3, 7, 1), recoverable}, - {newTx(addr3, 8, 1), recoverable}, + {newTx(addr3, 5, 1, types.LegacyTxType), ok}, + {newTx(addr3, 6, 1, types.LegacyTxType), recoverable}, + {newTx(addr3, 7, 1, types.LegacyTxType), recoverable}, + {newTx(addr3, 8, 1, types.LegacyTxType), recoverable}, }, }, expected: result{ @@ -3018,15 +3020,15 @@ func TestRecovery(t *testing.T) { name: "recoverable remains in account", allTxs: map[types.Address][]statusTx{ addr1: { - {newTx(addr1, 0, 1), ok}, - {newTx(addr1, 1, 1), ok}, - {newTx(addr1, 2, 1), ok}, - {newTx(addr1, 3, 1), recoverable}, - {newTx(addr1, 4, 1), recoverable}, + {newTx(addr1, 0, 1, types.LegacyTxType), ok}, + {newTx(addr1, 1, 1, types.LegacyTxType), ok}, + {newTx(addr1, 2, 1, types.LegacyTxType), ok}, + {newTx(addr1, 3, 1, types.LegacyTxType), recoverable}, + {newTx(addr1, 4, 1, types.LegacyTxType), recoverable}, }, addr2: { - {newTx(addr2, 9, 1), recoverable}, - {newTx(addr2, 10, 1), recoverable}, + {newTx(addr2, 9, 1, types.LegacyTxType), recoverable}, + {newTx(addr2, 10, 1, types.LegacyTxType), recoverable}, }, }, expected: result{ @@ -3147,40 +3149,40 @@ func TestGetTxs(t *testing.T) { name: "get promoted txs", allTxs: map[types.Address][]*types.Transaction{ addr1: { - eoa1.signTx(t, newTx(addr1, 0, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 1, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 2, 1), signerEIP155), + eoa1.signTx(t, newTx(addr1, 0, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 1, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 2, 1, types.LegacyTxType), signerEIP155), }, addr2: { - eoa2.signTx(t, newTx(addr2, 0, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 1, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 2, 1), signerEIP155), + eoa2.signTx(t, newTx(addr2, 0, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 1, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 2, 1, types.LegacyTxType), signerEIP155), }, addr3: { - eoa3.signTx(t, newTx(addr3, 0, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 1, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 2, 1), signerEIP155), + eoa3.signTx(t, newTx(addr3, 0, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 1, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 2, 1, types.LegacyTxType), signerEIP155), }, }, expectedPromoted: map[types.Address][]*types.Transaction{ addr1: { - eoa1.signTx(t, newTx(addr1, 0, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 1, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 2, 1), signerEIP155), + eoa1.signTx(t, newTx(addr1, 0, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 1, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 2, 1, types.LegacyTxType), signerEIP155), }, addr2: { - eoa2.signTx(t, newTx(addr2, 0, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 1, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 2, 1), signerEIP155), + eoa2.signTx(t, newTx(addr2, 0, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 1, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 2, 1, types.LegacyTxType), signerEIP155), }, addr3: { - eoa3.signTx(t, newTx(addr3, 0, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 1, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 2, 1), signerEIP155), + eoa3.signTx(t, newTx(addr3, 0, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 1, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 2, 1, types.LegacyTxType), signerEIP155), }, }, }, @@ -3188,73 +3190,73 @@ func TestGetTxs(t *testing.T) { name: "get all txs", allTxs: map[types.Address][]*types.Transaction{ addr1: { - eoa1.signTx(t, newTx(addr1, 0, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 1, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 2, 1), signerEIP155), + eoa1.signTx(t, newTx(addr1, 0, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 1, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 2, 1, types.LegacyTxType), signerEIP155), // enqueued - eoa1.signTx(t, newTx(addr1, 10, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 11, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 12, 1), signerEIP155), + eoa1.signTx(t, newTx(addr1, 10, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 11, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 12, 1, types.LegacyTxType), signerEIP155), }, addr2: { - eoa2.signTx(t, newTx(addr2, 0, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 1, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 2, 1), signerEIP155), + eoa2.signTx(t, newTx(addr2, 0, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 1, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 2, 1, types.LegacyTxType), signerEIP155), // enqueued - eoa2.signTx(t, newTx(addr2, 10, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 11, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 12, 1), signerEIP155), + eoa2.signTx(t, newTx(addr2, 10, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 11, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 12, 1, types.LegacyTxType), signerEIP155), }, addr3: { - eoa3.signTx(t, newTx(addr3, 0, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 1, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 2, 1), signerEIP155), + eoa3.signTx(t, newTx(addr3, 0, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 1, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 2, 1, types.LegacyTxType), signerEIP155), // enqueued - eoa3.signTx(t, newTx(addr3, 10, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 11, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 12, 1), signerEIP155), + eoa3.signTx(t, newTx(addr3, 10, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 11, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 12, 1, types.LegacyTxType), signerEIP155), }, }, expectedPromoted: map[types.Address][]*types.Transaction{ addr1: { - eoa1.signTx(t, newTx(addr1, 0, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 1, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 2, 1), signerEIP155), + eoa1.signTx(t, newTx(addr1, 0, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 1, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 2, 1, types.LegacyTxType), signerEIP155), }, addr2: { - eoa2.signTx(t, newTx(addr2, 0, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 1, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 2, 1), signerEIP155), + eoa2.signTx(t, newTx(addr2, 0, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 1, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 2, 1, types.LegacyTxType), signerEIP155), }, addr3: { - eoa3.signTx(t, newTx(addr3, 0, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 1, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 2, 1), signerEIP155), + eoa3.signTx(t, newTx(addr3, 0, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 1, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 2, 1, types.LegacyTxType), signerEIP155), }, }, expectedEnqueued: map[types.Address][]*types.Transaction{ addr1: { - eoa1.signTx(t, newTx(addr1, 10, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 11, 1), signerEIP155), - eoa1.signTx(t, newTx(addr1, 12, 1), signerEIP155), + eoa1.signTx(t, newTx(addr1, 10, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 11, 1, types.LegacyTxType), signerEIP155), + eoa1.signTx(t, newTx(addr1, 12, 1, types.LegacyTxType), signerEIP155), }, addr2: { - eoa2.signTx(t, newTx(addr2, 10, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 11, 1), signerEIP155), - eoa2.signTx(t, newTx(addr2, 12, 1), signerEIP155), + eoa2.signTx(t, newTx(addr2, 10, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 11, 1, types.LegacyTxType), signerEIP155), + eoa2.signTx(t, newTx(addr2, 12, 1, types.LegacyTxType), signerEIP155), }, addr3: { - eoa3.signTx(t, newTx(addr3, 10, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 11, 1), signerEIP155), - eoa3.signTx(t, newTx(addr3, 12, 1), signerEIP155), + eoa3.signTx(t, newTx(addr3, 10, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 11, 1, types.LegacyTxType), signerEIP155), + eoa3.signTx(t, newTx(addr3, 12, 1, types.LegacyTxType), signerEIP155), }, }, }, @@ -3438,7 +3440,7 @@ func TestBatchTx_SingleAccount(t *testing.T) { // run max number of addTx concurrently for i := 0; i < int(defaultMaxAccountEnqueued); i++ { go func(i uint64) { - tx := newTx(addr, i, 1) + tx := newTx(addr, i, 1, types.LegacyTxType) tx.ComputeHash() @@ -3524,7 +3526,7 @@ func TestAddTxsInOrder(t *testing.T) { } for j := uint64(0); j < defaultMaxAccountEnqueued; j++ { - addrsTxs[i].txs[j] = newTx(addrsTxs[i].addr, j, uint64(1)) + addrsTxs[i].txs[j] = newTx(addrsTxs[i].addr, j, uint64(1), types.LegacyTxType) } } @@ -3643,8 +3645,7 @@ func TestAddTx_TxReplacement(t *testing.T) { key *ecdsa.PrivateKey, addr types.Address) *types.Transaction { t.Helper() - tx := newTx(addr, nonce, 1) - tx.SetTransactionType(types.DynamicFeeTx) + tx := newTx(addr, nonce, 1, types.DynamicFeeTxType) tx.SetInput(nil) tx.SetGasPrice(nil) tx.SetGasTipCap(new(big.Int).SetUint64(gasTipCap)) @@ -3663,7 +3664,7 @@ func TestAddTx_TxReplacement(t *testing.T) { key *ecdsa.PrivateKey, addr types.Address) *types.Transaction { t.Helper() - tx := newTx(addr, nonce, 1) + tx := newTx(addr, nonce, 1, types.LegacyTxType) tx.SetInput(nil) tx.SetGasPrice(new(big.Int).SetUint64(gasPrice)) @@ -3755,7 +3756,7 @@ func BenchmarkAddTxTime(b *testing.B) { b.Fatal(err) } - signedTx, err := signer.SignTx(newTx(crypto.PubKeyToAddress(&key.PublicKey), 0, 1), key) + signedTx, err := signer.SignTx(newTx(crypto.PubKeyToAddress(&key.PublicKey), 0, 1, types.LegacyTxType), key) if err != nil { b.Fatal(err) } @@ -3787,7 +3788,7 @@ func BenchmarkAddTxTime(b *testing.B) { txs := make([]*types.Transaction, defaultMaxAccountEnqueued) for i := range txs { - txs[i], err = signer.SignTx(newTx(addr, uint64(i), uint64(1)), key) + txs[i], err = signer.SignTx(newTx(addr, uint64(i), uint64(1), types.LegacyTxType), key) if err != nil { b.Fatal(err) } diff --git a/types/access_list_tx.go b/types/access_list_tx.go index f4c8687074..2a3b5a01f6 100644 --- a/types/access_list_tx.go +++ b/types/access_list_tx.go @@ -1,6 +1,11 @@ package types -import "math/big" +import ( + "fmt" + "math/big" + + "github.com/umbracle/fastrlp" +) type TxAccessList []AccessTuple @@ -40,6 +45,65 @@ func (al TxAccessList) Copy() TxAccessList { return newAccessList } +func (al TxAccessList) unmarshallRLPFrom(p *fastrlp.Parser, accessListVV []*fastrlp.Value) error { + for i, accessTupleVV := range accessListVV { + accessTupleElems, err := accessTupleVV.GetElems() + if err != nil { + return err + } + + // Read the address + addressVV := accessTupleElems[0] + + addressBytes, err := addressVV.Bytes() + if err != nil { + return err + } + + al[i].Address = BytesToAddress(addressBytes) + + // Read the storage keys + storageKeysArrayVV := accessTupleElems[1] + + storageKeysElems, err := storageKeysArrayVV.GetElems() + if err != nil { + return err + } + + al[i].StorageKeys = make([]Hash, len(storageKeysElems)) + + for j, storageKeyVV := range storageKeysElems { + storageKeyBytes, err := storageKeyVV.Bytes() + if err != nil { + return err + } + + al[i].StorageKeys[j] = BytesToHash(storageKeyBytes) + } + } + + return nil +} + +func (al TxAccessList) marshallRLPWith(arena *fastrlp.Arena) *fastrlp.Value { + accessListVV := arena.NewArray() + + for _, accessTuple := range al { + accessTupleVV := arena.NewArray() + accessTupleVV.Set(arena.NewCopyBytes(accessTuple.Address.Bytes())) + + storageKeysVV := arena.NewArray() + for _, storageKey := range accessTuple.StorageKeys { + storageKeysVV.Set(arena.NewCopyBytes(storageKey.Bytes())) + } + + accessTupleVV.Set(storageKeysVV) + accessListVV.Set(accessTupleVV) + } + + return accessListVV +} + type AccessListTxn struct { Nonce uint64 GasPrice *big.Int @@ -55,7 +119,7 @@ type AccessListTxn struct { AccessList TxAccessList } -func (tx *AccessListTxn) transactionType() TxType { return AccessListTx } +func (tx *AccessListTxn) transactionType() TxType { return AccessListTxType } func (tx *AccessListTxn) chainID() *big.Int { return tx.ChainID } func (tx *AccessListTxn) input() []byte { return tx.Input } func (tx *AccessListTxn) gas() uint64 { return tx.Gas } @@ -133,3 +197,223 @@ func (tx *AccessListTxn) setAccessList(accessList TxAccessList) { func (tx *AccessListTxn) setHash(h Hash) { tx.Hash = h } + +// unmarshalRLPFrom unmarshals a Transaction in RLP format +// Be careful! This function does not de-serialize tx type, it assumes that t.Type is already set +// Hash calculation should also be done from the outside! +// Use UnmarshalRLP in most cases +func (tx *AccessListTxn) unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) error { + numOfElems := 11 + + var ( + values rlpValues + err error + ) + + values, err = v.GetElems() + if err != nil { + return err + } + + if numElems := len(values); numElems != numOfElems { + return fmt.Errorf("incorrect number of transaction elements, expected %d but found %d", numOfElems, numElems) + } + + txChainID := new(big.Int) + + if err = values.dequeueValue().GetBigInt(txChainID); err != nil { + return err + } + + tx.setChainID(txChainID) + + // nonce + txNonce, err := values.dequeueValue().GetUint64() + if err != nil { + return err + } + + tx.setNonce(txNonce) + + // gasPrice + txGasPrice := new(big.Int) + if err = values.dequeueValue().GetBigInt(txGasPrice); err != nil { + return err + } + + tx.setGasPrice(txGasPrice) + + // gas + txGas, err := values.dequeueValue().GetUint64() + if err != nil { + return err + } + + tx.setGas(txGas) + + // to + if vv, _ := values.dequeueValue().Bytes(); len(vv) == 20 { + // address + addr := BytesToAddress(vv) + tx.setTo(&addr) + } else { + // reset To + tx.setTo(nil) + } + + // value + txValue := new(big.Int) + if err = values.dequeueValue().GetBigInt(txValue); err != nil { + return err + } + + tx.setValue(txValue) + + // input + var txInput []byte + + txInput, err = values.dequeueValue().GetBytes(txInput) + if err != nil { + return err + } + + tx.setInput(txInput) + + //accessList + accessListVV, err := values.dequeueValue().GetElems() + if err != nil { + return err + } + + var txAccessList TxAccessList + if len(accessListVV) != 0 { + txAccessList = make(TxAccessList, len(accessListVV)) + } + + if err = txAccessList.unmarshallRLPFrom(p, accessListVV); err != nil { + return err + } + + tx.setAccessList(txAccessList) + + // V + txV := new(big.Int) + if err = values.dequeueValue().GetBigInt(txV); err != nil { + return err + } + + // R + txR := new(big.Int) + if err = values.dequeueValue().GetBigInt(txR); err != nil { + return err + } + + // S + txS := new(big.Int) + if err = values.dequeueValue().GetBigInt(txS); err != nil { + return err + } + + tx.setSignatureValues(txV, txR, txS) + + return nil +} + +// MarshalRLPWith marshals the transaction to RLP with a specific fastrlp.Arena +// Be careful! This function does not serialize tx type as a first byte. +// Use MarshalRLP/MarshalRLPTo in most cases +func (tx *AccessListTxn) marshalRLPWith(arena *fastrlp.Arena) *fastrlp.Value { + vv := arena.NewArray() + + vv.Set(arena.NewBigInt(tx.chainID())) + vv.Set(arena.NewUint(tx.nonce())) + vv.Set(arena.NewBigInt(tx.gasPrice())) + vv.Set(arena.NewUint(tx.gas())) + + // Address may be empty + if tx.to() != nil { + vv.Set(arena.NewCopyBytes(tx.to().Bytes())) + } else { + vv.Set(arena.NewNull()) + } + + vv.Set(arena.NewBigInt(tx.value())) + vv.Set(arena.NewCopyBytes(tx.input())) + + // Convert TxAccessList to RLP format and add it to the vv array. + vv.Set(tx.accessList().marshallRLPWith(arena)) + + v, r, s := tx.rawSignatureValues() + vv.Set(arena.NewBigInt(v)) + vv.Set(arena.NewBigInt(r)) + vv.Set(arena.NewBigInt(s)) + + return vv +} + +func (tx *AccessListTxn) copy() TxData { + cpy := &AccessListTxn{} + + if tx.chainID() != nil { + chainID := new(big.Int) + chainID.Set(tx.chainID()) + + cpy.setChainID(chainID) + } + + cpy.setNonce(tx.nonce()) + + if tx.gasPrice() != nil { + gasPrice := new(big.Int) + gasPrice.Set(tx.gasPrice()) + + cpy.setGasPrice(gasPrice) + } + + cpy.setGas(tx.gas()) + + cpy.setTo(tx.to()) + + if tx.value() != nil { + value := new(big.Int) + value.Set(tx.value()) + + cpy.setValue(value) + } + + inputCopy := make([]byte, len(tx.input())) + copy(inputCopy, tx.input()[:]) + + cpy.setInput(inputCopy) + + cpy.setInput(inputCopy) + + v, r, s := tx.rawSignatureValues() + + var vCopy, rCopy, sCopy *big.Int + + if v != nil { + vCopy = new(big.Int) + vCopy.Set(v) + } + + if r != nil { + rCopy = new(big.Int) + rCopy.Set(r) + } + + if s != nil { + sCopy = new(big.Int) + sCopy.Set(s) + } + + cpy.setHash(tx.hash()) + + cpy.setFrom(tx.from()) + + cpy.setSignatureValues(vCopy, rCopy, sCopy) + + cpy.setAccessList(tx.accessList().Copy()) + + return cpy +} diff --git a/types/buildroot/buildroot_test.go b/types/buildroot/buildroot_test.go index e787fa31cb..839313e0d2 100644 --- a/types/buildroot/buildroot_test.go +++ b/types/buildroot/buildroot_test.go @@ -27,7 +27,7 @@ func TestCalculateReceiptsRoot(t *testing.T) { CumulativeGasUsed: 100, GasUsed: 70, ContractAddress: &contractAddr1, - TransactionType: types.DynamicFeeTx, + TransactionType: types.DynamicFeeTxType, Logs: []*types.Log{ { Address: contractAddr1, @@ -47,7 +47,7 @@ func TestCalculateReceiptsRoot(t *testing.T) { CumulativeGasUsed: 100, GasUsed: 30, ContractAddress: &contractAddr2, - TransactionType: types.LegacyTx, + TransactionType: types.LegacyTxType, Logs: []*types.Log{ { Address: contractAddr1, @@ -82,7 +82,7 @@ func TestCalculateReceiptsRoot(t *testing.T) { CumulativeGasUsed: 100 + i, GasUsed: 70 + i, ContractAddress: &contractAddr1, - TransactionType: types.DynamicFeeTx, + TransactionType: types.DynamicFeeTxType, Logs: []*types.Log{ { Address: contractAddr1, @@ -128,7 +128,7 @@ func TestCalculateTransactionsRoot(t *testing.T) { transactions := []*types.Transaction{ { - Inner: &types.MixedTxn{ + Inner: &types.DynamicFeeTx{ Hash: types.StringToHash("0x1"), From: types.StringToAddress("0x2"), To: &contractAddr1, @@ -139,11 +139,10 @@ func TestCalculateTransactionsRoot(t *testing.T) { Nonce: 1, Gas: 100000, ChainID: big.NewInt(1), - Type: types.DynamicFeeTx, }, }, { - Inner: &types.MixedTxn{ + Inner: &types.LegacyTx{ Hash: types.StringToHash("0x4"), From: types.StringToAddress("0x5"), To: &contractAddr2, @@ -152,7 +151,6 @@ func TestCalculateTransactionsRoot(t *testing.T) { Gas: 200000, Input: []byte{0x4, 0x5, 0x6}, Nonce: 2, - Type: types.LegacyTx, }, }, } diff --git a/types/dynamic_fee_tx.go b/types/dynamic_fee_tx.go new file mode 100644 index 0000000000..bb055947f1 --- /dev/null +++ b/types/dynamic_fee_tx.go @@ -0,0 +1,327 @@ +package types + +import ( + "fmt" + "math/big" + + "github.com/umbracle/fastrlp" +) + +type DynamicFeeTx struct { + Nonce uint64 + GasTipCap *big.Int + GasFeeCap *big.Int + Gas uint64 + To *Address + Value *big.Int + Input []byte + V, R, S *big.Int + Hash Hash + From Address + + ChainID *big.Int + AccessList TxAccessList +} + +func (tx *DynamicFeeTx) transactionType() TxType { return DynamicFeeTxType } +func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID } +func (tx *DynamicFeeTx) input() []byte { return tx.Input } +func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas } +func (tx *DynamicFeeTx) gasPrice() *big.Int { return nil } +func (tx *DynamicFeeTx) gasTipCap() *big.Int { return tx.GasTipCap } +func (tx *DynamicFeeTx) gasFeeCap() *big.Int { return tx.GasFeeCap } +func (tx *DynamicFeeTx) value() *big.Int { return tx.Value } +func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce } +func (tx *DynamicFeeTx) to() *Address { return tx.To } +func (tx *DynamicFeeTx) from() Address { return tx.From } + +func (tx *DynamicFeeTx) hash() Hash { return tx.Hash } + +func (tx *DynamicFeeTx) rawSignatureValues() (v, r, s *big.Int) { + return tx.V, tx.R, tx.S +} + +func (tx *DynamicFeeTx) accessList() TxAccessList { return tx.AccessList } + +func (tx *DynamicFeeTx) setSignatureValues(v, r, s *big.Int) { + tx.V, tx.R, tx.S = v, r, s +} + +func (tx *DynamicFeeTx) setFrom(addr Address) { tx.From = addr } + +func (tx *DynamicFeeTx) setGas(gas uint64) { + tx.Gas = gas +} + +func (tx *DynamicFeeTx) setChainID(id *big.Int) { + tx.ChainID = id +} + +func (tx *DynamicFeeTx) setGasPrice(gas *big.Int) { + tx.GasTipCap = gas +} + +func (tx *DynamicFeeTx) setGasFeeCap(gas *big.Int) { + tx.GasFeeCap = gas +} + +func (tx *DynamicFeeTx) setGasTipCap(gas *big.Int) { + tx.GasTipCap = gas +} + +func (tx *DynamicFeeTx) setValue(value *big.Int) { + tx.Value = value +} + +func (tx *DynamicFeeTx) setInput(input []byte) { + tx.Input = input +} + +func (tx *DynamicFeeTx) setTo(address *Address) { + tx.To = address +} + +func (tx *DynamicFeeTx) setNonce(nonce uint64) { + tx.Nonce = nonce +} + +func (tx *DynamicFeeTx) setAccessList(accessList TxAccessList) { + tx.AccessList = accessList +} + +func (tx *DynamicFeeTx) setHash(h Hash) { tx.Hash = h } + +// unmarshalRLPFrom unmarshals a Transaction in RLP format +// Be careful! This function does not de-serialize tx type, it assumes that t.Type is already set +// Hash calculation should also be done from the outside! +// Use UnmarshalRLP in most cases +func (tx *DynamicFeeTx) unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) error { + numOfElems := 12 + + var ( + values rlpValues + err error + ) + + values, err = v.GetElems() + if err != nil { + return err + } + + if numElems := len(values); numElems != numOfElems { + return fmt.Errorf("incorrect number of transaction elements, expected %d but found %d", numOfElems, numElems) + } + + // Load Chain ID + txChainID := new(big.Int) + if err = values.dequeueValue().GetBigInt(txChainID); err != nil { + return err + } + + tx.setChainID(txChainID) + + // nonce + txNonce, err := values.dequeueValue().GetUint64() + if err != nil { + return err + } + + tx.setNonce(txNonce) + + // gasTipCap + txGasTipCap := new(big.Int) + if err = values.dequeueValue().GetBigInt(txGasTipCap); err != nil { + return err + } + + tx.setGasTipCap(txGasTipCap) + + // gasFeeCap + txGasFeeCap := new(big.Int) + if err = values.dequeueValue().GetBigInt(txGasFeeCap); err != nil { + return err + } + + tx.setGasFeeCap(txGasFeeCap) + + // gas + txGas, err := values.dequeueValue().GetUint64() + if err != nil { + return err + } + + tx.setGas(txGas) + + // to + if vv, _ := values.dequeueValue().Bytes(); len(vv) == AddressLength { + addr := BytesToAddress(vv) + tx.setTo(&addr) + } else { + // reset To + tx.setTo(nil) + } + + // value + txValue := new(big.Int) + if err = values.dequeueValue().GetBigInt(txValue); err != nil { + return err + } + + tx.setValue(txValue) + + // input + var txInput []byte + + txInput, err = values.dequeueValue().GetBytes(txInput) + if err != nil { + return err + } + + tx.setInput(txInput) + + accessListVV, err := values.dequeueValue().GetElems() + if err != nil { + return err + } + + var txAccessList TxAccessList + if len(accessListVV) != 0 { + txAccessList = make(TxAccessList, len(accessListVV)) + } + + if err = txAccessList.unmarshallRLPFrom(p, accessListVV); err != nil { + return err + } + + tx.setAccessList(txAccessList) + + // V + txV := new(big.Int) + if err = values.dequeueValue().GetBigInt(txV); err != nil { + return err + } + + // R + txR := new(big.Int) + if err = values.dequeueValue().GetBigInt(txR); err != nil { + return err + } + + // S + txS := new(big.Int) + if err = values.dequeueValue().GetBigInt(txS); err != nil { + return err + } + + tx.setSignatureValues(txV, txR, txS) + + return nil +} + +// MarshalRLPWith marshals the transaction to RLP with a specific fastrlp.Arena +// Be careful! This function does not serialize tx type as a first byte. +// Use MarshalRLP/MarshalRLPTo in most cases +func (tx *DynamicFeeTx) marshalRLPWith(arena *fastrlp.Arena) *fastrlp.Value { + vv := arena.NewArray() + + vv.Set(arena.NewBigInt(tx.chainID())) + vv.Set(arena.NewUint(tx.nonce())) + // Add EIP-1559 related fields. + // For non-dynamic-fee-tx gas price is used. + vv.Set(arena.NewBigInt(tx.gasTipCap())) + vv.Set(arena.NewBigInt(tx.gasFeeCap())) + vv.Set(arena.NewUint(tx.gas())) + + // Address may be empty + if tx.to() != nil { + vv.Set(arena.NewCopyBytes(tx.to().Bytes())) + } else { + vv.Set(arena.NewNull()) + } + + vv.Set(arena.NewBigInt(tx.value())) + vv.Set(arena.NewCopyBytes(tx.input())) + + // Convert TxAccessList to RLP format and add it to the vv array. + vv.Set(tx.accessList().marshallRLPWith(arena)) + + // signature values + v, r, s := tx.rawSignatureValues() + vv.Set(arena.NewBigInt(v)) + vv.Set(arena.NewBigInt(r)) + vv.Set(arena.NewBigInt(s)) + + return vv +} + +func (tx *DynamicFeeTx) copy() TxData { + cpy := &DynamicFeeTx{} + + if tx.chainID() != nil { + chainID := new(big.Int) + chainID.Set(tx.chainID()) + + cpy.setChainID(chainID) + } + + cpy.setNonce(tx.nonce()) + + if tx.gasTipCap() != nil { + gasTipCap := new(big.Int) + gasTipCap.Set(tx.gasTipCap()) + + cpy.setGasTipCap(gasTipCap) + } + + if tx.gasFeeCap() != nil { + gasFeeCap := new(big.Int) + gasFeeCap.Set(tx.gasFeeCap()) + + cpy.setGasFeeCap(gasFeeCap) + } + + cpy.setGas(tx.gas()) + + cpy.setTo(tx.to()) + + if tx.value() != nil { + value := new(big.Int) + value.Set(tx.value()) + + cpy.setValue(value) + } + + inputCopy := make([]byte, len(tx.input())) + copy(inputCopy, tx.input()[:]) + + cpy.setInput(inputCopy) + + v, r, s := tx.rawSignatureValues() + + var vCopy, rCopy, sCopy *big.Int + + if v != nil { + vCopy = new(big.Int) + vCopy.Set(v) + } + + if r != nil { + rCopy = new(big.Int) + rCopy.Set(r) + } + + if s != nil { + sCopy = new(big.Int) + sCopy.Set(s) + } + + cpy.setSignatureValues(vCopy, rCopy, sCopy) + + cpy.setAccessList(tx.accessList().Copy()) + + cpy.setHash(tx.hash()) + + cpy.setFrom(tx.from()) + + return cpy +} diff --git a/types/legacy_tx.go b/types/legacy_tx.go new file mode 100644 index 0000000000..23af43bd10 --- /dev/null +++ b/types/legacy_tx.go @@ -0,0 +1,267 @@ +package types + +import ( + "fmt" + "math/big" + + "github.com/umbracle/fastrlp" +) + +type LegacyTx struct { + Nonce uint64 + GasPrice *big.Int + Gas uint64 + To *Address + Value *big.Int + Input []byte + V, R, S *big.Int + Hash Hash + From Address +} + +func (tx *LegacyTx) transactionType() TxType { return LegacyTxType } +func (tx *LegacyTx) chainID() *big.Int { return nil } +func (tx *LegacyTx) input() []byte { return tx.Input } +func (tx *LegacyTx) gas() uint64 { return tx.Gas } +func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice } +func (tx *LegacyTx) gasTipCap() *big.Int { return tx.GasPrice } +func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice } +func (tx *LegacyTx) value() *big.Int { return tx.Value } +func (tx *LegacyTx) nonce() uint64 { return tx.Nonce } +func (tx *LegacyTx) to() *Address { return tx.To } +func (tx *LegacyTx) from() Address { return tx.From } + +func (tx *LegacyTx) hash() Hash { return tx.Hash } + +func (tx *LegacyTx) rawSignatureValues() (v, r, s *big.Int) { + return tx.V, tx.R, tx.S +} + +func (tx *LegacyTx) accessList() TxAccessList { return nil } + +// set methods for transaction fields +func (tx *LegacyTx) setSignatureValues(v, r, s *big.Int) { + tx.V, tx.R, tx.S = v, r, s +} + +func (tx *LegacyTx) setFrom(addr Address) { tx.From = addr } + +func (tx *LegacyTx) setGas(gas uint64) { + tx.Gas = gas +} + +func (tx *LegacyTx) setChainID(id *big.Int) {} + +func (tx *LegacyTx) setGasPrice(gas *big.Int) { + tx.GasPrice = gas +} + +func (tx *LegacyTx) setGasFeeCap(gas *big.Int) { +} + +func (tx *LegacyTx) setGasTipCap(gas *big.Int) { + +} + +func (tx *LegacyTx) setTransactionType(t TxType) {} + +func (tx *LegacyTx) setValue(value *big.Int) { + tx.Value = value +} + +func (tx *LegacyTx) setInput(input []byte) { + tx.Input = input +} + +func (tx *LegacyTx) setTo(addeess *Address) { + tx.To = addeess +} + +func (tx *LegacyTx) setNonce(nonce uint64) { + tx.Nonce = nonce +} + +func (tx *LegacyTx) setAccessList(accessList TxAccessList) {} + +func (tx *LegacyTx) setHash(h Hash) { tx.Hash = h } + +// unmarshalRLPFrom unmarshals a Transaction in RLP format +// Be careful! This function does not de-serialize tx type, it assumes that t.Type is already set +// Hash calculation should also be done from the outside! +// Use UnmarshalRLP in most cases +func (tx *LegacyTx) unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) error { + num := 9 + + var ( + values rlpValues + err error + ) + + values, err = v.GetElems() + if err != nil { + return err + } + + if numElems := len(values); numElems != num { + return fmt.Errorf("legacy incorrect number of transaction elements, expected %d but found %d", num, numElems) + } + + // nonce + txNonce, err := values.dequeueValue().GetUint64() + if err != nil { + return err + } + + tx.setNonce(txNonce) + + // gasPrice + txGasPrice := new(big.Int) + if err = values.dequeueValue().GetBigInt(txGasPrice); err != nil { + return err + } + + tx.setGasPrice(txGasPrice) + + // gas + txGas, err := values.dequeueValue().GetUint64() + if err != nil { + return err + } + + tx.setGas(txGas) + + // to + if vv, _ := values.dequeueValue().Bytes(); len(vv) == 20 { + // address + addr := BytesToAddress(vv) + tx.setTo(&addr) + } else { + // reset To + tx.setTo(nil) + } + + // value + txValue := new(big.Int) + if err = values.dequeueValue().GetBigInt(txValue); err != nil { + return err + } + + tx.setValue(txValue) + + // input + var txInput []byte + + txInput, err = values.dequeueValue().GetBytes(txInput) + if err != nil { + return err + } + + tx.setInput(txInput) + + // V + txV := new(big.Int) + if err = values.dequeueValue().GetBigInt(txV); err != nil { + return err + } + + // R + txR := new(big.Int) + if err = values.dequeueValue().GetBigInt(txR); err != nil { + return err + } + + // S + txS := new(big.Int) + if err = values.dequeueValue().GetBigInt(txS); err != nil { + return err + } + + tx.setSignatureValues(txV, txR, txS) + + return nil +} + +// MarshalRLPWith marshals the transaction to RLP with a specific fastrlp.Arena +// Be careful! This function does not serialize tx type as a first byte. +// Use MarshalRLP/MarshalRLPTo in most cases +func (tx *LegacyTx) marshalRLPWith(arena *fastrlp.Arena) *fastrlp.Value { + vv := arena.NewArray() + + vv.Set(arena.NewUint(tx.nonce())) + vv.Set(arena.NewBigInt(tx.gasPrice())) + vv.Set(arena.NewUint(tx.gas())) + + // Address may be empty + if tx.to() != nil { + vv.Set(arena.NewCopyBytes(tx.to().Bytes())) + } else { + vv.Set(arena.NewNull()) + } + + vv.Set(arena.NewBigInt(tx.value())) + vv.Set(arena.NewCopyBytes(tx.input())) + + // signature values + v, r, s := tx.rawSignatureValues() + vv.Set(arena.NewBigInt(v)) + vv.Set(arena.NewBigInt(r)) + vv.Set(arena.NewBigInt(s)) + + return vv +} + +func (tx *LegacyTx) copy() TxData { //nolint:dupl + cpy := &LegacyTx{} + + cpy.setNonce(tx.nonce()) + + if tx.gasPrice() != nil { + gasPrice := new(big.Int) + gasPrice.Set(tx.gasPrice()) + + cpy.setGasPrice(gasPrice) + } + + cpy.setGas(tx.gas()) + + cpy.setTo(tx.to()) + + if tx.value() != nil { + value := new(big.Int) + value.Set(tx.value()) + + cpy.setValue(value) + } + + inputCopy := make([]byte, len(tx.input())) + copy(inputCopy, tx.input()[:]) + + cpy.setInput(inputCopy) + + v, r, s := tx.rawSignatureValues() + + var vCopy, rCopy, sCopy *big.Int + + if v != nil { + vCopy = new(big.Int) + vCopy.Set(v) + } + + if r != nil { + rCopy = new(big.Int) + rCopy.Set(r) + } + + if s != nil { + sCopy = new(big.Int) + sCopy.Set(s) + } + + cpy.setSignatureValues(vCopy, rCopy, sCopy) + + cpy.setHash(tx.hash()) + + cpy.setFrom(tx.from()) + + return cpy +} diff --git a/types/mixed_tx.go b/types/mixed_tx.go deleted file mode 100644 index da4094d159..0000000000 --- a/types/mixed_tx.go +++ /dev/null @@ -1,105 +0,0 @@ -package types - -import "math/big" - -type MixedTxn struct { - Nonce uint64 - GasPrice *big.Int - GasTipCap *big.Int - GasFeeCap *big.Int - Gas uint64 - To *Address - Value *big.Int - Input []byte - V, R, S *big.Int - Hash Hash - From Address - - Type TxType - - ChainID *big.Int - AccessList TxAccessList -} - -func (tx *MixedTxn) transactionType() TxType { return tx.Type } -func (tx *MixedTxn) chainID() *big.Int { return tx.ChainID } -func (tx *MixedTxn) input() []byte { return tx.Input } -func (tx *MixedTxn) gas() uint64 { return tx.Gas } -func (tx *MixedTxn) gasPrice() *big.Int { return tx.GasPrice } -func (tx *MixedTxn) gasTipCap() *big.Int { return tx.GasTipCap } -func (tx *MixedTxn) gasFeeCap() *big.Int { return tx.GasFeeCap } -func (tx *MixedTxn) value() *big.Int { return tx.Value } -func (tx *MixedTxn) nonce() uint64 { return tx.Nonce } -func (tx *MixedTxn) to() *Address { return tx.To } -func (tx *MixedTxn) from() Address { return tx.From } - -func (tx *MixedTxn) hash() Hash { return tx.Hash } - -func (tx *MixedTxn) rawSignatureValues() (v, r, s *big.Int) { - return tx.V, tx.R, tx.S -} - -func (tx *MixedTxn) accessList() TxAccessList { - if tx.transactionType() == DynamicFeeTx { - return tx.AccessList - } - - return nil -} - -// set methods for transaction fields -func (tx *MixedTxn) setSignatureValues(v, r, s *big.Int) { - tx.V, tx.R, tx.S = v, r, s -} - -func (tx *MixedTxn) setFrom(addr Address) { - tx.From = addr -} - -func (tx *MixedTxn) setGas(gas uint64) { - tx.Gas = gas -} - -func (tx *MixedTxn) setChainID(id *big.Int) { - tx.ChainID = id -} - -func (tx *MixedTxn) setGasPrice(gas *big.Int) { - tx.GasPrice = gas -} - -func (tx *MixedTxn) setGasFeeCap(gas *big.Int) { - tx.GasFeeCap = gas -} - -func (tx *MixedTxn) setGasTipCap(gas *big.Int) { - tx.GasTipCap = gas -} - -func (tx *MixedTxn) setTransactionType(t TxType) { - tx.Type = t -} - -func (tx *MixedTxn) setValue(value *big.Int) { - tx.Value = value -} - -func (tx *MixedTxn) setInput(input []byte) { - tx.Input = input -} - -func (tx *MixedTxn) setTo(addeess *Address) { - tx.To = addeess -} - -func (tx *MixedTxn) setNonce(nonce uint64) { - tx.Nonce = nonce -} - -func (tx *MixedTxn) setAccessList(accessList TxAccessList) { - tx.AccessList = accessList -} - -func (tx *MixedTxn) setHash(h Hash) { - tx.Hash = h -} diff --git a/types/receipt.go b/types/receipt.go index 93830506a7..a482d9f2bb 100644 --- a/types/receipt.go +++ b/types/receipt.go @@ -34,7 +34,7 @@ type Receipt struct { } func (r *Receipt) IsLegacyTx() bool { - return r.TransactionType == LegacyTx + return r.TransactionType == LegacyTxType } func (r *Receipt) SetStatus(s ReceiptStatus) { diff --git a/types/rlp_encoding_test.go b/types/rlp_encoding_test.go index 1f5c1ae3f5..db334ec809 100644 --- a/types/rlp_encoding_test.go +++ b/types/rlp_encoding_test.go @@ -41,9 +41,9 @@ func TestRLPEncoding(t *testing.T) { } } -func TestRLPMarshall_And_Unmarshall_Transaction(t *testing.T) { +func TestRLPMarshall_And_Unmarshall_Legacy_Transaction(t *testing.T) { addrTo := StringToAddress("11") - txn := NewTx(&MixedTxn{ + txn := NewTx(&LegacyTx{ Nonce: 0, GasPrice: big.NewInt(11), Gas: 11, @@ -57,7 +57,7 @@ func TestRLPMarshall_And_Unmarshall_Transaction(t *testing.T) { txn.ComputeHash() - unmarshalledTxn := NewTx(&MixedTxn{}) + unmarshalledTxn := NewTx(&LegacyTx{}) marshaledRlp := txn.MarshalRLP() if err := unmarshalledTxn.UnmarshalRLP(marshaledRlp); err != nil { @@ -152,35 +152,56 @@ func TestRLPUnmarshal_Header_ComputeHash(t *testing.T) { func TestRLPMarshall_And_Unmarshall_TypedTransaction(t *testing.T) { addrTo := StringToAddress("11") addrFrom := StringToAddress("22") - originalTx := NewTx(&MixedTxn{ - Nonce: 0, - GasPrice: big.NewInt(11), - GasFeeCap: big.NewInt(12), - GasTipCap: big.NewInt(13), - Gas: 11, - To: &addrTo, - From: addrFrom, - Value: big.NewInt(1), - Input: []byte{1, 2}, - V: big.NewInt(25), - S: big.NewInt(26), - R: big.NewInt(27), - }) - txTypes := []TxType{ - StateTx, - LegacyTx, - DynamicFeeTx, + originalTxs := []*Transaction{ + NewTx(&StateTx{ + Nonce: 0, + GasPrice: big.NewInt(11), + Gas: 11, + To: &addrTo, + From: addrFrom, + Value: big.NewInt(1), + Input: []byte{1, 2}, + V: big.NewInt(25), + S: big.NewInt(26), + R: big.NewInt(27), + }), + NewTx(&LegacyTx{ + Nonce: 0, + GasPrice: big.NewInt(11), + Gas: 11, + To: &addrTo, + From: addrFrom, + Value: big.NewInt(1), + Input: []byte{1, 2}, + V: big.NewInt(25), + S: big.NewInt(26), + R: big.NewInt(27), + }), + NewTx(&DynamicFeeTx{ + Nonce: 0, + GasFeeCap: big.NewInt(12), + GasTipCap: big.NewInt(13), + Gas: 11, + To: &addrTo, + From: addrFrom, + Value: big.NewInt(1), + Input: []byte{1, 2}, + V: big.NewInt(25), + S: big.NewInt(26), + R: big.NewInt(27), + }), } - for _, v := range txTypes { - t.Run(v.String(), func(t *testing.T) { - originalTx.SetTransactionType(v) + for _, originalTx := range originalTxs { + t.Run(originalTx.Type().String(), func(t *testing.T) { originalTx.ComputeHash() + unmarshalledTx := &Transaction{} + unmarshalledTx.InitInnerData(originalTx.Type()) + txRLP := originalTx.MarshalRLP() - unmarshalledTx := NewTx(&MixedTxn{}) assert.NoError(t, unmarshalledTx.UnmarshalRLP(txRLP)) unmarshalledTx.ComputeHash() @@ -194,9 +215,9 @@ func TestRLPMarshall_Unmarshall_Missing_Data(t *testing.T) { t.Parallel() txTypes := []TxType{ - StateTx, - LegacyTx, - DynamicFeeTx, + StateTxType, + LegacyTxType, + DynamicFeeTxType, } for _, txType := range txTypes { @@ -219,27 +240,27 @@ func TestRLPMarshall_Unmarshall_Missing_Data(t *testing.T) { name: fmt.Sprintf("[%s] Missing From", txType), expectedErr: false, omittedValues: map[string]bool{ - "ChainID": txType != DynamicFeeTx, - "GasTipCap": txType != DynamicFeeTx, - "GasFeeCap": txType != DynamicFeeTx, - "GasPrice": txType == DynamicFeeTx, - "AccessList": txType != DynamicFeeTx, - "From": txType != StateTx, + "ChainID": txType != DynamicFeeTxType, + "GasTipCap": txType != DynamicFeeTxType, + "GasFeeCap": txType != DynamicFeeTxType, + "GasPrice": txType == DynamicFeeTxType, + "AccessList": txType != DynamicFeeTxType, + "From": txType != StateTxType, }, - fromAddrSet: txType == StateTx, + fromAddrSet: txType == StateTxType, }, { name: fmt.Sprintf("[%s] Address set for state tx only", txType), expectedErr: false, omittedValues: map[string]bool{ - "ChainID": txType != DynamicFeeTx, - "GasTipCap": txType != DynamicFeeTx, - "GasFeeCap": txType != DynamicFeeTx, - "GasPrice": txType == DynamicFeeTx, - "AccessList": txType != DynamicFeeTx, - "From": txType != StateTx, + "ChainID": txType != DynamicFeeTxType, + "GasTipCap": txType != DynamicFeeTxType, + "GasFeeCap": txType != DynamicFeeTxType, + "GasPrice": txType == DynamicFeeTxType, + "AccessList": txType != DynamicFeeTxType, + "From": txType != StateTxType, }, - fromAddrSet: txType == StateTx, + fromAddrSet: txType == StateTxType, }, } @@ -255,14 +276,12 @@ func TestRLPMarshall_Unmarshall_Missing_Data(t *testing.T) { v, err := parser.Parse(testData) assert.Nil(t, err) - unmarshalledTx := NewTx(&MixedTxn{ - Type: txType, - }) + unmarshalledTx := NewTxWithType(txType) if tt.expectedErr { - assert.Error(t, unmarshalledTx.unmarshalRLPFrom(parser, v), tt.name) + assert.Error(t, unmarshalledTx.Inner.unmarshalRLPFrom(parser, v), tt.name) } else { - assert.NoError(t, unmarshalledTx.unmarshalRLPFrom(parser, v), tt.name) + assert.NoError(t, unmarshalledTx.Inner.unmarshalRLPFrom(parser, v), tt.name) assert.Equal(t, tt.fromAddrSet, len(unmarshalledTx.From()) != 0 && unmarshalledTx.From() != ZeroAddress, unmarshalledTx.Type().String(), unmarshalledTx.From()) } @@ -281,15 +300,15 @@ func TestRLPMarshall_And_Unmarshall_TxType(t *testing.T) { }{ { name: "StateTx", - txType: StateTx, + txType: StateTxType, }, { name: "LegacyTx", - txType: LegacyTx, + txType: LegacyTxType, }, { name: "DynamicFeeTx", - txType: DynamicFeeTx, + txType: DynamicFeeTxType, }, { name: "undefined type", diff --git a/types/rlp_marshal.go b/types/rlp_marshal.go index 7cb8b143b2..b6f543403d 100644 --- a/types/rlp_marshal.go +++ b/types/rlp_marshal.go @@ -40,11 +40,11 @@ func (b *Block) MarshalRLPWith(ar *fastrlp.Arena) *fastrlp.Value { v0 := ar.NewArray() for _, tx := range b.Transactions { - if tx.Type() != LegacyTx { + if tx.Type() != LegacyTxType { v0.Set(ar.NewCopyBytes([]byte{byte(tx.Type())})) } - v0.Set(tx.MarshalRLPWith(ar)) + v0.Set(tx.Inner.marshalRLPWith(ar)) } vv.Set(v0) @@ -183,118 +183,9 @@ func (t *Transaction) MarshalRLP() []byte { } func (t *Transaction) MarshalRLPTo(dst []byte) []byte { - if t.Type() != LegacyTx { + if t.Type() != LegacyTxType { dst = append(dst, byte(t.Type())) } return MarshalRLPTo(t.MarshalRLPWith, dst) } - -// MarshalRLPWith marshals the transaction to RLP with a specific fastrlp.Arena -// Be careful! This function does not serialize tx type as a first byte. -// Use MarshalRLP/MarshalRLPTo in most cases -func (t *Transaction) MarshalRLPWith(arena *fastrlp.Arena) *fastrlp.Value { - vv := arena.NewArray() - - switch t.Inner.(type) { - case *MixedTxn: - // Check Transaction1559Payload there https://eips.ethereum.org/EIPS/eip-1559#specification - if t.Type() == DynamicFeeTx { - vv.Set(arena.NewBigInt(t.ChainID())) - } - - vv.Set(arena.NewUint(t.Nonce())) - - if t.Type() == DynamicFeeTx { - // Add EIP-1559 related fields. - // For non-dynamic-fee-tx gas price is used. - vv.Set(arena.NewBigInt(t.GasTipCap())) - vv.Set(arena.NewBigInt(t.GasFeeCap())) - } else { - vv.Set(arena.NewBigInt(t.GasPrice())) - } - - vv.Set(arena.NewUint(t.Gas())) - - // Address may be empty - if t.To() != nil { - vv.Set(arena.NewCopyBytes(t.To().Bytes())) - } else { - vv.Set(arena.NewNull()) - } - - vv.Set(arena.NewBigInt(t.Value())) - vv.Set(arena.NewCopyBytes(t.Input())) - - // Specify access list as per spec. - if t.Type() == DynamicFeeTx { - // Convert TxAccessList to RLP format and add it to the vv array. - accessListVV := arena.NewArray() - - for _, accessTuple := range t.AccessList() { - accessTupleVV := arena.NewArray() - accessTupleVV.Set(arena.NewCopyBytes(accessTuple.Address.Bytes())) - - storageKeysVV := arena.NewArray() - for _, storageKey := range accessTuple.StorageKeys { - storageKeysVV.Set(arena.NewCopyBytes(storageKey.Bytes())) - } - - accessTupleVV.Set(storageKeysVV) - accessListVV.Set(accessTupleVV) - } - - vv.Set(accessListVV) - } - - // signature values - v, r, s := t.RawSignatureValues() - vv.Set(arena.NewBigInt(v)) - vv.Set(arena.NewBigInt(r)) - vv.Set(arena.NewBigInt(s)) - - if t.Type() == StateTx { - vv.Set(arena.NewCopyBytes(t.From().Bytes())) - } - case *AccessListTxn: - vv.Set(arena.NewBigInt(t.ChainID())) - vv.Set(arena.NewUint(t.Nonce())) - vv.Set(arena.NewBigInt(t.GasPrice())) - vv.Set(arena.NewUint(t.Gas())) - - // Address may be empty - if t.To() != nil { - vv.Set(arena.NewCopyBytes(t.To().Bytes())) - } else { - vv.Set(arena.NewNull()) - } - - vv.Set(arena.NewBigInt(t.Value())) - vv.Set(arena.NewCopyBytes(t.Input())) - - // add accessList - accessListVV := arena.NewArray() - - for _, accessTuple := range t.AccessList() { - accessTupleVV := arena.NewArray() - accessTupleVV.Set(arena.NewCopyBytes(accessTuple.Address.Bytes())) - - storageKeysVV := arena.NewArray() - for _, storageKey := range accessTuple.StorageKeys { - storageKeysVV.Set(arena.NewCopyBytes(storageKey.Bytes())) - } - - accessTupleVV.Set(storageKeysVV) - accessListVV.Set(accessTupleVV) - } - - vv.Set(accessListVV) - - v, r, s := t.RawSignatureValues() - vv.Set(arena.NewBigInt(v)) - vv.Set(arena.NewBigInt(r)) - vv.Set(arena.NewBigInt(s)) - } - - return vv -} diff --git a/types/rlp_marshal_storage.go b/types/rlp_marshal_storage.go index 82cfbafe86..6d11d009ab 100644 --- a/types/rlp_marshal_storage.go +++ b/types/rlp_marshal_storage.go @@ -44,7 +44,7 @@ func (t *Transaction) MarshalStoreRLPTo(dst []byte) []byte { func (t *Transaction) marshalStoreRLPWith(a *fastrlp.Arena) *fastrlp.Value { vv := a.NewArray() - if t.Type() != LegacyTx { + if t.Type() != LegacyTxType { vv.Set(a.NewBytes([]byte{byte(t.Type())})) } diff --git a/types/rlp_unmarshal.go b/types/rlp_unmarshal.go index 981d789c7f..480acbe54d 100644 --- a/types/rlp_unmarshal.go +++ b/types/rlp_unmarshal.go @@ -2,7 +2,6 @@ package types import ( "fmt" - "math/big" "github.com/umbracle/fastrlp" ) @@ -45,7 +44,7 @@ func unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value, cb unmarshalRLPFromFu for i := 0; i < len(elems); i++ { // Non-legacy tx raw contains a tx type prefix in the beginning according to EIP-2718. // Here we check if the first element is a tx type and unmarshal it first. - txType := LegacyTx + txType := LegacyTxType if elems[i].Type() == fastrlp.TypeBytes { if err = txType.unmarshalRLPFrom(p, elems[i]); err != nil { return err @@ -105,17 +104,9 @@ func (b *Block) unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) error { // transactions if err = unmarshalRLPFrom(p, elems[1], func(txType TxType, p *fastrlp.Parser, v *fastrlp.Value) error { - var bTxn *Transaction - switch txType { - case AccessListTx: - bTxn = NewTx(&AccessListTxn{}) - case DynamicFeeTx, LegacyTx, StateTx: - bTxn = NewTx(&MixedTxn{ - Type: txType, - }) - } + bTxn := NewTxWithType(txType) - if err = bTxn.unmarshalRLPFrom(p, v); err != nil { + if err = bTxn.Inner.unmarshalRLPFrom(p, v); err != nil { return err } @@ -259,7 +250,7 @@ func (r *Receipts) unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) error { } func (r *Receipt) UnmarshalRLP(input []byte) error { - r.TransactionType = LegacyTx + r.TransactionType = LegacyTxType offset := 0 if len(input) > 0 && input[0] <= RLPSingleByteUpperLimit { @@ -370,7 +361,7 @@ func (l *Log) unmarshalRLPFrom(_ *fastrlp.Parser, v *fastrlp.Value) error { // UnmarshalRLP unmarshals transaction from byte slice // Caution: Hash calculation should be done from the outside! func (t *Transaction) UnmarshalRLP(input []byte) error { - txType := LegacyTx + txType := LegacyTxType offset := 0 if len(input) > 0 && input[0] <= RLPSingleByteUpperLimit { @@ -386,340 +377,22 @@ func (t *Transaction) UnmarshalRLP(input []byte) error { t.InitInnerData(txType) - if err := UnmarshalRlp(t.unmarshalRLPFrom, input[offset:]); err != nil { + if err := UnmarshalRlp(t.UnmarshalRLPFrom, input[offset:]); err != nil { return err } return nil } -// unmarshalRLPFrom unmarshals a Transaction in RLP format -// Be careful! This function does not de-serialize tx type, it assumes that t.Type is already set -// Hash calculation should also be done from the outside! -// Use UnmarshalRLP in most cases -func (t *Transaction) unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) error { - elems, err := v.GetElems() - if err != nil { - return err - } - - getElem := func() *fastrlp.Value { - val := elems[0] - elems = elems[1:] - - return val - } +type rlpValues []*fastrlp.Value - var num int - - switch t.Type() { - case LegacyTx: - num = 9 - case StateTx: - num = 10 - case DynamicFeeTx: - num = 12 - case AccessListTx: - num = 11 - default: - return fmt.Errorf("transaction type %d not found", t.Type()) - } - - if numElems := len(elems); numElems != num { - return fmt.Errorf("incorrect number of transaction elements, expected %d but found %d", num, numElems) +func (r *rlpValues) dequeueValue() *fastrlp.Value { + if len(*r) == 0 { + return nil } - switch t.Inner.(type) { - case *MixedTxn: - // Load Chain ID for dynamic transactions - if t.Type() == DynamicFeeTx { - txChainID := new(big.Int) - if err = getElem().GetBigInt(txChainID); err != nil { - return err - } - - t.SetChainID(txChainID) - } - - // nonce - txNonce, err := getElem().GetUint64() - if err != nil { - return err - } - - t.SetNonce(txNonce) - - if t.Type() == DynamicFeeTx { - // gasTipCap - txGasTipCap := new(big.Int) - if err = getElem().GetBigInt(txGasTipCap); err != nil { - return err - } - - t.SetGasTipCap(txGasTipCap) - - // gasFeeCap - txGasFeeCap := new(big.Int) - if err = getElem().GetBigInt(txGasFeeCap); err != nil { - return err - } - - t.SetGasFeeCap(txGasFeeCap) - } else { - // gasPrice - txGasPrice := new(big.Int) - if err = getElem().GetBigInt(txGasPrice); err != nil { - return err - } - - t.SetGasPrice(txGasPrice) - } - - // gas - txGas, err := getElem().GetUint64() - if err != nil { - return err - } - - t.SetGas(txGas) - - // to - if vv, _ := getElem().Bytes(); len(vv) == 20 { - // address - addr := BytesToAddress(vv) - t.SetTo(&addr) - } else { - // reset To - t.SetTo(nil) - } - - // value - txValue := new(big.Int) - if err = getElem().GetBigInt(txValue); err != nil { - return err - } - - t.SetValue(txValue) - - // input - var txInput []byte - - txInput, err = getElem().GetBytes(txInput) - if err != nil { - return err - } - - t.SetInput(txInput) - - if t.Type() == DynamicFeeTx { - accessListVV, err := getElem().GetElems() - if err != nil { - return err - } - - var txAccessList TxAccessList - if len(accessListVV) != 0 { - txAccessList = make(TxAccessList, len(accessListVV)) - } - - for i, accessTupleVV := range accessListVV { - accessTupleElems, err := accessTupleVV.GetElems() - if err != nil { - return err - } - - // Read the address - addressVV := accessTupleElems[0] - - addressBytes, err := addressVV.Bytes() - if err != nil { - return err - } - - txAccessList[i].Address = BytesToAddress(addressBytes) - - // Read the storage keys - storageKeysArrayVV := accessTupleElems[1] - - storageKeysElems, err := storageKeysArrayVV.GetElems() - if err != nil { - return err - } - - txAccessList[i].StorageKeys = make([]Hash, len(storageKeysElems)) - - for j, storageKeyVV := range storageKeysElems { - storageKeyBytes, err := storageKeyVV.Bytes() - if err != nil { - return err - } - - txAccessList[i].StorageKeys[j] = BytesToHash(storageKeyBytes) - } - } - - t.SetAccessList(txAccessList) - } - - // V - txV := new(big.Int) - if err = getElem().GetBigInt(txV); err != nil { - return err - } - - // R - txR := new(big.Int) - if err = getElem().GetBigInt(txR); err != nil { - return err - } + val := (*r)[0] + *r = (*r)[1:] - // S - txS := new(big.Int) - if err = getElem().GetBigInt(txS); err != nil { - return err - } - - t.SetSignatureValues(txV, txR, txS) - - if t.Type() == StateTx { - t.SetFrom(ZeroAddress) - - // We need to set From field for state transaction, - // because we are using unique, predefined address, for sending such transactions - if vv, err := getElem().Bytes(); err == nil && len(vv) == AddressLength { - // address - t.SetFrom(BytesToAddress(vv)) - } - } - case *AccessListTxn: - txChainID := new(big.Int) - if err = getElem().GetBigInt(txChainID); err != nil { - return err - } - - t.SetChainID(txChainID) - - // nonce - txNonce, err := getElem().GetUint64() - if err != nil { - return err - } - - t.SetNonce(txNonce) - - // gasPrice - txGasPrice := new(big.Int) - if err = getElem().GetBigInt(txGasPrice); err != nil { - return err - } - - t.SetGasPrice(txGasPrice) - - // gas - txGas, err := getElem().GetUint64() - if err != nil { - return err - } - - t.SetGas(txGas) - - // to - if vv, _ := getElem().Bytes(); len(vv) == 20 { - // address - addr := BytesToAddress(vv) - t.SetTo(&addr) - } else { - // reset To - t.SetTo(nil) - } - - // value - txValue := new(big.Int) - if err = getElem().GetBigInt(txValue); err != nil { - return err - } - - t.SetValue(txValue) - - // input - var txInput []byte - - txInput, err = getElem().GetBytes(txInput) - if err != nil { - return err - } - - t.SetInput(txInput) - - //accessList - accessListVV, err := getElem().GetElems() - if err != nil { - return err - } - - var txAccessList TxAccessList - if len(accessListVV) != 0 { - txAccessList = make(TxAccessList, len(accessListVV)) - } - - for i, accessTupleVV := range accessListVV { - accessTupleElems, err := accessTupleVV.GetElems() - if err != nil { - return err - } - - // Read the address - addressVV := accessTupleElems[0] - - addressBytes, err := addressVV.Bytes() - if err != nil { - return err - } - - txAccessList[i].Address = BytesToAddress(addressBytes) - - // Read the storage keys - storageKeysArrayVV := accessTupleElems[1] - - storageKeysElems, err := storageKeysArrayVV.GetElems() - if err != nil { - return err - } - - txAccessList[i].StorageKeys = make([]Hash, len(storageKeysElems)) - - for j, storageKeyVV := range storageKeysElems { - storageKeyBytes, err := storageKeyVV.Bytes() - if err != nil { - return err - } - - txAccessList[i].StorageKeys[j] = BytesToHash(storageKeyBytes) - } - } - - t.SetAccessList(txAccessList) - - // V - txV := new(big.Int) - if err = getElem().GetBigInt(txV); err != nil { - return err - } - - // R - txR := new(big.Int) - if err = getElem().GetBigInt(txR); err != nil { - return err - } - - // S - txS := new(big.Int) - if err = getElem().GetBigInt(txS); err != nil { - return err - } - - t.SetSignatureValues(txV, txR, txS) - } - - return nil + return val } diff --git a/types/rlp_unmarshal_storage.go b/types/rlp_unmarshal_storage.go index f83a160ed9..352c93b3b2 100644 --- a/types/rlp_unmarshal_storage.go +++ b/types/rlp_unmarshal_storage.go @@ -29,15 +29,7 @@ func (b *Body) unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) error { // transactions if err = unmarshalRLPFrom(p, tuple[0], func(txType TxType, p *fastrlp.Parser, v *fastrlp.Value) error { - var bTxn *Transaction - switch txType { - case AccessListTx: - bTxn = NewTx(&AccessListTxn{}) - case DynamicFeeTx, StateTx, LegacyTx: - bTxn = NewTx(&MixedTxn{ - Type: txType, - }) - } + bTxn := NewTxWithType(txType) if err = bTxn.unmarshalStoreRLPFrom(p, v); err != nil { return err @@ -70,8 +62,6 @@ func (b *Body) unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) error { // UnmarshalStoreRLP unmarshals transaction from byte slice. Hash must be computed manually after! func (t *Transaction) UnmarshalStoreRLP(input []byte) error { - t.SetTransactionType(LegacyTx) - offset := 0 if len(input) > 0 && input[0] <= RLPSingleByteUpperLimit { @@ -80,7 +70,7 @@ func (t *Transaction) UnmarshalStoreRLP(input []byte) error { return err } - t.SetTransactionType(tType) + t.InitInnerData(tType) offset = 1 } @@ -105,13 +95,13 @@ func (t *Transaction) unmarshalStoreRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) return err } - t.SetTransactionType(tType) + t.InitInnerData(tType) elems = elems[1:] } // consensus part - if err = t.unmarshalRLPFrom(p, elems[0]); err != nil { + if err = t.UnmarshalRLPFrom(p, elems[0]); err != nil { return err } @@ -144,7 +134,7 @@ func (r *Receipts) unmarshalStoreRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) er } func (r *Receipt) UnmarshalStoreRLP(input []byte) error { - r.TransactionType = LegacyTx + r.TransactionType = LegacyTxType offset := 0 if len(input) > 0 && input[0] <= RLPSingleByteUpperLimit { diff --git a/types/state_tx.go b/types/state_tx.go new file mode 100644 index 0000000000..52c86e3f3b --- /dev/null +++ b/types/state_tx.go @@ -0,0 +1,280 @@ +package types + +import ( + "fmt" + "math/big" + + "github.com/umbracle/fastrlp" +) + +type StateTx struct { + Nonce uint64 + GasPrice *big.Int + Gas uint64 + To *Address + Value *big.Int + Input []byte + V, R, S *big.Int + From Address + Hash Hash +} + +func (tx *StateTx) transactionType() TxType { return StateTxType } +func (tx *StateTx) chainID() *big.Int { return nil } +func (tx *StateTx) input() []byte { return tx.Input } +func (tx *StateTx) gas() uint64 { return tx.Gas } +func (tx *StateTx) gasPrice() *big.Int { return tx.GasPrice } +func (tx *StateTx) gasTipCap() *big.Int { return tx.GasPrice } +func (tx *StateTx) gasFeeCap() *big.Int { return tx.GasPrice } +func (tx *StateTx) value() *big.Int { return tx.Value } +func (tx *StateTx) nonce() uint64 { return tx.Nonce } +func (tx *StateTx) to() *Address { return tx.To } +func (tx *StateTx) from() Address { return tx.From } + +func (tx *StateTx) hash() Hash { return tx.Hash } + +func (tx *StateTx) rawSignatureValues() (v, r, s *big.Int) { + return tx.V, tx.R, tx.S +} + +func (tx *StateTx) accessList() TxAccessList { + return nil +} + +// set methods for transaction fields +func (tx *StateTx) setSignatureValues(v, r, s *big.Int) { + tx.V, tx.R, tx.S = v, r, s +} + +func (tx *StateTx) setFrom(addr Address) { + tx.From = addr +} + +func (tx *StateTx) setGas(gas uint64) { + tx.Gas = gas +} + +func (tx *StateTx) setChainID(id *big.Int) {} + +func (tx *StateTx) setGasPrice(gas *big.Int) { + tx.GasPrice = gas +} + +func (tx *StateTx) setGasFeeCap(gas *big.Int) { + tx.GasPrice = gas +} + +func (tx *StateTx) setGasTipCap(gas *big.Int) { + tx.GasPrice = gas +} + +func (tx *StateTx) setValue(value *big.Int) { + tx.Value = value +} + +func (tx *StateTx) setInput(input []byte) { + tx.Input = input +} + +func (tx *StateTx) setTo(addeess *Address) { + tx.To = addeess +} + +func (tx *StateTx) setNonce(nonce uint64) { + tx.Nonce = nonce +} + +func (tx *StateTx) setAccessList(accessList TxAccessList) {} + +func (tx *StateTx) setHash(h Hash) { tx.Hash = h } + +// unmarshalRLPFrom unmarshals a Transaction in RLP format +// Be careful! This function does not de-serialize tx type, it assumes that t.Type is already set +// Hash calculation should also be done from the outside! +// Use UnmarshalRLP in most cases +func (tx *StateTx) unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) error { + numOfElems := 10 + + var ( + values rlpValues + err error + ) + + values, err = v.GetElems() + if err != nil { + return err + } + + if numElems := len(values); numElems != numOfElems { + return fmt.Errorf("incorrect number of transaction elements, expected %d but found %d", numOfElems, numElems) + } + + // nonce + txNonce, err := values.dequeueValue().GetUint64() + if err != nil { + return err + } + + tx.setNonce(txNonce) + + // gasPrice + txGasPrice := new(big.Int) + if err = values.dequeueValue().GetBigInt(txGasPrice); err != nil { + return err + } + + tx.setGasPrice(txGasPrice) + + // gas + txGas, err := values.dequeueValue().GetUint64() + if err != nil { + return err + } + + tx.setGas(txGas) + + // to + if vv, _ := values.dequeueValue().Bytes(); len(vv) == 20 { + // address + addr := BytesToAddress(vv) + tx.setTo(&addr) + } else { + // reset To + tx.setTo(nil) + } + + // value + txValue := new(big.Int) + if err = values.dequeueValue().GetBigInt(txValue); err != nil { + return err + } + + tx.setValue(txValue) + + // input + var txInput []byte + + txInput, err = values.dequeueValue().GetBytes(txInput) + if err != nil { + return err + } + + tx.setInput(txInput) + + // V + txV := new(big.Int) + if err = values.dequeueValue().GetBigInt(txV); err != nil { + return err + } + + // R + txR := new(big.Int) + if err = values.dequeueValue().GetBigInt(txR); err != nil { + return err + } + + // S + txS := new(big.Int) + if err = values.dequeueValue().GetBigInt(txS); err != nil { + return err + } + + tx.setSignatureValues(txV, txR, txS) + + tx.setFrom(ZeroAddress) + + // We need to set From field for state transaction, + // because we are using unique, predefined address, for sending such transactions + if vv, err := values.dequeueValue().Bytes(); err == nil && len(vv) == AddressLength { + // address + tx.setFrom(BytesToAddress(vv)) + } + + return nil +} + +// MarshalRLPWith marshals the transaction to RLP with a specific fastrlp.Arena +// Be careful! This function does not serialize tx type as a first byte. +// Use MarshalRLP/MarshalRLPTo in most cases +func (tx *StateTx) marshalRLPWith(arena *fastrlp.Arena) *fastrlp.Value { + vv := arena.NewArray() + + vv.Set(arena.NewUint(tx.nonce())) + vv.Set(arena.NewBigInt(tx.gasPrice())) + vv.Set(arena.NewUint(tx.gas())) + // Address may be empty + if tx.to() != nil { + vv.Set(arena.NewCopyBytes(tx.to().Bytes())) + } else { + vv.Set(arena.NewNull()) + } + + vv.Set(arena.NewBigInt(tx.value())) + vv.Set(arena.NewCopyBytes(tx.input())) + + // signature values + v, r, s := tx.rawSignatureValues() + vv.Set(arena.NewBigInt(v)) + vv.Set(arena.NewBigInt(r)) + vv.Set(arena.NewBigInt(s)) + + vv.Set(arena.NewCopyBytes(tx.from().Bytes())) + + return vv +} + +func (tx *StateTx) copy() TxData { //nolint:dupl + cpy := &StateTx{} + + cpy.setNonce(tx.nonce()) + + if tx.gasPrice() != nil { + gasPrice := new(big.Int) + gasPrice.Set(tx.gasPrice()) + + cpy.setGasPrice(gasPrice) + } + + cpy.setGas(tx.gas()) + + cpy.setTo(tx.to()) + + if tx.value() != nil { + value := new(big.Int) + value.Set(tx.value()) + + cpy.setValue(value) + } + + inputCopy := make([]byte, len(tx.input())) + copy(inputCopy, tx.input()[:]) + + cpy.setInput(inputCopy) + + v, r, s := tx.rawSignatureValues() + + var vCopy, rCopy, sCopy *big.Int + + if v != nil { + vCopy = new(big.Int) + vCopy.Set(v) + } + + if r != nil { + rCopy = new(big.Int) + rCopy.Set(r) + } + + if s != nil { + sCopy = new(big.Int) + sCopy.Set(s) + } + + cpy.setSignatureValues(vCopy, rCopy, sCopy) + + cpy.setFrom(tx.from()) + + cpy.setHash(tx.hash()) + + return cpy +} diff --git a/types/transaction.go b/types/transaction.go index 64c508c323..8df1a40ddc 100644 --- a/types/transaction.go +++ b/types/transaction.go @@ -7,6 +7,7 @@ import ( "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/helper/keccak" + "github.com/umbracle/fastrlp" ) const ( @@ -19,17 +20,17 @@ type TxType byte // List of supported transaction types const ( - LegacyTx TxType = 0x0 - AccessListTx TxType = 0x01 - DynamicFeeTx TxType = 0x02 - StateTx TxType = 0x7f + LegacyTxType TxType = 0x0 + AccessListTxType TxType = 0x01 + DynamicFeeTxType TxType = 0x02 + StateTxType TxType = 0x7f ) func txTypeFromByte(b byte) (TxType, error) { tt := TxType(b) switch tt { - case LegacyTx, StateTx, DynamicFeeTx, AccessListTx: + case LegacyTxType, StateTxType, DynamicFeeTxType, AccessListTxType: return tt, nil default: return tt, fmt.Errorf("unknown transaction type: %d", b) @@ -39,13 +40,13 @@ func txTypeFromByte(b byte) (TxType, error) { // String returns string representation of the transaction type. func (t TxType) String() (s string) { switch t { - case LegacyTx: + case LegacyTxType: return "LegacyTx" - case StateTx: + case StateTxType: return "StateTx" - case DynamicFeeTx: + case DynamicFeeTxType: return "DynamicFeeTx" - case AccessListTx: + case AccessListTxType: return "AccessListTx" } @@ -72,13 +73,15 @@ func NewTx(inner TxData) *Transaction { // depending on the value of txType. func (t *Transaction) InitInnerData(txType TxType) { switch txType { - case AccessListTx: + case AccessListTxType: t.Inner = &AccessListTxn{} + case StateTxType: + t.Inner = &StateTx{} + case LegacyTxType: + t.Inner = &LegacyTx{} default: - t.Inner = &MixedTxn{} + t.Inner = &DynamicFeeTx{} } - - t.Inner.setTransactionType(txType) } type TxData interface { @@ -105,13 +108,15 @@ type TxData interface { setGasPrice(*big.Int) setGasFeeCap(*big.Int) setGasTipCap(*big.Int) - setTransactionType(TxType) setValue(*big.Int) setInput([]byte) setTo(address *Address) setNonce(uint64) setAccessList(TxAccessList) setHash(Hash) + unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) error + marshalRLPWith(arena *fastrlp.Arena) *fastrlp.Value + copy() TxData } func (t *Transaction) Type() TxType { @@ -199,10 +204,6 @@ func (t *Transaction) SetGasTipCap(gas *big.Int) { t.Inner.setGasTipCap(gas) } -func (t *Transaction) SetTransactionType(tType TxType) { - t.Inner.setTransactionType(tType) -} - func (t *Transaction) SetValue(value *big.Int) { t.Inner.setValue(value) } @@ -227,6 +228,14 @@ func (t *Transaction) SetHash(h Hash) { t.Inner.setHash(h) } +func (t *Transaction) MarshalRLPWith(a *fastrlp.Arena) *fastrlp.Value { + return t.Inner.marshalRLPWith(a) +} + +func (t *Transaction) UnmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) error { + return t.Inner.unmarshalRLPFrom(p, v) +} + // IsContractCreation checks if tx is contract creation func (t *Transaction) IsContractCreation() bool { return t.To() == nil @@ -258,102 +267,12 @@ func (t *Transaction) Copy() *Transaction { } newTx := new(Transaction) - innerCopy := CopyTxData(t.Inner) + innerCopy := t.Inner.copy() newTx.Inner = innerCopy return newTx } -// CopyTxData creates a deep copy of the provided TxData -func CopyTxData(data TxData) TxData { - if data == nil { - return nil - } - - var copyData TxData - switch data.(type) { - case *MixedTxn: - copyData = &MixedTxn{} - case *AccessListTxn: - copyData = &AccessListTxn{} - } - - if copyData == nil { - return nil - } - - copyData.setNonce(data.nonce()) - copyData.setFrom(data.from()) - copyData.setTo(data.to()) - copyData.setHash(data.hash()) - copyData.setTransactionType(data.transactionType()) - copyData.setGas(data.gas()) - - if data.chainID() != nil { - chainID := new(big.Int) - chainID.Set(data.chainID()) - - copyData.setChainID(chainID) - } - - if data.gasPrice() != nil { - gasPrice := new(big.Int) - gasPrice.Set(data.gasPrice()) - - copyData.setGasPrice(gasPrice) - } - - if data.gasTipCap() != nil { - gasTipCap := new(big.Int) - gasTipCap.Set(data.gasTipCap()) - - copyData.setGasTipCap(gasTipCap) - } - - if data.gasFeeCap() != nil { - gasFeeCap := new(big.Int) - gasFeeCap.Set(data.gasFeeCap()) - - copyData.setGasFeeCap(gasFeeCap) - } - - if data.value() != nil { - value := new(big.Int) - value.Set(data.value()) - - copyData.setValue(value) - } - - v, r, s := data.rawSignatureValues() - - var vCopy, rCopy, sCopy *big.Int - - if v != nil { - vCopy = new(big.Int) - vCopy.Set(v) - } - - if r != nil { - rCopy = new(big.Int) - rCopy.Set(r) - } - - if s != nil { - sCopy = new(big.Int) - sCopy.Set(s) - } - - copyData.setSignatureValues(vCopy, rCopy, sCopy) - - inputCopy := make([]byte, len(data.input())) - copy(inputCopy, data.input()[:]) - - copyData.setInput(inputCopy) - copyData.setAccessList(data.accessList().Copy()) - - return copyData -} - // Cost returns gas * gasPrice + value func (t *Transaction) Cost() *big.Int { var factor *big.Int @@ -435,7 +354,7 @@ func (t *Transaction) EffectiveGasTip(baseFee *big.Int) *big.Int { // Spec: https://eips.ethereum.org/EIPS/eip-1559#specification func (t *Transaction) GetGasTipCap() *big.Int { switch t.Type() { - case DynamicFeeTx: + case DynamicFeeTxType: return t.GasTipCap() default: return t.GasPrice() @@ -446,7 +365,7 @@ func (t *Transaction) GetGasTipCap() *big.Int { // Spec: https://eips.ethereum.org/EIPS/eip-1559#specification func (t *Transaction) GetGasFeeCap() *big.Int { switch t.Type() { - case DynamicFeeTx: + case DynamicFeeTxType: return t.GasFeeCap() default: return t.GasPrice() @@ -463,3 +382,11 @@ func FindTxByHash(txs []*Transaction, hash Hash) (*Transaction, int) { return nil, -1 } + +func NewTxWithType(txType TxType) *Transaction { + tx := &Transaction{} + + tx.InitInnerData(txType) + + return tx +} diff --git a/types/types_test.go b/types/types_test.go index aae6150e70..170c4f30e0 100644 --- a/types/types_test.go +++ b/types/types_test.go @@ -68,11 +68,10 @@ func TestEIP55(t *testing.T) { func TestTransactionCopy(t *testing.T) { addrTo := StringToAddress("11") - txn := NewTx(&MixedTxn{ + txn := NewTx(&DynamicFeeTx{ Nonce: 0, GasTipCap: big.NewInt(11), GasFeeCap: big.NewInt(11), - GasPrice: big.NewInt(11), Gas: 11, To: &addrTo, Value: big.NewInt(1),