diff --git a/bus-mapping/src/circuit_input_builder.rs b/bus-mapping/src/circuit_input_builder.rs index bcaf8cba6a..f769062766 100644 --- a/bus-mapping/src/circuit_input_builder.rs +++ b/bus-mapping/src/circuit_input_builder.rs @@ -138,15 +138,9 @@ impl<'a> CircuitInputBuilder { geth_traces: &[eth_types::GethExecTrace], ) -> Result<(), Error> { // accumulates gas across all txs in the block - let mut cumulative_gas_used = HashMap::new(); 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(), - &mut cumulative_gas_used, - )?; + self.handle_tx(tx, geth_trace, tx_index + 1 == eth_block.transactions.len())?; } self.set_value_ops_call_context_rwc_eor(); Ok(()) @@ -162,7 +156,6 @@ impl<'a> CircuitInputBuilder { eth_tx: ð_types::Transaction, geth_trace: &GethExecTrace, is_last_tx: bool, - cumulative_gas_used: &mut HashMap, ) -> Result<(), Error> { let mut tx = self.new_tx(eth_tx, !geth_trace.failed)?; let mut tx_ctx = TransactionContext::new(eth_tx, geth_trace, is_last_tx)?; @@ -189,10 +182,7 @@ impl<'a> CircuitInputBuilder { // - execution_state: EndTx // - op: None // Generate EndTx step - let end_tx_step = gen_end_tx_ops( - &mut self.state_ref(&mut tx, &mut tx_ctx), - cumulative_gas_used, - )?; + let end_tx_step = gen_end_tx_ops(&mut self.state_ref(&mut tx, &mut tx_ctx))?; tx.steps_mut().push(end_tx_step); self.sdb.commit_tx(); diff --git a/bus-mapping/src/circuit_input_builder/block.rs b/bus-mapping/src/circuit_input_builder/block.rs index 13f7e606b7..52db3d64e3 100644 --- a/bus-mapping/src/circuit_input_builder/block.rs +++ b/bus-mapping/src/circuit_input_builder/block.rs @@ -18,6 +18,8 @@ pub struct BlockContext { /// in Block.txs and call_index is the index used in Transaction. /// calls). pub(crate) call_map: HashMap, + /// Total gas used by previous transactions in this block. + pub(crate) cumulative_gas_used: u64, } impl Default for BlockContext { @@ -32,6 +34,7 @@ impl BlockContext { Self { rwc: RWCounter::new(), call_map: HashMap::new(), + cumulative_gas_used: 0, } } } diff --git a/bus-mapping/src/circuit_input_builder/input_state_ref.rs b/bus-mapping/src/circuit_input_builder/input_state_ref.rs index 4378059cf7..d1e440f629 100644 --- a/bus-mapping/src/circuit_input_builder/input_state_ref.rs +++ b/bus-mapping/src/circuit_input_builder/input_state_ref.rs @@ -345,6 +345,31 @@ impl<'a> CircuitInputStateRef<'a> { Ok(()) } + /// Push a write type [`TxReceiptOp`] into the + /// [`OperationContainer`](crate::operation::OperationContainer) with the + /// next [`RWCounter`](crate::operation::RWCounter), and then + /// adds a reference to the stored operation ([`OperationRef`]) inside + /// the bus-mapping instance of the current [`ExecStep`]. Then increase + /// the `block_ctx` [`RWCounter`](crate::operation::RWCounter) by one. + pub fn tx_receipt_write( + &mut self, + step: &mut ExecStep, + tx_id: usize, + field: TxReceiptField, + value: u64, + ) -> Result<(), Error> { + self.push_op( + step, + RW::WRITE, + TxReceiptOp { + tx_id, + field, + value, + }, + ); + Ok(()) + } + /// Push a write type [`TxAccessListAccountOp`] into the /// [`OperationContainer`](crate::operation::OperationContainer) with the /// next [`RWCounter`](crate::operation::RWCounter), and then diff --git a/bus-mapping/src/evm/opcodes.rs b/bus-mapping/src/evm/opcodes.rs index 1c4b4caf96..5bca084711 100644 --- a/bus-mapping/src/evm/opcodes.rs +++ b/bus-mapping/src/evm/opcodes.rs @@ -15,7 +15,6 @@ use eth_types::{ }; use keccak256::EMPTY_HASH; use log::warn; -use std::collections::HashMap; mod call; mod calldatacopy; @@ -372,10 +371,7 @@ pub fn gen_begin_tx_ops(state: &mut CircuitInputStateRef) -> Result, -) -> Result { +pub fn gen_end_tx_ops(state: &mut CircuitInputStateRef) -> Result { let mut exec_step = state.new_end_tx_step(); let call = state.tx.calls()[0].clone(); @@ -438,7 +434,7 @@ pub fn gen_end_tx_ops( )?; // handle tx receipt tag - state.tx_receipt_read( + state.tx_receipt_write( &mut exec_step, state.tx_ctx.id(), TxReceiptField::PostStateOrStatus, @@ -446,35 +442,31 @@ pub fn gen_end_tx_ops( )?; let log_id = exec_step.log_id; - state.tx_receipt_read( + state.tx_receipt_write( &mut exec_step, state.tx_ctx.id(), TxReceiptField::LogLength, log_id as u64, )?; - let gas_used = state.tx.gas - exec_step.gas_left.0; - let mut current_cumulative_gas_used: u64 = 0; if state.tx_ctx.id() > 1 { - current_cumulative_gas_used = *cumulative_gas_used.get(&(state.tx_ctx.id() - 1)).unwrap(); // query pre tx cumulative gas state.tx_receipt_read( &mut exec_step, state.tx_ctx.id() - 1, TxReceiptField::CumulativeGasUsed, - current_cumulative_gas_used, + state.block_ctx.cumulative_gas_used, )?; } - state.tx_receipt_read( + state.block_ctx.cumulative_gas_used += state.tx.gas - exec_step.gas_left.0; + state.tx_receipt_write( &mut exec_step, state.tx_ctx.id(), TxReceiptField::CumulativeGasUsed, - current_cumulative_gas_used + gas_used, + state.block_ctx.cumulative_gas_used, )?; - cumulative_gas_used.insert(state.tx_ctx.id(), current_cumulative_gas_used + gas_used); - if !state.tx_ctx.is_last_tx() { state.call_context_read( &mut exec_step, diff --git a/zkevm-circuits/src/evm_circuit/execution/end_tx.rs b/zkevm-circuits/src/evm_circuit/execution/end_tx.rs index 3a37717e7c..7dab0555db 100644 --- a/zkevm-circuits/src/evm_circuit/execution/end_tx.rs +++ b/zkevm-circuits/src/evm_circuit/execution/end_tx.rs @@ -104,11 +104,13 @@ impl ExecutionGadget for EndTxGadget { // constrain tx receipt fields cb.tx_receipt_lookup( + 1.expr(), tx_id.expr(), TxReceiptFieldTag::PostStateOrStatus, is_persistent.expr(), ); cb.tx_receipt_lookup( + 1.expr(), tx_id.expr(), TxReceiptFieldTag::LogLength, cb.curr.state.log_id.expr(), @@ -126,6 +128,7 @@ impl ExecutionGadget for EndTxGadget { cb.condition(1.expr() - is_first_tx.expr(), |cb| { cb.tx_receipt_lookup( + 0.expr(), tx_id.expr() - 1.expr(), TxReceiptFieldTag::CumulativeGasUsed, current_cumulative_gas_used.expr(), @@ -133,6 +136,7 @@ impl ExecutionGadget for EndTxGadget { }); cb.tx_receipt_lookup( + 1.expr(), tx_id.expr(), TxReceiptFieldTag::CumulativeGasUsed, gas_used + current_cumulative_gas_used.expr(), diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index 84d49f1a40..472ad5a1f2 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -1041,25 +1041,16 @@ impl<'a, F: FieldExt> ConstraintBuilder<'a, F> { // Tx Receipt - pub(crate) fn tx_receipt( - &mut self, - tx_id: Expression, - field_tag: TxReceiptFieldTag, - ) -> Cell { - let cell = self.query_cell(); - self.tx_receipt_lookup(tx_id, field_tag, cell.expr()); - cell - } - pub(crate) fn tx_receipt_lookup( &mut self, + is_write: Expression, tx_id: Expression, tag: TxReceiptFieldTag, value: Expression, ) { self.rw_lookup( "tx receipt lookup", - 0.expr(), + is_write, RwTableTag::TxReceipt, [ tx_id, diff --git a/zkevm-circuits/src/state_circuit.rs b/zkevm-circuits/src/state_circuit.rs index 9cf51b923f..70be026150 100644 --- a/zkevm-circuits/src/state_circuit.rs +++ b/zkevm-circuits/src/state_circuit.rs @@ -243,12 +243,9 @@ impl Circuit for StateCircuit { // TODO: Get initial_values from MPT updates instead. if is_first_access { - // TODO: Set initial values for Rw::CallContext and Rw::TxReceipt to be - // 0 instead of special casing them. - initial_value = if matches!( - row.tag(), - RwTableTag::CallContext | RwTableTag::TxReceipt - ) { + // TODO: Set initial values for Rw::CallContext to be 0 instead of + // special casing it. + initial_value = if matches!(row.tag(), RwTableTag::CallContext) { row.value_assignment(self.randomness) } else { row.value_prev_assignment(self.randomness)