diff --git a/bus-mapping/src/evm/opcodes.rs b/bus-mapping/src/evm/opcodes.rs index c034b8440d..4d1585a889 100644 --- a/bus-mapping/src/evm/opcodes.rs +++ b/bus-mapping/src/evm/opcodes.rs @@ -23,6 +23,7 @@ mod caller; mod callvalue; mod dup; mod extcodehash; +mod gasprice; mod mload; mod mstore; mod number; @@ -39,6 +40,7 @@ use caller::Caller; use callvalue::Callvalue; use dup::Dup; use extcodehash::Extcodehash; +use gasprice::GasPrice; use mload::Mload; use mstore::Mstore; use selfbalance::Selfbalance; @@ -113,7 +115,7 @@ fn fn_gen_associated_ops(opcode_id: &OpcodeId) -> FnGenAssociatedOps { OpcodeId::CALLDATACOPY => Calldatacopy::gen_associated_ops, // OpcodeId::CODESIZE => {}, // OpcodeId::CODECOPY => {}, - // OpcodeId::GASPRICE => {}, + OpcodeId::GASPRICE => GasPrice::gen_associated_ops, // OpcodeId::EXTCODESIZE => {}, // OpcodeId::EXTCODECOPY => {}, // OpcodeId::RETURNDATASIZE => {}, diff --git a/bus-mapping/src/evm/opcodes/gasprice.rs b/bus-mapping/src/evm/opcodes/gasprice.rs new file mode 100644 index 0000000000..1f94bc91d3 --- /dev/null +++ b/bus-mapping/src/evm/opcodes/gasprice.rs @@ -0,0 +1,124 @@ +use super::Opcode; +use crate::circuit_input_builder::{CircuitInputStateRef, ExecStep}; +use crate::operation::{CallContextField, CallContextOp, RW}; +use crate::Error; +use eth_types::GethExecStep; + +/// Placeholder structure used to implement [`Opcode`] trait over it +/// corresponding to the [`OpcodeId::PC`](crate::evm::OpcodeId::PC) `OpcodeId`. +#[derive(Debug, Copy, Clone)] +pub(crate) struct GasPrice; + +impl Opcode for GasPrice { + fn gen_associated_ops( + state: &mut CircuitInputStateRef, + geth_steps: &[GethExecStep], + ) -> Result, Error> { + let geth_step = &geth_steps[0]; + let mut exec_step = state.new_step(geth_step)?; + // Get gasprice result from next step + let value = geth_steps[1].stack.last()?; + let tx_id = state.tx_ctx.id(); + + // CallContext read of the TxId + state.push_op( + &mut exec_step, + RW::READ, + CallContextOp { + call_id: state.call()?.call_id, + field: CallContextField::TxId, + value: tx_id.into(), + }, + ); + + // Stack write of the gasprice value + state.push_stack_op( + &mut exec_step, + RW::WRITE, + geth_step.stack.last_filled().map(|a| a - 1), + value, + )?; + + Ok(vec![exec_step]) + } +} + +#[cfg(test)] +mod gasprice_tests { + use crate::{ + circuit_input_builder::ExecState, + evm::OpcodeId, + mock::BlockData, + operation::{CallContextField, CallContextOp, StackOp, RW}, + Error, + }; + use eth_types::{bytecode, evm_types::StackAddress, geth_types::GethData, Word}; + use mock::test_ctx::{helpers::*, TestContext}; + use pretty_assertions::assert_eq; + + #[test] + fn gasprice_opcode_impl() -> Result<(), Error> { + let code = bytecode! { + #[start] + GASPRICE + STOP + }; + + let two_gwei = Word::from(2_000_000_000u64); + + // Get the execution steps from the external tracer + let block: GethData = TestContext::<2, 1>::new( + None, + account_0_code_account_1_no_code(code), + |mut txs, accs| { + txs[0] + .from(accs[1].address) + .to(accs[0].address) + .gas_price(two_gwei); + }, + |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(); + + let step = builder.block.txs()[0] + .steps() + .iter() + .find(|step| step.exec_state == ExecState::Op(OpcodeId::GASPRICE)) + .unwrap(); + + let op_gasprice = &builder.block.container.stack[step.bus_mapping_instance[1].as_usize()]; + assert_eq!( + (op_gasprice.rw(), op_gasprice.op()), + ( + RW::WRITE, + &StackOp::new(1, StackAddress(1023usize), two_gwei) + ) + ); + + let call_id = builder.block.txs()[0].calls()[0].call_id; + + assert_eq!( + { + let operation = + &builder.block.container.call_context[step.bus_mapping_instance[0].as_usize()]; + (operation.rw(), operation.op()) + }, + ( + RW::READ, + &CallContextOp { + call_id, + field: CallContextField::TxId, + value: Word::one(), + } + ) + ); + + Ok(()) + } +} diff --git a/mock/src/test_ctx.rs b/mock/src/test_ctx.rs index 0375de660c..c232768f62 100644 --- a/mock/src/test_ctx.rs +++ b/mock/src/test_ctx.rs @@ -6,6 +6,7 @@ use eth_types::{ Block, Bytecode, Error, GethExecTrace, Transaction, Word, }; use external_tracer::{trace, TraceConfig}; +use helpers::*; use itertools::Itertools; /// TestContext is a type that contains all the information from a block @@ -185,6 +186,20 @@ impl TestContext { geth_traces, }) } + + /// Returns a simple TestContext setup with a single tx executing the + /// bytecode passed as parameters. The balances of the 2 accounts and + /// addresses are the ones used in [`TestContext:: + /// account_0_code_account_1_no_code`]. Extra accounts, txs and/or block + /// configs are set as [`Default`]. + pub fn simple_ctx_with_bytecode(bytecode: Bytecode) -> Result, Error> { + TestContext::new( + None, + account_0_code_account_1_no_code(bytecode), + tx_from_1_to_0, + |block, _txs| block, + ) + } } /// Generates execution traces for the transactions included in the provided @@ -228,11 +243,11 @@ pub mod helpers { |accs| { accs[0] .address(MOCK_ACCOUNTS[0]) - .balance(Word::from(1u64 << 20)) + .balance(Word::from(10u64.pow(19))) .code(code); accs[1] .address(MOCK_ACCOUNTS[1]) - .balance(Word::from(1u64 << 20)); + .balance(Word::from(10u64.pow(19))); } } diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 7942895a1f..5fe0bfe46c 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -35,6 +35,7 @@ mod end_tx; mod error_oog_static_memory; mod extcodehash; mod gas; +mod gasprice; mod is_zero; mod jump; mod jumpdest; @@ -74,6 +75,7 @@ use end_tx::EndTxGadget; use error_oog_static_memory::ErrorOOGStaticMemoryGadget; use extcodehash::ExtcodehashGadget; use gas::GasGadget; +use gasprice::GasPriceGadget; use is_zero::IsZeroGadget; use jump::JumpGadget; use jumpdest::JumpdestGadget; @@ -139,6 +141,7 @@ pub(crate) struct ExecutionConfig { jump_gadget: JumpGadget, jumpdest_gadget: JumpdestGadget, jumpi_gadget: JumpiGadget, + gasprice_gadget: GasPriceGadget, gas_gadget: GasGadget, memory_gadget: MemoryGadget, copy_to_memory_gadget: CopyToMemoryGadget, @@ -358,6 +361,7 @@ impl ExecutionConfig { jumpdest_gadget: configure_gadget!(), jumpi_gadget: configure_gadget!(), gas_gadget: configure_gadget!(), + gasprice_gadget: configure_gadget!(), memory_gadget: configure_gadget!(), copy_to_memory_gadget: configure_gadget!(), pc_gadget: configure_gadget!(), @@ -630,6 +634,7 @@ impl ExecutionConfig { assign_exec_step!(self.jumpdest_gadget) } ExecutionState::GAS => assign_exec_step!(self.gas_gadget), + ExecutionState::GASPRICE => assign_exec_step!(self.gasprice_gadget), ExecutionState::PUSH => assign_exec_step!(self.push_gadget), ExecutionState::DUP => assign_exec_step!(self.dup_gadget), ExecutionState::SWAP => assign_exec_step!(self.swap_gadget), diff --git a/zkevm-circuits/src/evm_circuit/execution/add.rs b/zkevm-circuits/src/evm_circuit/execution/add.rs index fd56a5194d..af19e0c418 100644 --- a/zkevm-circuits/src/evm_circuit/execution/add.rs +++ b/zkevm-circuits/src/evm_circuit/execution/add.rs @@ -108,6 +108,7 @@ mod test { use crate::test_util::run_test_circuits; use eth_types::evm_types::OpcodeId; use eth_types::{bytecode, Word}; + use mock::TestContext; fn test_ok(opcode: OpcodeId, a: Word, b: Word) { let bytecode = bytecode! { @@ -116,7 +117,14 @@ mod test { .write_op(opcode) STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/bitwise.rs b/zkevm-circuits/src/evm_circuit/execution/bitwise.rs index 0d7b0e4465..1dc4d508f7 100644 --- a/zkevm-circuits/src/evm_circuit/execution/bitwise.rs +++ b/zkevm-circuits/src/evm_circuit/execution/bitwise.rs @@ -103,11 +103,10 @@ impl ExecutionGadget for BitwiseGadget { mod test { use crate::{ evm_circuit::test::rand_word, - test_util::{ - get_fixed_table, test_circuits_using_bytecode, BytecodeTestConfig, FixedTableConfig, - }, + test_util::{get_fixed_table, run_test_circuits, BytecodeTestConfig, FixedTableConfig}, }; use eth_types::{bytecode, Word}; + use mock::TestContext; fn test_ok(a: Word, b: Word) { let bytecode = bytecode! { @@ -128,8 +127,12 @@ mod test { evm_circuit_lookup_tags: get_fixed_table(FixedTableConfig::Complete), ..Default::default() }; + assert_eq!( - test_circuits_using_bytecode(bytecode, test_config, None), + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + Some(test_config) + ), Ok(()) ); } diff --git a/zkevm-circuits/src/evm_circuit/execution/byte.rs b/zkevm-circuits/src/evm_circuit/execution/byte.rs index be71a6440f..670493c1ae 100644 --- a/zkevm-circuits/src/evm_circuit/execution/byte.rs +++ b/zkevm-circuits/src/evm_circuit/execution/byte.rs @@ -129,6 +129,7 @@ impl ExecutionGadget for ByteGadget { mod test { use crate::{evm_circuit::test::rand_word, test_util::run_test_circuits}; use eth_types::{bytecode, Word}; + use mock::TestContext; fn test_ok(index: Word, value: Word) { let bytecode = bytecode! { @@ -137,7 +138,14 @@ mod test { BYTE STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs b/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs index b1d1ac9967..9f78367f90 100644 --- a/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs +++ b/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs @@ -234,13 +234,14 @@ mod test { test::{rand_bytes, run_test_circuit_incomplete_fixed_table}, witness::{Block, Bytecode, Call, CodeSource, ExecStep, Rw, RwMap, Transaction}, }; - use crate::test_util::{test_circuits_using_bytecode, BytecodeTestConfig}; + use crate::test_util::run_test_circuits; use eth_types::{ bytecode, evm_types::{gas_utils::memory_copier_gas_cost, GasCost, OpcodeId}, ToBigEndian, Word, }; use halo2_proofs::arithmetic::BaseExt; + use mock::test_ctx::{helpers::*, TestContext}; use pairing::bn256::Fr as Fp; fn test_ok_root(call_data_length: usize, memory_offset: Word, data_offset: Word, length: Word) { @@ -253,11 +254,22 @@ mod test { STOP }; let call_data = rand_bytes(call_data_length); - let test_config = BytecodeTestConfig::default(); - assert_eq!( - test_circuits_using_bytecode(bytecode, test_config, Some(call_data)), - Ok(()) - ); + + // Get the execution steps from the external tracer + let ctx = TestContext::<2, 1>::new( + None, + account_0_code_account_1_no_code(bytecode), + |mut txs, accs| { + txs[0] + .from(accs[1].address) + .to(accs[0].address) + .input(call_data.into()); + }, + |block, _tx| block.number(0xcafeu64), + ) + .unwrap(); + + assert_eq!(run_test_circuits(ctx, None), Ok(())); } fn test_ok_internal( diff --git a/zkevm-circuits/src/evm_circuit/execution/caller.rs b/zkevm-circuits/src/evm_circuit/execution/caller.rs index 6e67e1c009..19c273c2ba 100644 --- a/zkevm-circuits/src/evm_circuit/execution/caller.rs +++ b/zkevm-circuits/src/evm_circuit/execution/caller.rs @@ -92,16 +92,21 @@ impl ExecutionGadget for CallerGadget { mod test { use crate::test_util::run_test_circuits; use eth_types::bytecode; + use mock::TestContext; - fn test_ok() { + #[test] + fn caller_gadget_test() { let bytecode = bytecode! { CALLER STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); - } - #[test] - fn caller_gadget_test() { - test_ok(); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } } diff --git a/zkevm-circuits/src/evm_circuit/execution/callvalue.rs b/zkevm-circuits/src/evm_circuit/execution/callvalue.rs index 65b54e5790..274ff18b1a 100644 --- a/zkevm-circuits/src/evm_circuit/execution/callvalue.rs +++ b/zkevm-circuits/src/evm_circuit/execution/callvalue.rs @@ -90,16 +90,21 @@ impl ExecutionGadget for CallValueGadget { mod test { use crate::test_util::run_test_circuits; use eth_types::bytecode; + use mock::TestContext; - fn test_ok() { + #[test] + fn callvalue_gadget_test() { let bytecode = bytecode! { CALLVALUE STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); - } - #[test] - fn callvalue_gadget_test() { - test_ok(); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } } diff --git a/zkevm-circuits/src/evm_circuit/execution/coinbase.rs b/zkevm-circuits/src/evm_circuit/execution/coinbase.rs index 96458ddc03..a256b74cc5 100644 --- a/zkevm-circuits/src/evm_circuit/execution/coinbase.rs +++ b/zkevm-circuits/src/evm_circuit/execution/coinbase.rs @@ -91,16 +91,21 @@ impl ExecutionGadget for CoinbaseGadget { mod test { use crate::test_util::run_test_circuits; use eth_types::bytecode; + use mock::TestContext; - fn test_ok() { + #[test] + fn coinbase_gadget_test() { let bytecode = bytecode! { COINBASE STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); - } - #[test] - fn coinbase_gadget_test() { - test_ok(); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } } diff --git a/zkevm-circuits/src/evm_circuit/execution/comparator.rs b/zkevm-circuits/src/evm_circuit/execution/comparator.rs index acd95d397a..3880b780e1 100644 --- a/zkevm-circuits/src/evm_circuit/execution/comparator.rs +++ b/zkevm-circuits/src/evm_circuit/execution/comparator.rs @@ -171,6 +171,7 @@ mod test { use crate::{evm_circuit::test::rand_word, test_util::run_test_circuits}; use eth_types::evm_types::OpcodeId; use eth_types::{bytecode, Word}; + use mock::TestContext; fn test_ok(opcode: OpcodeId, a: Word, b: Word, _c: Word) { let bytecode = bytecode! { @@ -179,7 +180,14 @@ mod test { .write_op(opcode) STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/dup.rs b/zkevm-circuits/src/evm_circuit/execution/dup.rs index dd3a9a76c2..d18346d154 100644 --- a/zkevm-circuits/src/evm_circuit/execution/dup.rs +++ b/zkevm-circuits/src/evm_circuit/execution/dup.rs @@ -85,6 +85,7 @@ mod test { use crate::{evm_circuit::test::rand_word, test_util::run_test_circuits}; use eth_types::evm_types::OpcodeId; use eth_types::{bytecode, Word}; + use mock::TestContext; fn test_ok(opcode: OpcodeId, value: Word) { let n = (opcode.as_u8() - OpcodeId::DUP1.as_u8() + 1) as usize; @@ -98,7 +99,14 @@ mod test { .write_op(opcode) STOP }); - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/gas.rs b/zkevm-circuits/src/evm_circuit/execution/gas.rs index c514dd2ecd..2183831ca1 100644 --- a/zkevm-circuits/src/evm_circuit/execution/gas.rs +++ b/zkevm-circuits/src/evm_circuit/execution/gas.rs @@ -99,7 +99,14 @@ mod test { GAS STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/gasprice.rs b/zkevm-circuits/src/evm_circuit/execution/gasprice.rs new file mode 100644 index 0000000000..c16f758642 --- /dev/null +++ b/zkevm-circuits/src/evm_circuit/execution/gasprice.rs @@ -0,0 +1,127 @@ +use crate::{ + evm_circuit::{ + execution::ExecutionGadget, + step::ExecutionState, + table::{CallContextFieldTag, TxContextFieldTag}, + util::{ + common_gadget::SameContextGadget, + constraint_builder::{ConstraintBuilder, StepStateTransition, Transition::Delta}, + Cell, Word, + }, + witness::{Block, Call, ExecStep, Transaction}, + }, + util::Expr, +}; +use bus_mapping::evm::OpcodeId; +use eth_types::{Field, ToLittleEndian}; +use halo2_proofs::{circuit::Region, plonk::Error}; + +#[derive(Clone, Debug)] +pub(crate) struct GasPriceGadget { + tx_id: Cell, + gas_price: Cell, + same_context: SameContextGadget, +} + +impl ExecutionGadget for GasPriceGadget { + const NAME: &'static str = "GASPRICE"; + + const EXECUTION_STATE: ExecutionState = ExecutionState::GASPRICE; + + fn configure(cb: &mut ConstraintBuilder) -> Self { + // Query gasprice value + let gas_price = cb.query_cell(); + + // Lookup in call_ctx the TxId + let tx_id = cb.call_context(None, CallContextFieldTag::TxId); + // Lookup the gas_price in tx table + cb.tx_context_lookup( + tx_id.expr(), + TxContextFieldTag::GasPrice, + None, + gas_price.expr(), + ); + + // Push the value to the stack + cb.stack_push(gas_price.expr()); + + // State transition + let opcode = cb.query_cell(); + let step_state_transition = StepStateTransition { + rw_counter: Delta(2u64.expr()), + program_counter: Delta(1u64.expr()), + stack_pointer: Delta((-1i32).expr()), + gas_left: Delta(-OpcodeId::GASPRICE.constant_gas_cost().expr()), + ..Default::default() + }; + let same_context = SameContextGadget::construct(cb, opcode, step_state_transition); + + Self { + tx_id, + gas_price, + same_context, + } + } + + fn assign_exec_step( + &self, + region: &mut Region<'_, F>, + offset: usize, + block: &Block, + tx: &Transaction, + _: &Call, + step: &ExecStep, + ) -> Result<(), Error> { + let gas_price = block.rws.sorted_stack_rw()[0].stack_value(); + + self.tx_id + .assign(region, offset, Some(F::from(tx.id as u64)))?; + + self.gas_price.assign( + region, + offset, + Some(Word::random_linear_combine( + gas_price.to_le_bytes(), + block.randomness, + )), + )?; + + self.same_context.assign_exec_step(region, offset, step)?; + + Ok(()) + } +} + +#[cfg(test)] +mod test { + use crate::test_util::run_test_circuits; + use eth_types::{bytecode, Word}; + use mock::test_ctx::{helpers::*, TestContext}; + + #[test] + fn gasprice_gadget_test() { + let bytecode = bytecode! { + #[start] + GASPRICE + STOP + }; + + let two_gwei = Word::from(2_000_000_000u64); + + // Get the execution steps from the external tracer + let ctx = TestContext::<2, 1>::new( + None, + account_0_code_account_1_no_code(bytecode), + |mut txs, accs| { + txs[0] + .from(accs[1].address) + .to(accs[0].address) + .gas_price(two_gwei); + }, + |block, _tx| block.number(0xcafeu64), + ) + .unwrap(); + + assert_eq!(run_test_circuits(ctx, None), Ok(())); + } +} diff --git a/zkevm-circuits/src/evm_circuit/execution/is_zero.rs b/zkevm-circuits/src/evm_circuit/execution/is_zero.rs index 76e9b02488..9e0d25e0ef 100644 --- a/zkevm-circuits/src/evm_circuit/execution/is_zero.rs +++ b/zkevm-circuits/src/evm_circuit/execution/is_zero.rs @@ -77,6 +77,7 @@ impl ExecutionGadget for IsZeroGadget { mod test { use crate::test_util::run_test_circuits; use eth_types::{bytecode, Word}; + use mock::TestContext; fn test_ok(value: Word) { let bytecode = bytecode! { @@ -84,7 +85,14 @@ mod test { ISZERO STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/jump.rs b/zkevm-circuits/src/evm_circuit/execution/jump.rs index e7ca28fe22..f03dd65af0 100644 --- a/zkevm-circuits/src/evm_circuit/execution/jump.rs +++ b/zkevm-circuits/src/evm_circuit/execution/jump.rs @@ -90,6 +90,7 @@ impl ExecutionGadget for JumpGadget { mod test { use crate::{evm_circuit::test::rand_range, test_util::run_test_circuits}; use eth_types::bytecode; + use mock::TestContext; fn test_ok(destination: usize) { assert!((34..(1 << 24) - 1).contains(&destination)); @@ -105,7 +106,14 @@ mod test { JUMPDEST STOP }); - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/jumpdest.rs b/zkevm-circuits/src/evm_circuit/execution/jumpdest.rs index 4f6fceb175..43bb85647d 100644 --- a/zkevm-circuits/src/evm_circuit/execution/jumpdest.rs +++ b/zkevm-circuits/src/evm_circuit/execution/jumpdest.rs @@ -54,18 +54,21 @@ impl ExecutionGadget for JumpdestGadget { mod test { use crate::test_util::run_test_circuits; use eth_types::bytecode; + use mock::TestContext; - fn test_ok() { + #[test] + fn jumpdest_gadget_simple() { let bytecode = bytecode! { JUMPDEST STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); - } - - #[test] - fn jumpdest_gadget_simple() { - test_ok(); + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } } diff --git a/zkevm-circuits/src/evm_circuit/execution/jumpi.rs b/zkevm-circuits/src/evm_circuit/execution/jumpi.rs index daf0dda9e8..03e6fe363a 100644 --- a/zkevm-circuits/src/evm_circuit/execution/jumpi.rs +++ b/zkevm-circuits/src/evm_circuit/execution/jumpi.rs @@ -120,6 +120,7 @@ mod test { test_util::run_test_circuits, }; use eth_types::{bytecode, Word}; + use mock::TestContext; fn test_ok(destination: usize, condition: Word) { assert!((68..(1 << 24) - 1).contains(&destination)); @@ -137,7 +138,14 @@ mod test { JUMPDEST STOP }); - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/memory.rs b/zkevm-circuits/src/evm_circuit/execution/memory.rs index d0c0e251ff..dd55f1e947 100644 --- a/zkevm-circuits/src/evm_circuit/execution/memory.rs +++ b/zkevm-circuits/src/evm_circuit/execution/memory.rs @@ -192,11 +192,12 @@ impl ExecutionGadget for MemoryGadget { mod test { use crate::{ evm_circuit::test::rand_word, - test_util::{test_circuits_using_bytecode, BytecodeTestConfig}, + test_util::{run_test_circuits, BytecodeTestConfig}, }; use eth_types::bytecode; use eth_types::evm_types::{GasCost, OpcodeId}; use eth_types::Word; + use mock::test_ctx::{helpers::*, TestContext}; use std::iter; fn test_ok(opcode: OpcodeId, address: Word, value: Word, gas_cost: u64) { @@ -217,10 +218,21 @@ mod test { enable_state_circuit_test: false, ..Default::default() }; - assert_eq!( - test_circuits_using_bytecode(bytecode, test_config, None), - Ok(()) - ); + + let ctx = TestContext::<2, 1>::new( + None, + account_0_code_account_1_no_code(bytecode), + |mut txs, accs| { + txs[0] + .to(accs[0].address) + .from(accs[1].address) + .gas(Word::from(test_config.gas_limit)); + }, + |block, _tx| block.number(0xcafeu64), + ) + .unwrap(); + + assert_eq!(run_test_circuits(ctx, Some(test_config)), Ok(())); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/msize.rs b/zkevm-circuits/src/evm_circuit/execution/msize.rs index a3de581cec..f16aede9a3 100644 --- a/zkevm-circuits/src/evm_circuit/execution/msize.rs +++ b/zkevm-circuits/src/evm_circuit/execution/msize.rs @@ -81,6 +81,7 @@ impl ExecutionGadget for MsizeGadget { mod test { use crate::test_util::run_test_circuits; use eth_types::{bytecode, Word}; + use mock::TestContext; #[test] fn msize_gadget() { @@ -94,6 +95,12 @@ mod test { STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } } diff --git a/zkevm-circuits/src/evm_circuit/execution/mul.rs b/zkevm-circuits/src/evm_circuit/execution/mul.rs index e75393dece..919824fab3 100644 --- a/zkevm-circuits/src/evm_circuit/execution/mul.rs +++ b/zkevm-circuits/src/evm_circuit/execution/mul.rs @@ -76,6 +76,7 @@ mod test { use crate::{evm_circuit::test::rand_word, test_util::run_test_circuits}; use eth_types::evm_types::OpcodeId; use eth_types::{bytecode, Word}; + use mock::TestContext; fn test_ok(opcode: OpcodeId, a: Word, b: Word) { let bytecode = bytecode! { @@ -84,7 +85,14 @@ mod test { .write_op(opcode) STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/number.rs b/zkevm-circuits/src/evm_circuit/execution/number.rs index e6562c6d57..74a7d68034 100644 --- a/zkevm-circuits/src/evm_circuit/execution/number.rs +++ b/zkevm-circuits/src/evm_circuit/execution/number.rs @@ -86,6 +86,7 @@ impl ExecutionGadget for NumberGadget { mod test { use crate::test_util::run_test_circuits; use eth_types::bytecode; + use mock::TestContext; #[test] fn number_gadget_test() { @@ -94,6 +95,13 @@ mod test { NUMBER STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } } diff --git a/zkevm-circuits/src/evm_circuit/execution/pc.rs b/zkevm-circuits/src/evm_circuit/execution/pc.rs index 61d8aefbee..88adb60867 100644 --- a/zkevm-circuits/src/evm_circuit/execution/pc.rs +++ b/zkevm-circuits/src/evm_circuit/execution/pc.rs @@ -79,6 +79,7 @@ impl ExecutionGadget for PcGadget { mod test { use crate::test_util::run_test_circuits; use eth_types::bytecode; + use mock::TestContext; fn test_ok() { let bytecode = bytecode! { @@ -86,7 +87,14 @@ mod test { PC STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/pop.rs b/zkevm-circuits/src/evm_circuit/execution/pop.rs index b41177725b..2b42951b59 100644 --- a/zkevm-circuits/src/evm_circuit/execution/pop.rs +++ b/zkevm-circuits/src/evm_circuit/execution/pop.rs @@ -78,6 +78,7 @@ impl ExecutionGadget for PopGadget { mod test { use crate::{evm_circuit::test::rand_word, test_util::run_test_circuits}; use eth_types::{bytecode, Word}; + use mock::TestContext; fn test_ok(value: Word) { let bytecode = bytecode! { @@ -85,7 +86,14 @@ mod test { POP STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/push.rs b/zkevm-circuits/src/evm_circuit/execution/push.rs index 19e431a4b4..d16248e8f0 100644 --- a/zkevm-circuits/src/evm_circuit/execution/push.rs +++ b/zkevm-circuits/src/evm_circuit/execution/push.rs @@ -147,6 +147,7 @@ mod test { use crate::{evm_circuit::test::rand_bytes, test_util::run_test_circuits}; use eth_types::bytecode; use eth_types::evm_types::OpcodeId; + use mock::TestContext; fn test_ok(opcode: OpcodeId, bytes: &[u8]) { assert!(bytes.len() as u8 == opcode.as_u8() - OpcodeId::PUSH1.as_u8() + 1,); @@ -159,7 +160,13 @@ mod test { } bytecode.write_op(OpcodeId::STOP); - assert_eq!(run_test_circuits(bytecode), Ok(())); + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/selfbalance.rs b/zkevm-circuits/src/evm_circuit/execution/selfbalance.rs index 7a00c82c62..e351a5f403 100644 --- a/zkevm-circuits/src/evm_circuit/execution/selfbalance.rs +++ b/zkevm-circuits/src/evm_circuit/execution/selfbalance.rs @@ -89,6 +89,7 @@ impl ExecutionGadget for SelfbalanceGadget { mod test { use crate::test_util::run_test_circuits; use eth_types::bytecode; + use mock::TestContext; #[test] fn selfbalance_gadget_test() { @@ -96,6 +97,13 @@ mod test { SELFBALANCE STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } } diff --git a/zkevm-circuits/src/evm_circuit/execution/signed_comparator.rs b/zkevm-circuits/src/evm_circuit/execution/signed_comparator.rs index bff64b730f..41e5624b86 100644 --- a/zkevm-circuits/src/evm_circuit/execution/signed_comparator.rs +++ b/zkevm-circuits/src/evm_circuit/execution/signed_comparator.rs @@ -221,6 +221,7 @@ mod test { use eth_types::bytecode; use eth_types::evm_types::OpcodeId; use eth_types::Word; + use mock::TestContext; use crate::{evm_circuit::test::rand_word, test_util::run_test_circuits}; @@ -232,7 +233,14 @@ mod test { bytecode.write_op(opcode); } bytecode.write_op(OpcodeId::STOP); - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/signextend.rs b/zkevm-circuits/src/evm_circuit/execution/signextend.rs index 4bbd307a79..2bfb7389b8 100644 --- a/zkevm-circuits/src/evm_circuit/execution/signextend.rs +++ b/zkevm-circuits/src/evm_circuit/execution/signextend.rs @@ -207,6 +207,7 @@ impl ExecutionGadget for SignextendGadget { mod test { use crate::{evm_circuit::test::rand_word, test_util::run_test_circuits}; use eth_types::{bytecode, ToLittleEndian, Word}; + use mock::TestContext; fn test_ok(index: Word, value: Word, _result: Word) { let bytecode = bytecode! { @@ -215,7 +216,14 @@ mod test { SIGNEXTEND STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/swap.rs b/zkevm-circuits/src/evm_circuit/execution/swap.rs index 0a8540ebfc..0518c7ce0c 100644 --- a/zkevm-circuits/src/evm_circuit/execution/swap.rs +++ b/zkevm-circuits/src/evm_circuit/execution/swap.rs @@ -93,6 +93,7 @@ mod test { use crate::{evm_circuit::test::rand_word, test_util::run_test_circuits}; use eth_types::evm_types::OpcodeId; use eth_types::{bytecode, Word}; + use mock::TestContext; fn test_ok(opcode: OpcodeId, lhs: Word, rhs: Word) { let n = (opcode.as_u8() - OpcodeId::SWAP1.as_u8() + 1) as usize; @@ -108,7 +109,14 @@ mod test { .write_op(opcode) STOP }); - assert_eq!(run_test_circuits(bytecode), Ok(())); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } #[test] diff --git a/zkevm-circuits/src/evm_circuit/execution/timestamp.rs b/zkevm-circuits/src/evm_circuit/execution/timestamp.rs index bb8dbe4ddb..0c1663102a 100644 --- a/zkevm-circuits/src/evm_circuit/execution/timestamp.rs +++ b/zkevm-circuits/src/evm_circuit/execution/timestamp.rs @@ -84,16 +84,21 @@ impl ExecutionGadget for TimestampGadget { mod test { use crate::test_util::run_test_circuits; use eth_types::bytecode; + use mock::TestContext; - fn test_ok() { + #[test] + fn timestamp_gadget_test() { let bytecode = bytecode! { TIMESTAMP STOP }; - assert_eq!(run_test_circuits(bytecode), Ok(())); - } - #[test] - fn timestamp_gadget_test() { - test_ok(); + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); } } diff --git a/zkevm-circuits/src/evm_circuit/witness.rs b/zkevm-circuits/src/evm_circuit/witness.rs index 3886036089..d032af8d5f 100644 --- a/zkevm-circuits/src/evm_circuit/witness.rs +++ b/zkevm-circuits/src/evm_circuit/witness.rs @@ -1093,6 +1093,7 @@ impl From<&circuit_input_builder::ExecStep> for ExecutionState { OpcodeId::JUMPDEST => ExecutionState::JUMPDEST, OpcodeId::JUMP => ExecutionState::JUMP, OpcodeId::JUMPI => ExecutionState::JUMPI, + OpcodeId::GASPRICE => ExecutionState::GASPRICE, OpcodeId::PC => ExecutionState::PC, OpcodeId::MSIZE => ExecutionState::MSIZE, OpcodeId::CALLER => ExecutionState::CALLER, diff --git a/zkevm-circuits/src/test_util.rs b/zkevm-circuits/src/test_util.rs index dde21abaff..c97dad9d5f 100644 --- a/zkevm-circuits/src/test_util.rs +++ b/zkevm-circuits/src/test_util.rs @@ -3,7 +3,7 @@ use crate::{ state_circuit::StateCircuit, }; use bus_mapping::mock::BlockData; -use eth_types::{address, geth_types::GethData, Bytes, Word}; +use eth_types::geth_types::GethData; use halo2_proofs::dev::{MockProver, VerifyFailure}; use mock::TestContext; use pairing::bn256::Fr; @@ -49,39 +49,11 @@ impl Default for BytecodeTestConfig { } } -pub fn run_test_circuits(bytecode: eth_types::Bytecode) -> Result<(), Vec> { - test_circuits_using_bytecode(bytecode, BytecodeTestConfig::default(), None) -} - -pub fn test_circuits_using_bytecode( - bytecode: eth_types::Bytecode, - config: BytecodeTestConfig, - call_data: Option>, +pub fn run_test_circuits( + test_ctx: TestContext, + config: Option, ) -> Result<(), Vec> { - // Create a custom tx setting Gas to - let block: GethData = TestContext::<2, 1>::new( - None, - |accs| { - accs[0] - .address(address!("0x0000000000000000000000000000000000000010")) - .balance(Word::from(1u64 << 20)) - .code(bytecode); - accs[1] - .address(address!("0x0000000000000000000000000000000000000000")) - .balance(Word::from(1u64 << 30)); - }, - |mut txs, accs| { - txs[0] - .to(accs[0].address) - .from(accs[1].address) - .gas(Word::from(config.gas_limit)) - .input(Bytes::from(call_data.unwrap_or_default())); - }, - |block, _tx| block.number(0xcafeu64), - ) - .unwrap() - .into(); - + let block: GethData = test_ctx.into(); let mut builder = BlockData::new_from_geth_data(block.clone()).new_circuit_input_builder(); builder .handle_block(&block.eth_block, &block.geth_traces) @@ -91,7 +63,7 @@ pub fn test_circuits_using_bytecode( let block = crate::evm_circuit::witness::block_convert(&builder.block, &builder.code_db); // finish required tests according to config using this witness block - test_circuits_using_witness_block(block, config) + test_circuits_using_witness_block(block, config.unwrap_or_default()) } pub fn test_circuits_using_witness_block(