diff --git a/bus-mapping/src/circuit_input_builder.rs b/bus-mapping/src/circuit_input_builder.rs index e26e3e1bda..eeb9f04e17 100644 --- a/bus-mapping/src/circuit_input_builder.rs +++ b/bus-mapping/src/circuit_input_builder.rs @@ -34,7 +34,7 @@ pub use execution::{ pub use input_state_ref::CircuitInputStateRef; use itertools::Itertools; use log::warn; -use std::collections::HashMap; +use std::{collections::HashMap, ops::Deref}; pub use transaction::{Transaction, TransactionContext}; /// Circuit Setup Parameters @@ -164,6 +164,7 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder { /// Create a new Transaction from a [`eth_types::Transaction`]. pub fn new_tx( &mut self, + id: u64, eth_tx: ð_types::Transaction, is_success: bool, ) -> Result { @@ -180,7 +181,14 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder { ), ); - Transaction::new(call_id, &self.sdb, &mut self.code_db, eth_tx, is_success) + Transaction::new( + id, + call_id, + &self.sdb, + &mut self.code_db, + eth_tx, + is_success, + ) } /// Iterate over all generated CallContext RwCounterEndOfReversion @@ -214,8 +222,9 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder { eth_tx: ð_types::Transaction, geth_trace: &GethExecTrace, is_last_tx: bool, + tx_index: u64, ) -> Result<(), Error> { - let mut tx = self.new_tx(eth_tx, !geth_trace.failed)?; + let mut tx = self.new_tx(tx_index, eth_tx, !geth_trace.failed)?; let mut tx_ctx = TransactionContext::new(eth_tx, geth_trace, is_last_tx)?; // Generate BeginTx step @@ -318,9 +327,16 @@ impl CircuitInputBuilder { geth_traces: &[eth_types::GethExecTrace], ) -> Result<(), Error> { // accumulates gas across all txs in the block - for (tx_index, tx) in eth_block.transactions.iter().enumerate() { - let geth_trace = &geth_traces[tx_index]; - self.handle_tx(tx, geth_trace, tx_index + 1 == eth_block.transactions.len())?; + for (idx, tx) in eth_block.transactions.iter().enumerate() { + let geth_trace = &geth_traces[idx]; + // Transaction index starts from 1 + let tx_id = idx + 1; + self.handle_tx( + tx, + geth_trace, + tx_id == eth_block.transactions.len(), + tx_id as u64, + )?; } // set eth_block self.block.eth_block = eth_block.clone(); @@ -404,7 +420,7 @@ impl CircuitInputBuilder { pub fn keccak_inputs(block: &Block, code_db: &CodeDB) -> Result>, Error> { let mut keccak_inputs = Vec::new(); // Tx Circuit - let txs: Vec = block.txs.iter().map(|tx| tx.tx.clone()).collect(); + let txs: Vec = block.txs.iter().map(|tx| tx.deref().clone()).collect(); keccak_inputs.extend_from_slice(&keccak_inputs_tx_circuit(&txs, block.chain_id.as_u64())?); // Bytecode Circuit for bytecode in code_db.0.values() { diff --git a/bus-mapping/src/circuit_input_builder/tracer_tests.rs b/bus-mapping/src/circuit_input_builder/tracer_tests.rs index b64a15a4f8..e38df7f159 100644 --- a/bus-mapping/src/circuit_input_builder/tracer_tests.rs +++ b/bus-mapping/src/circuit_input_builder/tracer_tests.rs @@ -37,7 +37,7 @@ impl CircuitInputBuilderTx { let block = crate::mock::BlockData::new_from_geth_data(geth_data.clone()); let mut builder = block.new_circuit_input_builder(); let tx = builder - .new_tx(&block.eth_block.transactions[0], true) + .new_tx(0, &block.eth_block.transactions[0], true) .unwrap(); let tx_ctx = TransactionContext::new( &block.eth_block.transactions[0], diff --git a/bus-mapping/src/circuit_input_builder/transaction.rs b/bus-mapping/src/circuit_input_builder/transaction.rs index dae4f1db35..7016c0a7dc 100644 --- a/bus-mapping/src/circuit_input_builder/transaction.rs +++ b/bus-mapping/src/circuit_input_builder/transaction.rs @@ -179,8 +179,10 @@ impl TransactionContext { #[derive(Debug, Clone, Default)] /// Result of the parsing of an Ethereum Transaction. pub struct Transaction { + /// The transaction id + pub id: u64, /// The raw transaction fields - pub tx: geth_types::Transaction, + tx: geth_types::Transaction, /// Calls made in the transaction pub(crate) calls: Vec, /// Execution steps @@ -190,6 +192,7 @@ pub struct Transaction { impl Transaction { /// Create a new Self. pub fn new( + id: u64, call_id: usize, sdb: &StateDB, code_db: &mut CodeDB, @@ -244,17 +247,13 @@ impl Transaction { }; Ok(Self { + id, tx: eth_tx.into(), calls: vec![call], steps: Vec::new(), }) } - /// Whether this [`Transaction`] is a create one - pub fn is_create(&self) -> bool { - self.calls[0].is_create() - } - /// Return the list of execution steps of this transaction. pub fn steps(&self) -> &[ExecStep] { &self.steps @@ -295,8 +294,19 @@ impl Transaction { self.steps.is_empty() } - /// Convinient method for gas limit - pub fn gas(&self) -> u64 { - self.tx.gas_limit.as_u64() + /// Constructor for padding tx in tx circuit + pub fn padding_tx(id: usize) -> Self { + Self { + id: id as u64, + ..Default::default() + } + } +} + +impl std::ops::Deref for Transaction { + type Target = geth_types::Transaction; + + fn deref(&self) -> &Self::Target { + &self.tx } } diff --git a/bus-mapping/src/evm/opcodes/begin_end_tx.rs b/bus-mapping/src/evm/opcodes/begin_end_tx.rs index e8baf7f88f..9a12bb644c 100644 --- a/bus-mapping/src/evm/opcodes/begin_end_tx.rs +++ b/bus-mapping/src/evm/opcodes/begin_end_tx.rs @@ -73,7 +73,7 @@ fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result Result Result Result Result } let caller_balance_prev = caller_account.balance; let caller_balance = - caller_balance_prev + state.tx.tx.gas_price * (exec_step.gas_left + effective_refund); + caller_balance_prev + state.tx.gas_price * (exec_step.gas_left + effective_refund); state.account_write( &mut exec_step, call.caller_address, @@ -272,7 +272,7 @@ fn gen_end_tx_steps(state: &mut CircuitInputStateRef) -> Result caller_balance_prev, )?; - let effective_tip = state.tx.tx.gas_price - state.block.base_fee; + let effective_tip = state.tx.gas_price - state.block.base_fee; let (found, coinbase_account) = state.sdb.get_account(&state.block.coinbase); if !found { return Err(Error::AccountNotFound(state.block.coinbase)); diff --git a/bus-mapping/src/evm/opcodes/logs.rs b/bus-mapping/src/evm/opcodes/logs.rs index 59591da8a3..c00e677fa1 100644 --- a/bus-mapping/src/evm/opcodes/logs.rs +++ b/bus-mapping/src/evm/opcodes/logs.rs @@ -291,7 +291,7 @@ mod log_tests { .unwrap(); let is_persistent = builder.block.txs()[0].calls()[0].is_persistent; - let callee_address = builder.block.txs()[0].tx.to_or_contract_addr(); + let callee_address = builder.block.txs()[0].to_or_contract_addr(); let step = builder.block.txs()[0] .steps() diff --git a/bus-mapping/src/evm/opcodes/selfbalance.rs b/bus-mapping/src/evm/opcodes/selfbalance.rs index 41ab37386f..70c0c10f4d 100644 --- a/bus-mapping/src/evm/opcodes/selfbalance.rs +++ b/bus-mapping/src/evm/opcodes/selfbalance.rs @@ -91,7 +91,7 @@ mod selfbalance_tests { .unwrap(); let call_id = builder.block.txs()[0].calls()[0].call_id; - let callee_address = builder.block.txs()[0].tx.to_or_contract_addr(); + let callee_address = builder.block.txs()[0].to_or_contract_addr(); let self_balance = builder.sdb.get_account(&callee_address).1.balance; assert_eq!( diff --git a/circuit-benchmarks/src/pi_circuit.rs b/circuit-benchmarks/src/pi_circuit.rs index d3a4ed2ae9..294c0ba752 100644 --- a/circuit-benchmarks/src/pi_circuit.rs +++ b/circuit-benchmarks/src/pi_circuit.rs @@ -18,6 +18,7 @@ mod tests { Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, }, }; + use itertools::Itertools; use rand::SeedableRng; use rand_xorshift::XorShiftRng; use std::env::var; @@ -112,15 +113,16 @@ mod tests { } fn generate_publicdata(max_txs: usize) -> PublicData { - let mut public_data = PublicData::default(); - let chain_id = 1337u64; - public_data.chain_id = Word::from(chain_id); + let transactions = std::iter::repeat(eth_types::geth_types::Transaction::from( + mock::CORRECT_MOCK_TXS[0].clone(), + )) + .take(max_txs) + .collect_vec(); - let n_tx = max_txs; - for _ in 0..n_tx { - let eth_tx = eth_types::Transaction::from(mock::CORRECT_MOCK_TXS[0].clone()); - public_data.transactions.push(eth_tx); + PublicData { + chain_id: Word::from(1337), + transactions, + ..Default::default() } - public_data } } diff --git a/eth-types/src/geth_types.rs b/eth-types/src/geth_types.rs index 48d624ba34..176a807e71 100644 --- a/eth-types/src/geth_types.rs +++ b/eth-types/src/geth_types.rs @@ -288,6 +288,10 @@ impl Transaction { ..response::Transaction::default() } } + /// Convinient method for gas limit + pub fn gas(&self) -> u64 { + self.gas_limit.as_u64() + } } /// GethData is a type that contains all the information of a Ethereum block diff --git a/zkevm-circuits/src/evm_circuit.rs b/zkevm-circuits/src/evm_circuit.rs index 1a44579842..d3bb3e4b2a 100644 --- a/zkevm-circuits/src/evm_circuit.rs +++ b/zkevm-circuits/src/evm_circuit.rs @@ -214,7 +214,7 @@ impl EvmCircuit { pub fn get_min_num_rows_required(block: &Block) -> usize { let mut num_rows = 0; for transaction in &block.txs { - for step in &transaction.steps { + for step in transaction.steps() { num_rows += step.execution_state().get_step_height(); } } @@ -270,7 +270,7 @@ impl SubCircuit for EvmCircuit { /// create fixed_table_tags needed given witness block pub(crate) fn detect_fixed_table_tags(block: &Block) -> Vec { let need_bitwise_lookup = block.txs.iter().any(|tx| { - tx.steps.iter().any(|step| { + tx.steps().iter().any(|step| { matches!( step.opcode(), Some(OpcodeId::AND) diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index ac8fca72bb..911d8631b0 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -922,7 +922,7 @@ impl ExecutionConfig { let last_call = block .txs .last() - .map(|tx| tx.calls[0].clone()) + .map(|tx| tx.calls()[0].clone()) .unwrap_or_else(Call::default); let end_block_not_last = &block.end_block_not_last; let end_block_last = &block.end_block_last; @@ -931,9 +931,9 @@ impl ExecutionConfig { .txs .iter() .flat_map(|tx| { - tx.steps + tx.steps() .iter() - .map(move |step| (tx, &tx.calls[step.call_index], step)) + .map(move |step| (tx, &tx.calls()[step.call_index], step)) }) .chain(std::iter::once((&dummy_tx, &last_call, end_block_not_last))) .peekable(); diff --git a/zkevm-circuits/src/evm_circuit/execution/balance.rs b/zkevm-circuits/src/evm_circuit/execution/balance.rs index faed4d5097..9db943ffbe 100644 --- a/zkevm-circuits/src/evm_circuit/execution/balance.rs +++ b/zkevm-circuits/src/evm_circuit/execution/balance.rs @@ -122,7 +122,7 @@ impl ExecutionGadget for BalanceGadget { .assign_h160(region, offset, address.to_address())?; self.tx_id - .assign(region, offset, Value::known(F::from(tx.id as u64)))?; + .assign(region, offset, Value::known(F::from(tx.id)))?; self.reversion_info.assign( region, diff --git a/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs b/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs index 6a5ed3c8fd..9e337cf164 100644 --- a/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs +++ b/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs @@ -28,8 +28,7 @@ use crate::{ }, }; use bus_mapping::state_db::CodeDB; -use eth_types::{evm_types::GasCost, Field, ToWord, U256}; -use ethers_core::utils::{get_contract_address, keccak256}; +use eth_types::{evm_types::GasCost, keccak256, Field, ToWord, U256}; use halo2_proofs::{ circuit::Value, plonk::{Error, Expression}, @@ -505,7 +504,7 @@ impl ExecutionGadget for BeginTxGadget { call: &Call, step: &ExecStep, ) -> Result<(), Error> { - let gas_fee = tx.gas_price * tx.gas; + let gas_fee = tx.gas_price * tx.gas(); let zero = eth_types::Word::zero(); let mut rws = StepRws::new(block, step); @@ -513,13 +512,13 @@ impl ExecutionGadget for BeginTxGadget { let is_coinbase_warm = rws.next().tx_access_list_value_pair().1; let mut callee_code_hash = zero; - if !is_precompiled(&tx.callee_address) && !tx.is_create { + if !is_precompiled(&tx.to_or_contract_addr()) && !tx.is_create() { callee_code_hash = rws.next().account_value_pair().1; } - let callee_exists = - is_precompiled(&tx.callee_address) || (!tx.is_create && !callee_code_hash.is_zero()); + let callee_exists = is_precompiled(&tx.to_or_contract_addr()) + || (!tx.is_create() && !callee_code_hash.is_zero()); let caller_balance_sub_fee_pair = rws.next().account_value_pair(); - let must_create = tx.is_create; + let must_create = tx.is_create(); if (!callee_exists && !tx.value.is_zero()) || must_create { callee_code_hash = rws.next().account_value_pair().1; } @@ -531,52 +530,45 @@ impl ExecutionGadget for BeginTxGadget { }; self.tx_id - .assign(region, offset, Value::known(F::from(tx.id as u64)))?; + .assign(region, offset, Value::known(F::from(tx.id)))?; self.tx_nonce - .assign(region, offset, Value::known(F::from(tx.nonce)))?; + .assign(region, offset, Value::known(F::from(tx.nonce.as_u64())))?; self.tx_gas - .assign(region, offset, Value::known(F::from(tx.gas)))?; + .assign(region, offset, Value::known(F::from(tx.gas())))?; self.tx_gas_price .assign_u256(region, offset, tx.gas_price)?; self.mul_gas_fee_by_gas - .assign(region, offset, tx.gas_price, tx.gas, gas_fee)?; + .assign(region, offset, tx.gas_price, tx.gas(), gas_fee)?; self.tx_caller_address - .assign_h160(region, offset, tx.caller_address)?; + .assign_h160(region, offset, tx.from)?; self.tx_caller_address_is_zero.assign_u256( region, offset, - U256::from_big_endian(&tx.caller_address.to_fixed_bytes()), + U256::from_big_endian(&tx.from.to_fixed_bytes()), )?; self.tx_callee_address - .assign_h160(region, offset, tx.callee_address)?; - self.call_callee_address.assign_h160( - region, - offset, - if tx.is_create { - get_contract_address(tx.caller_address, tx.nonce) - } else { - tx.callee_address - }, - )?; + .assign_h160(region, offset, tx.to_or_contract_addr())?; + self.call_callee_address + .assign_h160(region, offset, tx.to_or_contract_addr())?; self.is_caller_callee_equal.assign( region, offset, - Value::known(F::from((tx.caller_address == tx.callee_address) as u64)), + Value::known(F::from((tx.from == tx.to_or_contract_addr()) as u64)), )?; self.tx_is_create - .assign(region, offset, Value::known(F::from(tx.is_create as u64)))?; + .assign(region, offset, Value::known(F::from(tx.is_create().into())))?; self.tx_call_data_length.assign( region, offset, - Value::known(F::from(tx.call_data_length as u64)), + Value::known(F::from(tx.call_data.len() as u64)), )?; self.tx_call_data_gas_cost.assign( region, offset, - Value::known(F::from(tx.call_data_gas_cost)), + Value::known(F::from(tx.call_data_gas_cost())), )?; self.tx_call_data_word_length - .assign(region, offset, tx.call_data_length as u128 + 31)?; + .assign(region, offset, tx.call_data.len() as u128 + 31)?; self.reversion_info.assign( region, offset, @@ -584,7 +576,7 @@ impl ExecutionGadget for BeginTxGadget { call.is_persistent, )?; self.sufficient_gas_left - .assign(region, offset, F::from(tx.gas - step.gas_cost))?; + .assign(region, offset, F::from(tx.gas() - step.gas_cost))?; self.transfer_with_gas_fee.assign( region, offset, @@ -608,10 +600,10 @@ impl ExecutionGadget for BeginTxGadget { let untrimmed_contract_addr = { let mut stream = ethers_core::utils::rlp::RlpStream::new(); stream.begin_list(2); - stream.append(&tx.caller_address); - stream.append(ð_types::U256::from(tx.nonce)); + stream.append(&tx.from); + stream.append(&tx.nonce.to_word()); let rlp_encoding = stream.out().to_vec(); - keccak256(rlp_encoding) + keccak256(&rlp_encoding) }; self.caller_nonce_hash_bytes.assign_u256( region, @@ -621,8 +613,8 @@ impl ExecutionGadget for BeginTxGadget { self.create.assign( region, offset, - tx.caller_address, - tx.nonce, + tx.from, + tx.nonce.as_u64(), Some(callee_code_hash), None, )?; diff --git a/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs b/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs index a6a8d19817..887bd63d75 100644 --- a/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs +++ b/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs @@ -186,16 +186,17 @@ impl ExecutionGadget for CallDataCopyGadget { let memory_address = self .memory_address .assign(region, offset, memory_offset, length)?; - let src_id = if call.is_root { tx.id } else { call.caller_id }; - self.src_id.assign( - region, - offset, - Value::known(F::from(u64::try_from(src_id).unwrap())), - )?; + let src_id = if call.is_root { + tx.id + } else { + call.caller_id as u64 + }; + self.src_id + .assign(region, offset, Value::known(F::from(src_id)))?; // Call data length and call data offset let (call_data_length, call_data_offset) = if call.is_root { - (tx.call_data_length as u64, 0_u64) + (tx.call_data.len() as u64, 0_u64) } else { (call.call_data_length, call.call_data_offset) }; diff --git a/zkevm-circuits/src/evm_circuit/execution/calldataload.rs b/zkevm-circuits/src/evm_circuit/execution/calldataload.rs index 4a8ad3a643..d7b0aba51a 100644 --- a/zkevm-circuits/src/evm_circuit/execution/calldataload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/calldataload.rs @@ -213,12 +213,16 @@ impl ExecutionGadget for CallDataLoadGadget { // Assign to the buffer reader gadget. let (src_id, call_data_offset, call_data_length) = if call.is_root { - (tx.id, 0, tx.call_data_length as u64) + (tx.id, 0, tx.call_data.len() as u64) } else { - (call.caller_id, call.call_data_offset, call.call_data_length) + ( + call.caller_id as u64, + call.call_data_offset, + call.call_data_length, + ) }; self.src_id - .assign(region, offset, Value::known(F::from(src_id as u64)))?; + .assign(region, offset, Value::known(F::from(src_id)))?; self.call_data_length .assign(region, offset, Value::known(F::from(call_data_length)))?; self.call_data_offset @@ -245,7 +249,7 @@ impl ExecutionGadget for CallDataLoadGadget { for (i, byte) in calldata_bytes.iter_mut().enumerate() { if call.is_root { // Fetch from tx call data. - if src_addr + (i as u64) < tx.call_data_length as u64 { + if src_addr + (i as u64) < tx.call_data.len() as u64 { *byte = tx.call_data[src_addr as usize + i]; } } else { diff --git a/zkevm-circuits/src/evm_circuit/execution/end_tx.rs b/zkevm-circuits/src/evm_circuit/execution/end_tx.rs index b90c3d0250..e44fcdd1de 100644 --- a/zkevm-circuits/src/evm_circuit/execution/end_tx.rs +++ b/zkevm-circuits/src/evm_circuit/execution/end_tx.rs @@ -205,15 +205,15 @@ impl ExecutionGadget for EndTxGadget { call: &Call, step: &ExecStep, ) -> Result<(), Error> { - let gas_used = tx.gas - step.gas_left; + let gas_used = tx.gas() - step.gas_left; let (refund, _) = block.get_rws(step, 2).tx_refund_value_pair(); let [(caller_balance, caller_balance_prev), (coinbase_balance, coinbase_balance_prev)] = [3, 4].map(|index| block.get_rws(step, index).account_value_pair()); self.tx_id - .assign(region, offset, Value::known(F::from(tx.id as u64)))?; + .assign(region, offset, Value::known(F::from(tx.id)))?; self.tx_gas - .assign(region, offset, Value::known(F::from(tx.gas)))?; + .assign(region, offset, Value::known(F::from(tx.gas())))?; let (max_refund, _) = self.max_refund.assign(region, offset, gas_used as u128)?; self.refund .assign(region, offset, Value::known(F::from(refund)))?; @@ -233,7 +233,7 @@ impl ExecutionGadget for EndTxGadget { gas_fee_refund, )?; self.tx_caller_address - .assign_h160(region, offset, tx.caller_address)?; + .assign_h160(region, offset, tx.from)?; self.gas_fee_refund.assign( region, offset, @@ -272,7 +272,7 @@ impl ExecutionGadget for EndTxGadget { // while later transactions need 4 (with one extra cumulative gas read) lookups let rw = &block.rws[( Target::TxReceipt, - (tx.id - 2) * (TxReceiptFieldTag::COUNT + 1) + 2, + (tx.id as usize - 2) * (TxReceiptFieldTag::COUNT + 1) + 2, )]; rw.receipt_value() }; @@ -283,7 +283,7 @@ impl ExecutionGadget for EndTxGadget { Value::known(F::from(current_cumulative_gas_used)), )?; self.is_first_tx - .assign(region, offset, F::from(tx.id as u64), F::ONE)?; + .assign(region, offset, F::from(tx.id), F::ONE)?; self.is_persistent.assign( region, offset, diff --git a/zkevm-circuits/src/evm_circuit/execution/error_oog_memory_copy.rs b/zkevm-circuits/src/evm_circuit/execution/error_oog_memory_copy.rs index 8abefb4533..b7f5499540 100644 --- a/zkevm-circuits/src/evm_circuit/execution/error_oog_memory_copy.rs +++ b/zkevm-circuits/src/evm_circuit/execution/error_oog_memory_copy.rs @@ -185,7 +185,7 @@ impl ExecutionGadget for ErrorOOGMemoryCopyGadget { self.is_warm .assign(region, offset, Value::known(F::from(u64::from(is_warm))))?; self.tx_id - .assign(region, offset, Value::known(F::from(transaction.id as u64)))?; + .assign(region, offset, Value::known(F::from(transaction.id)))?; self.external_address .assign_h160(region, offset, external_address.to_address())?; self.src_offset.assign_u256(region, offset, src_offset)?; diff --git a/zkevm-circuits/src/evm_circuit/execution/error_oog_sload_sstore.rs b/zkevm-circuits/src/evm_circuit/execution/error_oog_sload_sstore.rs index d35f24d9b7..94e6312d9f 100644 --- a/zkevm-circuits/src/evm_circuit/execution/error_oog_sload_sstore.rs +++ b/zkevm-circuits/src/evm_circuit/execution/error_oog_sload_sstore.rs @@ -189,7 +189,7 @@ impl ExecutionGadget for ErrorOOGSloadSstoreGadget { self.opcode .assign(region, offset, Value::known(F::from(opcode.as_u64())))?; self.tx_id - .assign(region, offset, Value::known(F::from(tx.id as u64)))?; + .assign(region, offset, Value::known(F::from(tx.id)))?; self.is_static .assign(region, offset, Value::known(F::from(call.is_static as u64)))?; self.callee_address diff --git a/zkevm-circuits/src/evm_circuit/execution/extcodecopy.rs b/zkevm-circuits/src/evm_circuit/execution/extcodecopy.rs index 3187fc7807..25543d8419 100644 --- a/zkevm-circuits/src/evm_circuit/execution/extcodecopy.rs +++ b/zkevm-circuits/src/evm_circuit/execution/extcodecopy.rs @@ -188,7 +188,7 @@ impl ExecutionGadget for ExtcodecopyGadget { .assign(region, offset, memory_offset, memory_length)?; self.tx_id - .assign(region, offset, Value::known(F::from(transaction.id as u64)))?; + .assign(region, offset, Value::known(F::from(transaction.id)))?; self.reversion_info.assign( region, offset, diff --git a/zkevm-circuits/src/evm_circuit/execution/extcodehash.rs b/zkevm-circuits/src/evm_circuit/execution/extcodehash.rs index 73318ba5d2..825a84e492 100644 --- a/zkevm-circuits/src/evm_circuit/execution/extcodehash.rs +++ b/zkevm-circuits/src/evm_circuit/execution/extcodehash.rs @@ -110,7 +110,7 @@ impl ExecutionGadget for ExtcodehashGadget { self.address_word.assign_u256(region, offset, address)?; self.tx_id - .assign(region, offset, Value::known(F::from(tx.id as u64)))?; + .assign(region, offset, Value::known(F::from(tx.id)))?; self.reversion_info.assign( region, offset, diff --git a/zkevm-circuits/src/evm_circuit/execution/extcodesize.rs b/zkevm-circuits/src/evm_circuit/execution/extcodesize.rs index 702b2ce294..7c453c6a61 100644 --- a/zkevm-circuits/src/evm_circuit/execution/extcodesize.rs +++ b/zkevm-circuits/src/evm_circuit/execution/extcodesize.rs @@ -127,7 +127,7 @@ impl ExecutionGadget for ExtcodesizeGadget { self.address_word.assign_u256(region, offset, address)?; self.tx_id - .assign(region, offset, Value::known(F::from(tx.id as u64)))?; + .assign(region, offset, Value::known(F::from(tx.id)))?; self.reversion_info.assign( region, diff --git a/zkevm-circuits/src/evm_circuit/execution/gas.rs b/zkevm-circuits/src/evm_circuit/execution/gas.rs index e5486ad1db..b86441db34 100644 --- a/zkevm-circuits/src/evm_circuit/execution/gas.rs +++ b/zkevm-circuits/src/evm_circuit/execution/gas.rs @@ -144,8 +144,8 @@ mod test { // wrong `gas_left` value for the second step, to assert that // the circuit verification fails for this scenario. assert_eq!(block.txs.len(), 1); - assert_eq!(block.txs[0].steps.len(), 4); - block.txs[0].steps[2].gas_left -= 1; + assert_eq!(block.txs[0].steps().len(), 4); + block.txs[0].steps_mut()[2].gas_left -= 1; })) .evm_checks(Box::new(|prover, gate_rows, lookup_rows| { assert!(prover diff --git a/zkevm-circuits/src/evm_circuit/execution/gasprice.rs b/zkevm-circuits/src/evm_circuit/execution/gasprice.rs index 943372af72..cf01885460 100644 --- a/zkevm-circuits/src/evm_circuit/execution/gasprice.rs +++ b/zkevm-circuits/src/evm_circuit/execution/gasprice.rs @@ -78,7 +78,7 @@ impl ExecutionGadget for GasPriceGadget { let gas_price = block.get_rws(step, 1).stack_value(); self.tx_id - .assign(region, offset, Value::known(F::from(tx.id as u64)))?; + .assign(region, offset, Value::known(F::from(tx.id)))?; self.gas_price.assign_u256(region, offset, gas_price)?; diff --git a/zkevm-circuits/src/evm_circuit/execution/logs.rs b/zkevm-circuits/src/evm_circuit/execution/logs.rs index 14c5485b7d..830a755a08 100644 --- a/zkevm-circuits/src/evm_circuit/execution/logs.rs +++ b/zkevm-circuits/src/evm_circuit/execution/logs.rs @@ -241,7 +241,7 @@ impl ExecutionGadget for LogGadget { self.is_persistent .assign(region, offset, Value::known(F::from(is_persistent)))?; self.tx_id - .assign(region, offset, Value::known(F::from(tx.id as u64)))?; + .assign(region, offset, Value::known(F::from(tx.id)))?; // rw_counter increase from copy table lookup is `msize` memory reads + `msize` // log writes when `is_persistent` is true. self.copy_rwc_inc.assign( diff --git a/zkevm-circuits/src/evm_circuit/execution/origin.rs b/zkevm-circuits/src/evm_circuit/execution/origin.rs index bc0003c81b..720d8d21b0 100644 --- a/zkevm-circuits/src/evm_circuit/execution/origin.rs +++ b/zkevm-circuits/src/evm_circuit/execution/origin.rs @@ -75,7 +75,7 @@ impl ExecutionGadget for OriginGadget { // Assing TxId. self.tx_id - .assign(region, offset, Value::known(F::from(tx.id as u64)))?; + .assign(region, offset, Value::known(F::from(tx.id)))?; // Assign Origin addr. self.origin.assign_u256(region, offset, origin)?; diff --git a/zkevm-circuits/src/evm_circuit/execution/sload.rs b/zkevm-circuits/src/evm_circuit/execution/sload.rs index 750abbf7d8..3bee3fa2c9 100644 --- a/zkevm-circuits/src/evm_circuit/execution/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/sload.rs @@ -104,7 +104,7 @@ impl ExecutionGadget for SloadGadget { self.same_context.assign_exec_step(region, offset, step)?; self.tx_id - .assign(region, offset, Value::known(F::from(tx.id as u64)))?; + .assign(region, offset, Value::known(F::from(tx.id)))?; self.reversion_info.assign( region, offset, diff --git a/zkevm-circuits/src/evm_circuit/execution/sstore.rs b/zkevm-circuits/src/evm_circuit/execution/sstore.rs index 5c1927a4c8..46f030b0a3 100644 --- a/zkevm-circuits/src/evm_circuit/execution/sstore.rs +++ b/zkevm-circuits/src/evm_circuit/execution/sstore.rs @@ -168,7 +168,7 @@ impl ExecutionGadget for SstoreGadget { self.same_context.assign_exec_step(region, offset, step)?; self.tx_id - .assign(region, offset, Value::known(F::from(tx.id as u64)))?; + .assign(region, offset, Value::known(F::from(tx.id)))?; self.is_static .assign(region, offset, Value::known(F::from(call.is_static as u64)))?; self.reversion_info.assign( diff --git a/zkevm-circuits/src/instance.rs b/zkevm-circuits/src/instance.rs index 91836c6a1f..f58222d1a1 100644 --- a/zkevm-circuits/src/instance.rs +++ b/zkevm-circuits/src/instance.rs @@ -1,8 +1,7 @@ //! The instance definition. -use std::iter; - use eth_types::{geth_types::BlockConstants, BigEndianHash, Field, Keccak}; +use std::{iter, ops::Deref}; use eth_types::{geth_types::Transaction, Address, ToBigEndian, Word, H256}; use itertools::Itertools; @@ -78,7 +77,7 @@ pub struct PublicData { /// where the latest one is at history_hashes[history_hashes.len() - 1]. pub history_hashes: Vec, /// Block Transactions - pub transactions: Vec, + pub transactions: Vec, /// Block State Root pub state_root: H256, /// Previous block root @@ -133,14 +132,14 @@ impl PublicData { .try_into() .expect("Error converting chain_id to u64"); let mut tx_vals = vec![]; - for tx in &self.txs() { + for tx in &self.transactions { let sign_data_res = tx.sign_data(chain_id); let msg_hash_le = sign_data_res.map_or_else(|_| [0u8; 32], |sign_data| sign_data.msg_hash.to_bytes()); tx_vals.push(TxValues { nonce: tx.nonce.low_u64(), gas_price: tx.gas_price, - gas_limit: tx.gas_limit.low_u64(), + gas_limit: tx.gas(), from_addr: tx.from, to_addr: tx.to.unwrap_or_else(Address::zero), is_create: (tx.to.is_none() as u64), @@ -168,14 +167,6 @@ impl PublicData { } } - /// Return converted transaction - pub fn txs(&self) -> Vec { - self.transactions - .iter() - .map(Transaction::from) - .collect_vec() - } - /// get the serialized public data bytes pub fn get_pi_bytes(&self, max_txs: usize, max_calldata: usize) -> Vec { // Assign block table @@ -247,8 +238,8 @@ impl PublicData { .chain(all_tx_bytes); // Tx Table CallData - let txs = self.txs(); - let all_calldata = txs + let all_calldata = self + .transactions .iter() .flat_map(|tx| tx.call_data.0.as_ref().iter().copied()) .collect_vec(); @@ -278,7 +269,7 @@ pub fn public_data_convert(block: &Block) -> PublicData { PublicData { chain_id: block.context.chain_id, history_hashes: block.context.history_hashes.clone(), - transactions: block.eth_block.transactions.clone(), + transactions: block.txs.iter().map(|tx| tx.deref().clone()).collect_vec(), state_root: block.eth_block.state_root, prev_state_root: H256::from_uint(&block.prev_state_root), block_hash: block.eth_block.hash, diff --git a/zkevm-circuits/src/pi_circuit.rs b/zkevm-circuits/src/pi_circuit.rs index bd16b856ec..a6f380558b 100644 --- a/zkevm-circuits/src/pi_circuit.rs +++ b/zkevm-circuits/src/pi_circuit.rs @@ -1561,8 +1561,8 @@ impl SubCircuit for PiCircuit { let mut call_data_offset = TX_LEN * self.max_txs + EMPTY_TX_ROW_COUNT; - let txs = self.public_data.txs(); - for (i, tx) in self.public_data.txs().iter().enumerate() { + let txs = self.public_data.transactions.clone(); + for (i, tx) in self.public_data.transactions.iter().enumerate() { let call_data_length = tx.call_data.0.len(); let mut gas_cost = F::ZERO; for (index, byte) in tx.call_data.0.iter().enumerate() { diff --git a/zkevm-circuits/src/table/tx_table.rs b/zkevm-circuits/src/table/tx_table.rs index af8d4aa12c..dfff34204f 100644 --- a/zkevm-circuits/src/table/tx_table.rs +++ b/zkevm-circuits/src/table/tx_table.rs @@ -154,13 +154,61 @@ impl TxTable { let mut calldata_assignments: Vec<[Value; 5]> = Vec::new(); // Assign Tx data (all tx fields except for calldata) let padding_txs: Vec<_> = (txs.len()..max_txs) - .map(|i| Transaction { - id: i + 1, - ..Default::default() - }) + .map(|i| Transaction::padding_tx(i + 1)) .collect(); for tx in txs.iter().chain(padding_txs.iter()) { - let [tx_data, tx_calldata] = tx.table_assignments(); + let tx_id = Value::known(F::from(tx.id)); + let tx_data = vec![ + ( + TxContextFieldTag::Nonce, + word::Word::from(tx.nonce.as_u64()), + ), + (TxContextFieldTag::Gas, word::Word::from(tx.gas())), + (TxContextFieldTag::GasPrice, word::Word::from(tx.gas_price)), + (TxContextFieldTag::CallerAddress, word::Word::from(tx.from)), + ( + TxContextFieldTag::CalleeAddress, + word::Word::from(tx.to_or_contract_addr()), + ), + ( + TxContextFieldTag::IsCreate, + word::Word::from(tx.is_create()), + ), + (TxContextFieldTag::Value, word::Word::from(tx.value)), + ( + TxContextFieldTag::CallDataLength, + word::Word::from(tx.call_data.len() as u64), + ), + ( + TxContextFieldTag::CallDataGasCost, + word::Word::from(tx.call_data_gas_cost()), + ), + ] + .iter() + .map(|&(tag, word)| { + [ + tx_id, + Value::known(F::from(tag as u64)), + Value::known(F::ZERO), + Value::known(word.lo()), + Value::known(word.hi()), + ] + }) + .collect_vec(); + let tx_calldata = tx + .call_data + .iter() + .enumerate() + .map(|(idx, byte)| { + [ + tx_id, + Value::known(F::from(TxContextFieldTag::CallData as u64)), + Value::known(F::from(idx as u64)), + Value::known(F::from(*byte as u64)), + Value::known(F::ZERO), + ] + }) + .collect_vec(); for row in tx_data { assign_row(&mut region, offset, &advice_columns, &self.tag, &row, "")?; offset += 1; diff --git a/zkevm-circuits/src/tx_circuit.rs b/zkevm-circuits/src/tx_circuit.rs index e4a295dbc6..05fe175cad 100644 --- a/zkevm-circuits/src/tx_circuit.rs +++ b/zkevm-circuits/src/tx_circuit.rs @@ -26,7 +26,7 @@ use halo2_proofs::{ use itertools::Itertools; use log::error; use sign_verify::{AssignedSignatureVerify, SignVerifyChip, SignVerifyConfig}; -use std::marker::PhantomData; +use std::{marker::PhantomData, ops::Deref}; /// Number of static fields per tx: [nonce, gas, gas_price, /// caller_address, callee_address, is_create, value, call_data_length, @@ -206,10 +206,7 @@ impl TxCircuit { TxFieldTag::Nonce, Word::from(tx.nonce.as_u64()).into_value(), ), - ( - TxFieldTag::Gas, - Word::from(tx.gas_limit.as_u64()).into_value(), - ), + (TxFieldTag::Gas, Word::from(tx.gas()).into_value()), (TxFieldTag::GasPrice, Word::from(tx.gas_price).into_value()), (TxFieldTag::CallerAddress, Word::from(tx.from).into_value()), ( @@ -314,12 +311,7 @@ impl SubCircuit for TxCircuit { block.circuits_params.max_txs, block.circuits_params.max_calldata, block.context.chain_id.as_u64(), - block - .eth_block - .transactions - .iter() - .map(|tx| tx.into()) - .collect(), + block.txs.iter().map(|tx| tx.deref().clone()).collect_vec(), ) } diff --git a/zkevm-circuits/src/witness.rs b/zkevm-circuits/src/witness.rs index dde790dd39..8a1211e3fc 100644 --- a/zkevm-circuits/src/witness.rs +++ b/zkevm-circuits/src/witness.rs @@ -9,8 +9,5 @@ pub use bytecode::Bytecode; mod mpt; pub use mpt::{MptUpdate, MptUpdateRow, MptUpdates}; mod rw; -pub use bus_mapping::circuit_input_builder::ExecStep; +pub use bus_mapping::circuit_input_builder::{Call, ExecStep, Transaction}; pub use rw::{Rw, RwMap, RwRow}; -mod tx; -pub use bus_mapping::circuit_input_builder::Call; -pub use tx::Transaction; diff --git a/zkevm-circuits/src/witness/block.rs b/zkevm-circuits/src/witness/block.rs index 48e62778b5..854516eba0 100644 --- a/zkevm-circuits/src/witness/block.rs +++ b/zkevm-circuits/src/witness/block.rs @@ -14,7 +14,7 @@ use bus_mapping::{ use eth_types::{Address, Field, ToScalar, Word}; use halo2_proofs::circuit::Value; -use super::{tx::tx_convert, Bytecode, ExecStep, Rw, RwMap, Transaction}; +use super::{Bytecode, ExecStep, Rw, RwMap, Transaction}; // TODO: Remove fields that are duplicated in`eth_block` /// Block is the struct used by all circuits, which contains all the needed @@ -60,7 +60,7 @@ impl Block { pub(crate) fn debug_print_txs_steps_rw_ops(&self) { for (tx_idx, tx) in self.txs.iter().enumerate() { println!("tx {}", tx_idx); - for step in &tx.steps { + for step in tx.steps() { println!(" step {:?} rwc: {}", step.exec_state, step.rwc.0); for rw_idx in 0..step.bus_mapping_instance.len() { println!(" - {:?}", self.get_rws(step, rw_idx)); @@ -248,12 +248,7 @@ pub fn block_convert( randomness: F::from(0xcafeu64), context: block.into(), rws, - txs: block - .txs() - .iter() - .enumerate() - .map(|(idx, tx)| tx_convert(tx, idx + 1)) - .collect(), + txs: block.txs().to_vec(), end_block_not_last: block.block_steps.end_block_not_last.clone(), end_block_last: block.block_steps.end_block_last.clone(), bytecodes: code_db diff --git a/zkevm-circuits/src/witness/tx.rs b/zkevm-circuits/src/witness/tx.rs deleted file mode 100644 index 0068e312bf..0000000000 --- a/zkevm-circuits/src/witness/tx.rs +++ /dev/null @@ -1,144 +0,0 @@ -use crate::util::word; -use bus_mapping::circuit_input_builder; -use eth_types::{Address, Field, Word}; -use halo2_proofs::circuit::Value; - -use crate::table::TxContextFieldTag; - -use super::{Call, ExecStep}; - -/// Transaction in a witness block -#[derive(Debug, Default, Clone)] -pub struct Transaction { - /// The transaction identifier in the block - pub id: usize, - /// The sender account nonce of the transaction - pub nonce: u64, - /// The gas limit of the transaction - pub gas: u64, - /// The gas price - pub gas_price: Word, - /// The caller address - pub caller_address: Address, - /// The callee address - pub callee_address: Address, - /// Whether it's a create transaction - pub is_create: bool, - /// The ether amount of the transaction - pub value: Word, - /// The call data - pub call_data: Vec, - /// The call data length - pub call_data_length: usize, - /// The gas cost for transaction call data - pub call_data_gas_cost: u64, - /// The calls made in the transaction - pub calls: Vec, - /// The steps executioned in the transaction - pub steps: Vec, -} - -impl Transaction { - /// Assignments for tx table, split into tx_data (all fields except - /// calldata) and tx_calldata - pub fn table_assignments(&self) -> [Vec<[Value; 5]>; 2] { - let tx_data = vec![ - [ - Value::known(F::from(self.id as u64)), - Value::known(F::from(TxContextFieldTag::Nonce as u64)), - Value::known(F::ZERO), - Value::known(F::from(self.nonce)), - Value::known(F::ZERO), - ], - [ - Value::known(F::from(self.id as u64)), - Value::known(F::from(TxContextFieldTag::Gas as u64)), - Value::known(F::ZERO), - Value::known(F::from(self.gas)), - Value::known(F::ZERO), - ], - [ - Value::known(F::from(self.id as u64)), - Value::known(F::from(TxContextFieldTag::GasPrice as u64)), - Value::known(F::ZERO), - Value::known(word::Word::from(self.gas_price).lo()), - Value::known(word::Word::from(self.gas_price).hi()), - ], - [ - Value::known(F::from(self.id as u64)), - Value::known(F::from(TxContextFieldTag::CallerAddress as u64)), - Value::known(F::ZERO), - Value::known(word::Word::from(self.caller_address).lo()), - Value::known(word::Word::from(self.caller_address).hi()), - ], - [ - Value::known(F::from(self.id as u64)), - Value::known(F::from(TxContextFieldTag::CalleeAddress as u64)), - Value::known(F::ZERO), - Value::known(word::Word::from(self.callee_address).lo()), - Value::known(word::Word::from(self.callee_address).hi()), - ], - [ - Value::known(F::from(self.id as u64)), - Value::known(F::from(TxContextFieldTag::IsCreate as u64)), - Value::known(F::ZERO), - Value::known(F::from(self.is_create as u64)), - Value::known(F::ZERO), - ], - [ - Value::known(F::from(self.id as u64)), - Value::known(F::from(TxContextFieldTag::Value as u64)), - Value::known(F::ZERO), - Value::known(word::Word::from(self.value).lo()), - Value::known(word::Word::from(self.value).hi()), - ], - [ - Value::known(F::from(self.id as u64)), - Value::known(F::from(TxContextFieldTag::CallDataLength as u64)), - Value::known(F::ZERO), - Value::known(F::from(self.call_data_length as u64)), - Value::known(F::ZERO), - ], - [ - Value::known(F::from(self.id as u64)), - Value::known(F::from(TxContextFieldTag::CallDataGasCost as u64)), - Value::known(F::ZERO), - Value::known(F::from(self.call_data_gas_cost)), - Value::known(F::ZERO), - ], - ]; - let tx_calldata = self - .call_data - .iter() - .enumerate() - .map(|(idx, byte)| { - [ - Value::known(F::from(self.id as u64)), - Value::known(F::from(TxContextFieldTag::CallData as u64)), - Value::known(F::from(idx as u64)), - Value::known(F::from(*byte as u64)), - Value::known(F::ZERO), - ] - }) - .collect(); - [tx_data, tx_calldata] - } -} - -pub(super) fn tx_convert(tx: &circuit_input_builder::Transaction, id: usize) -> Transaction { - Transaction { - id, - nonce: tx.tx.nonce.as_u64(), - gas: tx.gas(), - gas_price: tx.tx.gas_price, - caller_address: tx.tx.from, - callee_address: tx.tx.to_or_contract_addr(), - is_create: tx.is_create(), - value: tx.tx.value, - call_data: tx.tx.call_data.to_vec(), - call_data_length: tx.tx.call_data.len(), - call_data_gas_cost: tx.tx.call_data_gas_cost(), - calls: tx.calls().to_vec(), - steps: tx.steps().to_vec(), - } -}