From 5ee0157897ede0145e0b39ae53335cbe693b51d3 Mon Sep 17 00:00:00 2001 From: DreamWuGit Date: Wed, 18 Sep 2024 10:28:37 +0800 Subject: [PATCH] add pre-eip155 evm circuit test (#1412) * try add pre-eip155 test * move test out of tx_access_list * fix build * try mock existing pre-eip155 tx * use CircuitsParams for test pass for default feature * log tx type * try restore chain_id * comment chain_id and remove build_pre_eip155_tx * test tx with sig v=27 * MockTransaction::copy_from * refactor * add note * fix clippy * fix ci * some updates * figure out to use clone_from --- .../src/circuit_input_builder/transaction.rs | 6 ++ geth-utils/l2geth/trace.go | 14 +++- mock/src/transaction.rs | 8 ++ .../src/evm_circuit/execution/begin_tx.rs | 80 ++++++++++++++++++- 4 files changed, 105 insertions(+), 3 deletions(-) diff --git a/bus-mapping/src/circuit_input_builder/transaction.rs b/bus-mapping/src/circuit_input_builder/transaction.rs index fa32dc87f8..e733a388dc 100644 --- a/bus-mapping/src/circuit_input_builder/transaction.rs +++ b/bus-mapping/src/circuit_input_builder/transaction.rs @@ -343,6 +343,12 @@ impl Transaction { ); let tx_type = TxType::get_tx_type(eth_tx); + log::debug!( + "{:?}th tx, tx hash {:?}, tx_type {:?}", + eth_tx.transaction_index, + eth_tx.hash(), + tx_type + ); let (l1_fee, l1_fee_committed) = if tx_type.is_l1_msg() { Default::default() } else { diff --git a/geth-utils/l2geth/trace.go b/geth-utils/l2geth/trace.go index 39f6ea377a..a930c10701 100644 --- a/geth-utils/l2geth/trace.go +++ b/geth-utils/l2geth/trace.go @@ -90,8 +90,20 @@ func transferTxs(txs []Transaction, chainID *big.Int) types.Transactions { } t_txs = append(t_txs, types.NewTx(l1msgTx)) } else { - switch tx.Type { + case "PreEip155": + t := &types.LegacyTx{ + Nonce: uint64(tx.Nonce), + GasPrice: toBigInt(tx.GasPrice), + Gas: uint64(tx.GasLimit), + To: tx.To, + Value: toBigInt(tx.Value), + Data: tx.CallData, + V: big.NewInt(tx.V), + R: tx.R.ToInt(), + S: tx.S.ToInt(), + } + t_txs = append(t_txs, types.NewTx(t)) case "Eip155": t := &types.LegacyTx{ Nonce: uint64(tx.Nonce), diff --git a/mock/src/transaction.rs b/mock/src/transaction.rs index d05701c9ca..9da59dcfea 100644 --- a/mock/src/transaction.rs +++ b/mock/src/transaction.rs @@ -345,6 +345,10 @@ impl MockTransaction { .value(self.value) .data(self.input.clone()) .gas(self.gas) + // Note: even pre-eip155 type transaction doesn't have chain_id field, here having chain_id won't + // result in negative effects, because eventually geth_type::Transaction decide the tx type by TxType::get_tx_type(tx) + // then trace.go will treat it as correct pre-eip155 type transaction. the additional chain_id + // is not used finally. .chain_id(self.chain_id); let tx = if let Some(gas_price) = self.gas_price { @@ -359,6 +363,9 @@ impl MockTransaction { }; match (self.v, self.r, self.s) { + (Some(_), Some(_), Some(_)) => { + // already have entire signature data, won't do anything. + } (None, None, None) => { // Compute sig params and set them in case we have a wallet as `from` attr. if self.from.is_wallet() && self.hash.is_none() { @@ -372,6 +379,7 @@ impl MockTransaction { self.sig_data((sig.v, sig.r, sig.s)); } } + _ => panic!("Either all or none of the SigData params have to be set"), } diff --git a/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs b/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs index be786f8da2..07ddda9764 100644 --- a/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs +++ b/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs @@ -1254,9 +1254,10 @@ mod test { use std::{str::FromStr, vec}; use crate::{evm_circuit::test::rand_bytes, test_util::CircuitTestBuilder}; - use bus_mapping::evm::OpcodeId; + use bus_mapping::{circuit_input_builder::CircuitsParams, evm::OpcodeId}; use eth_types::{ - self, address, bytecode, evm_types::GasCost, word, Address, Bytecode, Hash, Word, U256, + self, address, bytecode, evm_types::GasCost, word, Address, Bytecode, Error, Hash, Word, + U256, }; use ethers_core::{types::Bytes, utils::get_contract_address}; use mock::{eth, gwei, MockTransaction, TestContext, MOCK_ACCOUNTS}; @@ -1737,4 +1738,79 @@ mod test { .block_modifier(Box::new(|block| block.circuits_params.max_txs = 3)) .run(); } + + // Note: all pre-eip155 txs here for testing have signature data. don't need to generate signature dynamically + // because ethers-rs lib's helper `sign_transaction_sync` doesn't support pre-eip155 type. + #[test] + fn test_legacy_tx_pre_eip155() { + let mut tx1 = MockTransaction::default(); + // pre-eip155 tx1 downloaded from [etherscan](https://etherscan.io/getRawTx?tx=0x9cd2288e69623b109e25edc46bc518156498b521e5c162d96e1ab392ff1d9dff) + // tx with signature::v =0x1c (28). + let sig_data1 = ( + 0x1c_u64, + word!("0x90b751c5870e9bc071c8d6b2bf1ee80f36ee7efd8e6fbabaa25bd3b8b68cfe9b"), + word!("0x79c25a01f12493a6d35f1330306d4e3c4e782fcbffc64c6809959577f41ff248"), + ); + + tx1 + .from(address!("0xcf40d0d2b44f2b66e07cace1372ca42b73cf21a3")) + .nonce(word!("0x2ea8")) + .gas_price(word!("0x098bca5a00")) + .gas(word!("0x0249f0")) + .value(word!("0x00")) + // Set tx type to pre-eip155. + .transaction_type(0) + .input(hex::decode("606060405260008054600160a060020a0319163317905560f2806100236000396000f3606060405260e060020a6000350463f5537ede8114601c575b6002565b3460025760f06004356024356044356000805433600160a060020a039081169116141560ea5783905080600160a060020a031663a9059cbb84846000604051602001526040518360e060020a0281526004018083600160a060020a0316815260200182815260200192505050602060405180830381600087803b1560025760325a03f1156002575050604080518481529051600160a060020a0386811693508716917fd0ed88a3f042c6bbb1e3ea406079b5f2b4b198afccaa535d837f4c63abbc4de6919081900360200190a35b50505050565b00") + .expect("hex data can be decoded").into()) + .sig_data(sig_data1); + + // pre-eip155 tx2 refers to https://github.com/scroll-tech/go-ethereum/blob/develop/cmd/evm/testdata/3/txs.json. + let mut tx2 = MockTransaction::default(); + // tx with signature::v =0x1b (27). + let sig_data2 = ( + 0x1b_u64, + word!("0x88544c93a564b4c28d2ffac2074a0c55fdd4658fe0d215596ed2e32e3ef7f56b"), + word!("0x7fb4075d54190f825d7c47bb820284757b34fd6293904a93cddb1d3aa961ac28"), + ); + + tx2.from(address!("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .to(address!("0x095e7baea6a6c7c4c2dfeb977efac326af552d87")) + .nonce(word!("0x0")) + .gas_price(word!("0x1")) + .gas(word!("0x5f5e100")) + .value(word!("0x186a0")) + // Set tx type to pre-eip155. + .transaction_type(0) + .sig_data(sig_data2); + + for tx in [tx1, tx2] { + let ctx = build_legacy_ctx(gwei(8_000_000), &tx).unwrap(); + CircuitTestBuilder::new_from_test_ctx(ctx) + .params(CircuitsParams { + max_calldata: 300, + ..Default::default() + }) + .run() + } + } + + // build pre-eip155 tx + fn build_legacy_ctx( + sender_balance: Word, + tx: &MockTransaction, + ) -> Result, Error> { + TestContext::new( + None, + |accs| { + accs[0] + .address(tx.from.address()) + .balance(sender_balance) + .nonce(tx.nonce); + }, + |mut txs, _accs| { + txs[0].clone_from(tx); + }, + |block, _tx| block.number(0xcafeu64), + ) + } }