diff --git a/bus-mapping/src/evm/opcodes/return.rs b/bus-mapping/src/evm/opcodes/return.rs index dff801b6cbf..4062ed53936 100644 --- a/bus-mapping/src/evm/opcodes/return.rs +++ b/bus-mapping/src/evm/opcodes/return.rs @@ -55,7 +55,7 @@ impl Opcode for Return { state.call_context_write( &mut exec_step, - state.call()?.call_id, + state.caller()?.call_id, CallContextField::LastCalleeId, state.call()?.call_id.into(), ); diff --git a/bus-mapping/src/evm/opcodes/returndatacopy.rs b/bus-mapping/src/evm/opcodes/returndatacopy.rs index 5ce4824671b..2a7429525d4 100644 --- a/bus-mapping/src/evm/opcodes/returndatacopy.rs +++ b/bus-mapping/src/evm/opcodes/returndatacopy.rs @@ -34,6 +34,7 @@ impl Opcode for Returndatacopy { let call_id = state.call()?.call_id; let call_ctx = state.call_ctx()?; let return_data = call_ctx.return_data.clone(); + let last_callee_id = state.call()?.last_callee_id; let last_callee_return_data_offset = state.call()?.last_callee_return_data_offset; let last_callee_return_data_length = state.call()?.last_callee_return_data_length; assert_eq!( @@ -44,6 +45,7 @@ impl Opcode for Returndatacopy { // read last callee info for (field, value) in [ + (CallContextField::LastCalleeId, last_callee_id.into()), ( CallContextField::LastCalleeReturnDataOffset, last_callee_return_data_offset.into(), @@ -165,15 +167,20 @@ fn gen_copy_event( state.call()?.is_root, )?; - let (src_type, src_id) = (CopyDataType::Memory, state.call()?.call_id); + let (src_type, dst_type, src_id, dst_id) = ( + CopyDataType::Memory, + CopyDataType::Memory, + state.call()?.last_callee_id, + state.call()?.call_id, + ); Ok(CopyEvent { src_type, src_id: NumberOrHash::Number(src_id), src_addr, src_addr_end, - dst_type: CopyDataType::Memory, - dst_id: NumberOrHash::Number(src_id), + dst_type, + dst_id: NumberOrHash::Number(dst_id), dst_addr: dst_memory_offset, log_id: None, length, diff --git a/zkevm-circuits/src/evm_circuit/execution/returndatacopy.rs b/zkevm-circuits/src/evm_circuit/execution/returndatacopy.rs index 0fe4ff0e04f..2ef71c78edc 100644 --- a/zkevm-circuits/src/evm_circuit/execution/returndatacopy.rs +++ b/zkevm-circuits/src/evm_circuit/execution/returndatacopy.rs @@ -27,6 +27,8 @@ use halo2_proofs::{circuit::Value, plonk::Error}; #[derive(Clone, Debug)] pub(crate) struct ReturnDataCopyGadget { same_context: SameContextGadget, + /// Holds the last_called_id for copy table. + last_callee_id: Cell, /// Holds the memory address for return data from where we read. return_data_offset: Cell, /// Holds the size of the return data. @@ -68,8 +70,15 @@ impl ExecutionGadget for ReturnDataCopyGadget { cb.stack_pop(size.expr()); // 2. Add lookup constraint in the call context for the returndatacopy field. + let last_callee_id = cb.query_cell(); let return_data_offset = cb.query_cell(); let return_data_size = cb.query_cell(); + cb.call_context_lookup( + false.expr(), + None, + CallContextFieldTag::LastCalleeId, + last_callee_id.expr(), + ); cb.call_context_lookup( false.expr(), None, @@ -112,7 +121,7 @@ impl ExecutionGadget for ReturnDataCopyGadget { let copy_rwc_inc = cb.query_cell(); cb.condition(dst_memory_addr.has_length(), |cb| { cb.copy_table_lookup( - cb.curr.state.call_id.expr(), + last_callee_id.expr(), CopyDataType::Memory.expr(), cb.curr.state.call_id.expr(), CopyDataType::Memory.expr(), @@ -147,6 +156,7 @@ impl ExecutionGadget for ReturnDataCopyGadget { Self { same_context, + last_callee_id, return_data_offset, return_data_size, dst_memory_addr, @@ -182,8 +192,25 @@ impl ExecutionGadget for ReturnDataCopyGadget { ), )?; - let [return_data_offset, return_data_size] = - [3, 4].map(|i| block.rws[step.rw_indices[i as usize]].call_context_value()); + let [last_callee_id, return_data_offset, return_data_size] = [ + (3, CallContextFieldTag::LastCalleeId), + (4, CallContextFieldTag::LastCalleeReturnDataOffset), + (5, CallContextFieldTag::LastCalleeReturnDataLength), + ] + .map(|(i, tag)| { + let rw = block.rws[step.rw_indices[i as usize]]; + assert_eq!(rw.field_tag(), Some(tag as u64)); + rw.call_context_value() + }); + self.last_callee_id.assign( + region, + offset, + Value::known( + last_callee_id + .to_scalar() + .expect("unexpected U256 -> Scalar conversion failure"), + ), + )?; self.return_data_offset.assign( region, offset,