Skip to content

Commit

Permalink
Modularize mock crate for easier and more customizable testing setup …
Browse files Browse the repository at this point in the history
…generation (scroll-tech#349)

* mock: Add ethbloom to deps

* mock: Add MockBlock and builder methods

* mock: Add MockTransaction and builder methods

* mock: Add MockAccount and builder methods

* mock: Add build functions for mock structs

* mock: Remove BlockData from bus-mapping

* mock: Update TestContext builder sig params

* eth-types: Change `GethExecTrace` visibility to `pub`

* mock: Add const generics for ACC specification in TestContext

* Update default values for MockBlock

* mock: Accept multiple Tx's in TraceContext builder pattern

* mock: Update tests to generate Traces using TraceContext

* mock: Remove unused code in mock and refactor EndTx/BeginTx

* mock: Fix and comment BeginTx strange testscases

* mock: Fix rebase conflicts

* bus-mapping: Fix lib.rs docs

* mock: Change FACC trait to avoid returning &mut MockBlock

* mock: Add helpers for TextContext simple constructions

Adds helper functions to make the builder pattern less verbose when
there's a simple and frequent rutine being used.

Co-authored-by: ed255 <[email protected]>

* mock: Change from Bytecode to Bytes in MockAccount

Instead of requiering `Bytecode` as the type for the code passed to
MockAccount constructor, now it accepts anything that implements
`Into<Bytes>` which is much more ergonomic and generic.

* mock: Fix EXTCODEHASH errors introduced in the refactor

* mock: Add documentation & usage examples for TestContext

* bus-mapping: Shorten bolerprate with TestContext helpers

* fix docs

* Fix documentation for bus-mapping

* Fix ETH test value to point_one for BeginTx

* Fix according to review suggestions from @ed255 and @han0110

* eth_types: Add docs for GethExecTrace

* mock: Update MockTransaction `to` field to be Option

* bus-mapping: Fix CircuitInputBuilder rebased tests

* mock: Make all MOCK statics pub

* zkevm_circuits: Update end_tx testcase with correct idx and nonce

* Update TestContext to use consecutive TxId & nonce as default

By default, set the TxIndex and the Nonce values of the multiple transactions
of the context correlative so that any Ok test passes by default.
If the user decides to override these values, they'll then be set to whatever
inputs were provided by the user.

* zkevm-circuits: Fix reduce random gas_price range

Co-authored-by: ed255 <[email protected]>
  • Loading branch information
CPerezz and ed255 authored Mar 30, 2022
1 parent e612d1a commit 9cf0e56
Showing 31 changed files with 1,934 additions and 566 deletions.
141 changes: 76 additions & 65 deletions Cargo.lock

Large diffs are not rendered by default.

587 changes: 537 additions & 50 deletions bus-mapping/src/circuit_input_builder.rs

Large diffs are not rendered by default.

33 changes: 23 additions & 10 deletions bus-mapping/src/evm/opcodes/calldatacopy.rs
Original file line number Diff line number Diff line change
@@ -157,11 +157,19 @@ fn gen_memory_copy_steps(

#[cfg(test)]
mod calldatacopy_tests {
use super::*;
use crate::circuit_input_builder::ExecState;
use crate::operation::StackOp;
use eth_types::evm_types::{OpcodeId, StackAddress};
use eth_types::{bytecode, Word};
use crate::{
circuit_input_builder::ExecState,
mock::BlockData,
operation::{CallContextField, CallContextOp, StackOp, RW},
};
use eth_types::{
bytecode,
evm_types::{OpcodeId, StackAddress},
geth_types::GethData,
Word,
};

use mock::test_ctx::{helpers::*, TestContext};
use pretty_assertions::assert_eq;

#[test]
@@ -175,11 +183,16 @@ mod calldatacopy_tests {
};

// Get the execution steps from the external tracer
let block = crate::mock::BlockData::new_from_geth_data(
mock::new_single_tx_trace_code(&code).unwrap(),
);

let mut builder = block.new_circuit_input_builder();
let block: GethData = TestContext::<2, 1>::new(
None,
account_0_code_account_1_no_code(code),
tx_from_1_to_0,
|block, _tx| block.number(0xcafeu64),
)
.unwrap()
.into();

let mut builder = BlockData::new_from_geth_data(block.clone()).new_circuit_input_builder();
builder
.handle_block(&block.eth_block, &block.geth_traces)
.unwrap();
28 changes: 21 additions & 7 deletions bus-mapping/src/evm/opcodes/calldatasize.rs
Original file line number Diff line number Diff line change
@@ -40,9 +40,18 @@ impl Opcode for Calldatasize {

#[cfg(test)]
mod calldatasize_tests {
use crate::circuit_input_builder::ExecState;
use crate::operation::{CallContextField, CallContextOp, StackOp, RW};
use eth_types::{bytecode, evm_types::OpcodeId, evm_types::StackAddress};
use crate::{
circuit_input_builder::ExecState,
mock::BlockData,
operation::{CallContextField, CallContextOp, StackOp, RW},
};
use eth_types::{
bytecode,
evm_types::{OpcodeId, StackAddress},
geth_types::GethData,
};

use mock::test_ctx::{helpers::*, TestContext};
use pretty_assertions::assert_eq;

#[test]
@@ -53,11 +62,16 @@ mod calldatasize_tests {
};

// Get the execution steps from the external tracer
let block = crate::mock::BlockData::new_from_geth_data(
mock::new_single_tx_trace_code(&code).unwrap(),
);
let block: GethData = TestContext::<2, 1>::new(
None,
account_0_code_account_1_no_code(code),
tx_from_1_to_0,
|block, _tx| block.number(0xcafeu64),
)
.unwrap()
.into();

let mut builder = block.new_circuit_input_builder();
let mut builder = BlockData::new_from_geth_data(block.clone()).new_circuit_input_builder();
builder
.handle_block(&block.eth_block, &block.geth_traces)
.unwrap();
26 changes: 19 additions & 7 deletions bus-mapping/src/evm/opcodes/caller.rs
Original file line number Diff line number Diff line change
@@ -42,9 +42,16 @@ impl Opcode for Caller {

#[cfg(test)]
mod caller_tests {
use crate::circuit_input_builder::ExecState;
use crate::operation::{CallContextField, CallContextOp, StackOp, RW};
use eth_types::{bytecode, evm_types::OpcodeId, evm_types::StackAddress, ToWord};
use super::*;
use crate::{circuit_input_builder::ExecState, mock::BlockData, operation::StackOp};
use eth_types::{
bytecode,
evm_types::{OpcodeId, StackAddress},
geth_types::GethData,
ToWord,
};

use mock::test_ctx::{helpers::*, TestContext};
use pretty_assertions::assert_eq;

#[test]
@@ -55,11 +62,16 @@ mod caller_tests {
};

// Get the execution steps from the external tracer
let block = crate::mock::BlockData::new_from_geth_data(
mock::new_single_tx_trace_code(&code).unwrap(),
);
let block: GethData = TestContext::<2, 1>::new(
None,
account_0_code_account_1_no_code(code),
tx_from_1_to_0,
|block, _tx| block.number(0xcafeu64),
)
.unwrap()
.into();

let mut builder = block.new_circuit_input_builder();
let mut builder = BlockData::new_from_geth_data(block.clone()).new_circuit_input_builder();
builder
.handle_block(&block.eth_block, &block.geth_traces)
.unwrap();
27 changes: 20 additions & 7 deletions bus-mapping/src/evm/opcodes/callvalue.rs
Original file line number Diff line number Diff line change
@@ -42,9 +42,17 @@ impl Opcode for Callvalue {

#[cfg(test)]
mod callvalue_tests {
use crate::circuit_input_builder::ExecState;
use crate::operation::{CallContextField, CallContextOp, StackOp, RW};
use eth_types::{bytecode, evm_types::OpcodeId, evm_types::StackAddress};
use crate::{
circuit_input_builder::ExecState,
mock::BlockData,
operation::{CallContextField, CallContextOp, StackOp, RW},
};
use eth_types::{
bytecode,
evm_types::{OpcodeId, StackAddress},
geth_types::GethData,
};
use mock::test_ctx::{helpers::*, TestContext};
use pretty_assertions::assert_eq;

#[test]
@@ -55,11 +63,16 @@ mod callvalue_tests {
};

// Get the execution steps from the external tracer
let block = crate::mock::BlockData::new_from_geth_data(
mock::new_single_tx_trace_code(&code).unwrap(),
);
let block: GethData = TestContext::<2, 1>::new(
None,
account_0_code_account_1_no_code(code),
tx_from_1_to_0,
|block, _tx| block.number(0xcafeu64),
)
.unwrap()
.into();

let mut builder = block.new_circuit_input_builder();
let mut builder = BlockData::new_from_geth_data(block.clone()).new_circuit_input_builder();
builder
.handle_block(&block.eth_block, &block.geth_traces)
.unwrap();
21 changes: 12 additions & 9 deletions bus-mapping/src/evm/opcodes/dup.rs
Original file line number Diff line number Diff line change
@@ -34,11 +34,10 @@ impl<const N: usize> Opcode for Dup<N> {
#[cfg(test)]
mod dup_tests {
use super::*;
use crate::operation::StackOp;
use eth_types::bytecode;
use eth_types::evm_types::StackAddress;
use eth_types::word;
use crate::{mock::BlockData, operation::StackOp};
use eth_types::{bytecode, evm_types::StackAddress, geth_types::GethData, word};
use itertools::Itertools;
use mock::test_ctx::{helpers::*, TestContext};
use pretty_assertions::assert_eq;

#[test]
@@ -54,11 +53,16 @@ mod dup_tests {
};

// Get the execution steps from the external tracer
let block = crate::mock::BlockData::new_from_geth_data(
mock::new_single_tx_trace_code(&code).unwrap(),
);
let block: GethData = TestContext::<2, 1>::new(
None,
account_0_code_account_1_no_code(code),
tx_from_1_to_0,
|block, _tx| block.number(0xcafeu64),
)
.unwrap()
.into();

let mut builder = block.new_circuit_input_builder();
let mut builder = BlockData::new_from_geth_data(block.clone()).new_circuit_input_builder();
builder
.handle_block(&block.eth_block, &block.geth_traces)
.unwrap();
@@ -73,7 +77,6 @@ mod dup_tests {
.iter()
.filter(|step| step.exec_state.is_dup())
.collect_vec()[i];

assert_eq!(
[0, 1]
.map(|idx| &builder.block.container.stack
75 changes: 45 additions & 30 deletions bus-mapping/src/evm/opcodes/extcodehash.rs
Original file line number Diff line number Diff line change
@@ -133,11 +133,13 @@ mod extcodehash_tests {
use crate::mock::BlockData;
use crate::operation::StackOp;
use eth_types::{
address, bytecode, evm_types::OpcodeId, geth_types::Account as GethAccount, Address,
Bytecode, Bytes, U256,
address, bytecode,
evm_types::{OpcodeId, StackAddress},
geth_types::GethData,
Bytecode, Bytes, Word, U256,
};
use ethers_core::utils::keccak256;
use mock::new_single_tx_trace_accounts;
use mock::TestContext;
use pretty_assertions::assert_eq;

#[test]
@@ -178,36 +180,49 @@ mod extcodehash_tests {
EXTCODEHASH
STOP
});
let mut nonce = Word::from(300u64);
let mut balance = Word::from(800u64);
let mut code_ext = Bytes::from([34, 54, 56]);

let mut accounts = vec![GethAccount {
address: Address::default(), // This is the address of the executing account
code: Bytes::from(code.to_vec()),
..Default::default()
}];

// Let the external account exist, if needed, by making its code non-empty
let (mut nonce, mut balance, mut code) = (U256::zero(), U256::zero(), Bytes::default());
if exists {
nonce = U256::from(300u64);
balance = U256::from(800u64);
code = Bytes::from([34, 54, 56]);

accounts.push(GethAccount {
address: external_address,
nonce,
balance,
code: code.clone(),
..Default::default()
})
if !exists {
nonce = Word::zero();
balance = Word::zero();
code_ext = Bytes::default();
}
let code_hash = keccak256(&code).into();

// Get the execution steps from the external tracer
let geth_data = new_single_tx_trace_accounts(accounts)?;
let block = BlockData::new_from_geth_data(geth_data);
let block: GethData = TestContext::<3, 1>::new(
None,
|accs| {
accs[0]
.address(address!("0x0000000000000000000000000000000000000010"))
.balance(Word::from(1u64 << 20))
.code(code.clone());

accs[1]
.address(external_address)
.balance(balance)
.nonce(nonce)
.code(code_ext.clone());

accs[2]
.address(address!("0x0000000000000000000000000000000000cafe01"))
.balance(Word::from(1u64 << 20));
},
|mut txs, accs| {
txs[0].to(accs[0].address).from(accs[2].address);
},
|block, _tx| block.number(0xcafeu64),
)
.unwrap()
.into();

let code_hash = Word::from(keccak256(code_ext));

let mut builder = block.new_circuit_input_builder();
builder.handle_block(&block.eth_block, &block.geth_traces)?;
let mut builder = BlockData::new_from_geth_data(block.clone()).new_circuit_input_builder();
builder
.handle_block(&block.eth_block, &block.geth_traces)
.unwrap();

// Check that `external_address` is in access list as a result of bus mapping.
assert!(builder.sdb.add_account_to_access_list(external_address));
@@ -233,7 +248,7 @@ mod extcodehash_tests {
RW::READ,
&StackOp {
call_id,
address: 1023.into(),
address: StackAddress::from(1023u32),
value: external_address.to_word()
}
)
@@ -349,7 +364,7 @@ mod extcodehash_tests {
RW::WRITE,
&StackOp {
call_id,
address: 1023.into(),
address: 1023u32.into(),
value: if exists { code_hash } else { U256::zero() }
}
)
29 changes: 20 additions & 9 deletions bus-mapping/src/evm/opcodes/mload.rs
Original file line number Diff line number Diff line change
@@ -60,12 +60,18 @@ impl Opcode for Mload {
#[cfg(test)]
mod mload_tests {
use super::*;
use crate::circuit_input_builder::ExecState;
use crate::operation::{MemoryOp, StackOp};
use eth_types::bytecode;
use eth_types::evm_types::{OpcodeId, StackAddress};
use eth_types::Word;
use crate::{
circuit_input_builder::ExecState,
mock::BlockData,
operation::{MemoryOp, StackOp},
};
use eth_types::{
bytecode,
evm_types::{OpcodeId, StackAddress},
geth_types::GethData,
};
use itertools::Itertools;
use mock::test_ctx::{helpers::*, TestContext};
use pretty_assertions::assert_eq;

#[test]
@@ -79,11 +85,16 @@ mod mload_tests {
};

// Get the execution steps from the external tracer
let block = crate::mock::BlockData::new_from_geth_data(
mock::new_single_tx_trace_code(&code).unwrap(),
);
let block: GethData = TestContext::<2, 1>::new(
None,
account_0_code_account_1_no_code(code),
tx_from_1_to_0,
|block, _tx| block.number(0xcafeu64),
)
.unwrap()
.into();

let mut builder = block.new_circuit_input_builder();
let mut builder = BlockData::new_from_geth_data(block.clone()).new_circuit_input_builder();
builder
.handle_block(&block.eth_block, &block.geth_traces)
.unwrap();
Loading

0 comments on commit 9cf0e56

Please sign in to comment.