Skip to content

Commit

Permalink
Refactor: unify tx types(1559, 2930, pre155 etc) tests into dedicated…
Browse files Browse the repository at this point in the history
… folder (#1425)

* tests folder and move preeip155, 1559 tests into

* move 2930 tests

* add eip155

* rename

* fix clippy

* mod and clean

* fix clippy

* fmt fix
  • Loading branch information
DreamWuGit authored Sep 20, 2024
1 parent 2879c23 commit fab9d65
Show file tree
Hide file tree
Showing 10 changed files with 337 additions and 288 deletions.
3 changes: 3 additions & 0 deletions zkevm-circuits/src/evm_circuit/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ use strum::{EnumCount, IntoEnumIterator};
pub(crate) static CHECK_RW_LOOKUP: LazyLock<bool> =
LazyLock::new(|| read_env_var("CHECK_RW_LOOKUP", false));

#[cfg(any(feature = "test", test))]
mod tests;

mod add_sub;
mod addmod;
mod address;
Expand Down
80 changes: 2 additions & 78 deletions zkevm-circuits/src/evm_circuit/execution/begin_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1254,10 +1254,9 @@ mod test {
use std::{str::FromStr, vec};

use crate::{evm_circuit::test::rand_bytes, test_util::CircuitTestBuilder};
use bus_mapping::{circuit_input_builder::CircuitsParams, evm::OpcodeId};
use bus_mapping::evm::OpcodeId;
use eth_types::{
self, address, bytecode, evm_types::GasCost, word, Address, Bytecode, Error, Hash, Word,
U256,
self, address, bytecode, evm_types::GasCost, word, Address, Bytecode, Hash, Word, U256,
};
use ethers_core::{types::Bytes, utils::get_contract_address};
use mock::{eth, gwei, MockTransaction, TestContext, MOCK_ACCOUNTS};
Expand Down Expand Up @@ -1738,79 +1737,4 @@ 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<TestContext<1, 1>, 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),
)
}
}
37 changes: 37 additions & 0 deletions zkevm-circuits/src/evm_circuit/execution/tests/eip155.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// tests for eip155 tx
#[cfg(test)]
mod tx_type_test {
use crate::test_util::CircuitTestBuilder;
use eth_types::{Error, Word};
use ethers_signers::Signer;
use mock::{eth, gwei, TestContext, MOCK_ACCOUNTS, MOCK_WALLETS};

#[test]
fn test_eip155() {
let ctx = build_ctx(gwei(80_000)).unwrap();
CircuitTestBuilder::new_from_test_ctx(ctx).run();
}

fn build_ctx(sender_balance: Word) -> Result<TestContext<2, 1>, Error> {
TestContext::new(
None,
|accs| {
accs[0]
.address(MOCK_WALLETS[0].address())
.balance(sender_balance);
accs[1].address(MOCK_ACCOUNTS[0]).balance(eth(1));
},
|mut txs, _accs| {
txs[0]
.from(MOCK_WALLETS[0].clone())
.to(MOCK_ACCOUNTS[0])
.gas(40_000.into())
.gas_price(30_000.into())
.value(gwei(20_000))
// Set tx type to EIP-155.
.transaction_type(0);
},
|block, _tx| block.number(0xcafeu64),
)
}
}
107 changes: 107 additions & 0 deletions zkevm-circuits/src/evm_circuit/execution/tests/eip1559.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#[cfg(test)]
mod tx_type_test {
use crate::test_util::CircuitTestBuilder;
use eth_types::{Error, Word};
use ethers_signers::Signer;
use mock::{eth, gwei, TestContext, MOCK_ACCOUNTS, MOCK_WALLETS};

#[test]
fn test_eip1559_tx_for_equal_balance() {
let balance = if cfg!(feature = "scroll") {
// l1 fee
gwei(80_000) + Word::from(279u64)
} else {
gwei(80_000)
};
let ctx = build_ctx(balance, gwei(2), gwei(2)).unwrap();
CircuitTestBuilder::new_from_test_ctx(ctx).run();
}

#[test]
fn test_eip1559_tx_for_less_balance() {
let res = build_ctx(gwei(79_999), gwei(2), gwei(2));

#[cfg(not(feature = "scroll"))]
let expected_err = "Failed to run Trace, err: Failed to apply config.Transactions[0]: insufficient funds for gas * price + value: address 0xEeFca179F40D3B8b3D941E6A13e48835a3aF8241 have 79999000000000 want 80000000000000";

// "80000000000279": 279 is l1 fee
#[cfg(feature = "scroll")]
let expected_err = "Failed to run Trace, err: insufficient funds for gas * price + value: address 0xEeFca179F40D3B8b3D941E6A13e48835a3aF8241 have 79999000000000 want 80000000000279";

// Address `0xEeFca179F40D3B8b3D941E6A13e48835a3aF8241` in error message comes from
// MOCK_WALLETS[0] in build_ctx.

// Return a tracing error if insufficient sender balance.
if let Error::TracingError(err) = res.unwrap_err() {
assert_eq!(err, expected_err);
} else {
panic!("Must be a tracing error");
}
}

#[test]
fn test_eip1559_tx_for_more_balance() {
let ctx = build_ctx(gwei(80_001), gwei(2), gwei(2)).unwrap();
CircuitTestBuilder::new_from_test_ctx(ctx).run();
}

#[test]
fn test_eip1559_tx_for_gas_fee_cap_gt_gas_tip_cap() {
// Should be successful if `max_fee_per_gas > max_priority_fee_per_gas`.
let balance = if cfg!(feature = "scroll") {
// l1 fee
gwei(80_000) + Word::from(279u64)
} else {
gwei(80_000)
};
let ctx = build_ctx(balance, gwei(2), gwei(1)).unwrap();

CircuitTestBuilder::new_from_test_ctx(ctx).run();
}

#[test]
fn test_eip1559_tx_for_gas_fee_cap_lt_gas_tip_cap() {
let res = build_ctx(gwei(80_000), gwei(1), gwei(2));

#[cfg(not(feature = "scroll"))]
let expected_err = "Failed to run Trace, err: Failed to apply config.Transactions[0]: max priority fee per gas higher than max fee per gas: address 0xEeFca179F40D3B8b3D941E6A13e48835a3aF8241, maxPriorityFeePerGas: 2000000000, maxFeePerGas: 1000000000";
#[cfg(feature = "scroll")]
let expected_err = "Failed to run Trace, err: max priority fee per gas higher than max fee per gas: address 0xEeFca179F40D3B8b3D941E6A13e48835a3aF8241, maxPriorityFeePerGas: 2000000000, maxFeePerGas: 1000000000";
// Address `0xEeFca179F40D3B8b3D941E6A13e48835a3aF8241` in error message comes from
// MOCK_WALLETS[0] in build_ctx.

// Return a tracing error if `max_fee_per_gas < max_priority_fee_per_gas`.
if let Error::TracingError(err) = res.unwrap_err() {
assert_eq!(err, expected_err);
} else {
panic!("Must be a tracing error");
}
}

fn build_ctx(
sender_balance: Word,
max_fee_per_gas: Word,
max_priority_fee_per_gas: Word,
) -> Result<TestContext<2, 1>, Error> {
TestContext::new(
None,
|accs| {
accs[0]
.address(MOCK_WALLETS[0].address())
.balance(sender_balance);
accs[1].address(MOCK_ACCOUNTS[0]).balance(eth(1));
},
|mut txs, _accs| {
txs[0]
.from(MOCK_WALLETS[0].clone())
.to(MOCK_ACCOUNTS[0])
.gas(30_000.into())
.value(gwei(20_000))
.max_fee_per_gas(max_fee_per_gas)
.max_priority_fee_per_gas(max_priority_fee_per_gas)
.transaction_type(2); // Set tx type to EIP-1559.
},
|block, _tx| block.number(0xcafeu64),
)
}
}
97 changes: 97 additions & 0 deletions zkevm-circuits/src/evm_circuit/execution/tests/eip2930.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// tests for eip2930
#[cfg(test)]
mod tx_type_test {
use crate::test_util::CircuitTestBuilder;
use eth_types::{address, AccessList, AccessListItem, Error, Word, H256};
use ethers_signers::Signer;
use mock::{eth, gwei, TestContext, MOCK_ACCOUNTS, MOCK_WALLETS};

// test with empty access list.
#[test]
fn test_eip2930_tx_for_empty_access_list() {
// CASE1: tx not set access list, `access_list` field is none.
let ctx = build_ctx(gwei(80_000), None).unwrap();
CircuitTestBuilder::new_from_test_ctx(ctx).run();

// CASE2: tx set empty (neither address nor storage keys at all) access list into
// `access_list` field. this field is not none.
let test_access_list: AccessList = AccessList(vec![]);

let ctx = build_ctx(gwei(80_000), Some(test_access_list)).unwrap();
CircuitTestBuilder::new_from_test_ctx(ctx).run();
}

// test with non empty access list(address + storage keys list)
#[test]
fn test_eip2930_non_empty_access_list() {
let test_access_list: AccessList = AccessList(vec![
AccessListItem {
address: address!("0xEeFca179F40D3B8b3D941E6A13e48835a3aF8241"),
// one storage key
storage_keys: [10].map(H256::from_low_u64_be).to_vec(),
},
AccessListItem {
address: address!("0x0000000000000000000000000000000000001111"),
// two storage keys
storage_keys: [10, 11].map(H256::from_low_u64_be).to_vec(),
},
AccessListItem {
address: address!("0x0000000000000000000000000000000000002222"),
// three storage keys
storage_keys: [20, 22, 50].map(H256::from_low_u64_be).to_vec(),
},
]);

let ctx = build_ctx(gwei(80_000), Some(test_access_list)).unwrap();
CircuitTestBuilder::new_from_test_ctx(ctx).run();
}

// test with non empty access list(only address list)
#[test]
fn test_eip2930_only_address_access_list() {
let test_access_list: AccessList = AccessList(vec![
AccessListItem {
address: address!("0xEeFca179F40D3B8b3D941E6A13e48835a3aF8241"),
// no storage keys
storage_keys: Vec::new(),
},
AccessListItem {
address: address!("0x0000000000000000000000000000000000001111"),
// no storage keys
storage_keys: Vec::new(),
},
]);

let ctx = build_ctx(gwei(80_000), Some(test_access_list)).unwrap();
CircuitTestBuilder::new_from_test_ctx(ctx).run();
}

fn build_ctx(
sender_balance: Word,
access_list: Option<AccessList>,
) -> Result<TestContext<2, 1>, Error> {
TestContext::new(
None,
|accs| {
accs[0]
.address(MOCK_WALLETS[0].address())
.balance(sender_balance);
accs[1].address(MOCK_ACCOUNTS[0]).balance(eth(1));
},
|mut txs, _accs| {
txs[0]
.from(MOCK_WALLETS[0].clone())
.to(MOCK_ACCOUNTS[0])
.gas(40_000.into())
.gas_price(30_000.into())
.value(gwei(20_000))
.transaction_type(1); // Set tx type to EIP-2930.

if let Some(acc_list) = access_list {
txs[0].access_list(acc_list);
}
},
|block, _tx| block.number(0xcafeu64),
)
}
}
7 changes: 7 additions & 0 deletions zkevm-circuits/src/evm_circuit/execution/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// this fold only contains tx type tests, for all opcode related tests are in
// each opcode gadget file.
mod eip155;
mod pre_eip155;

mod eip1559;
mod eip2930;
Loading

0 comments on commit fab9d65

Please sign in to comment.