Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: unify tx types(1559, 2930, pre155 etc) tests into dedicated folder #1425

Merged
merged 8 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading