diff --git a/bus-mapping/src/circuit_input_builder/execution.rs b/bus-mapping/src/circuit_input_builder/execution.rs index f463396301..90c91dabde 100644 --- a/bus-mapping/src/circuit_input_builder/execution.rs +++ b/bus-mapping/src/circuit_input_builder/execution.rs @@ -144,7 +144,8 @@ pub enum CopyDetails { Code(U256), /// The bytes are being copied to a Log. /// Call's state change's persistance and tx_id are provided. - Log((bool, usize)), + /// the data start index when enter this copy step + Log((bool, usize, usize)), } /// Auxiliary data of Execution step diff --git a/zkevm-circuits/src/evm_circuit/execution/copy_to_log.rs b/zkevm-circuits/src/evm_circuit/execution/copy_to_log.rs index b7a244262c..46708fae4b 100644 --- a/zkevm-circuits/src/evm_circuit/execution/copy_to_log.rs +++ b/zkevm-circuits/src/evm_circuit/execution/copy_to_log.rs @@ -31,6 +31,8 @@ pub(crate) struct CopyToLogGadget { is_persistent: Cell, // The tx id tx_id: Cell, + // the log data start index fetched from last step + data_start_index: Cell, // Buffer reader gadget buffer_reader: BufferReaderGadget, // The comparison gadget between num bytes copied and bytes_left @@ -48,6 +50,7 @@ impl ExecutionGadget for CopyToLogGadget { let src_addr_end = cb.query_cell(); let is_persistent = cb.query_bool(); let tx_id = cb.query_cell(); + let data_start_index = cb.query_cell(); let buffer_reader = BufferReaderGadget::construct(cb, src_addr.expr(), src_addr_end.expr()); // Copy bytes from src and dst @@ -68,7 +71,7 @@ impl ExecutionGadget for CopyToLogGadget { cb.tx_log_lookup( tx_id.expr(), TxLogFieldTag::Data, - i.expr(), + data_start_index.expr() + i.expr(), buffer_reader.byte(i), ) }); @@ -88,6 +91,10 @@ impl ExecutionGadget for CopyToLogGadget { let next_src_addr = cb.query_cell(); let next_bytes_left = cb.query_cell(); let next_src_addr_end = cb.query_cell(); + let next_is_persistent = cb.query_bool(); + let next_tx_id = cb.query_cell(); + let next_data_start_index = cb.query_cell(); + cb.require_equal( "next_src_addr == src_addr + copied_size", next_src_addr.expr(), @@ -104,6 +111,18 @@ impl ExecutionGadget for CopyToLogGadget { next_src_addr_end.expr(), src_addr_end.expr(), ); + cb.require_equal( + "next_is_persistent == is_persistent", + next_is_persistent.expr(), + is_persistent.expr(), + ); + cb.require_equal("next_tx_id == tx_id", next_tx_id.expr(), tx_id.expr()); + cb.require_equal( + "next_data_start_index == data_start_index + MAX_COPY_BYTES + ", + next_data_start_index.expr(), + data_start_index.expr() + MAX_COPY_BYTES.expr(), + ); }); // State transition @@ -119,6 +138,7 @@ impl ExecutionGadget for CopyToLogGadget { src_addr_end, is_persistent, tx_id, + data_start_index, buffer_reader, finish_gadget, } @@ -141,8 +161,12 @@ impl ExecutionGadget for CopyToLogGadget { step.aux_data.unwrap() }; - let (is_persistent, tx_id) = match aux.copy_details() { - CopyDetails::Log((is_persistent, tx_id)) => (is_persistent, tx_id), + // log won't use dst_addr + assert!(aux.dst_addr() == 0u64); + let (is_persistent, tx_id, data_start_index) = match aux.copy_details() { + CopyDetails::Log((is_persistent, tx_id, data_index)) => { + (is_persistent, tx_id, data_index) + } _ => unreachable!("the data copy is not related to a LOG op"), }; @@ -156,7 +180,8 @@ impl ExecutionGadget for CopyToLogGadget { .assign(region, offset, Some(F::from(is_persistent as u64)))?; self.tx_id .assign(region, offset, Some(F::from(tx_id as u64)))?; - + self.data_start_index + .assign(region, offset, Some(F::from(data_start_index as u64)))?; // Retrieve the bytes and selectors let mut rw_idx = 0; @@ -220,6 +245,7 @@ pub mod test { src_addr: u64, src_addr_end: u64, bytes_left: usize, + data_start_index: usize, program_counter: u64, stack_pointer: usize, memory_size: u64, @@ -261,7 +287,7 @@ pub mod test { tx_id, log_id, field_tag: TxLogFieldTag::Data, - index: idx.try_into().unwrap(), + index: data_start_index + idx, value: Word::from(byte), }); rw_offset += 1; @@ -277,7 +303,7 @@ pub mod test { Default::default(), bytes_left as u64, src_addr_end, - CopyDetails::Log((is_persistent, tx_id)), + CopyDetails::Log((is_persistent, tx_id, data_start_index)), ); let memory_indices: Vec<(RwTableTag, usize)> = (memory_idx_start @@ -336,6 +362,7 @@ pub mod test { src_addr + copied as u64, buffer_addr_end, length - copied, + copied, program_counter, stack_pointer, memory_size, diff --git a/zkevm-circuits/src/evm_circuit/execution/logs.rs b/zkevm-circuits/src/evm_circuit/execution/logs.rs index fb0507b185..744f39f8f2 100644 --- a/zkevm-circuits/src/evm_circuit/execution/logs.rs +++ b/zkevm-circuits/src/evm_circuit/execution/logs.rs @@ -130,6 +130,7 @@ impl ExecutionGadget for LogGadget { let next_src_addr_end = cb.query_cell(); let next_is_persistent = cb.query_bool(); let next_tx_id = cb.query_cell(); + let next_data_start_index = cb.query_cell(); cb.require_equal( "next_src_addr = memory_offset", @@ -152,6 +153,10 @@ impl ExecutionGadget for LogGadget { is_persistent.expr(), ); cb.require_equal("next_tx_id = tx_id", next_tx_id.expr(), tx_id.expr()); + cb.require_zero( + "next_data_start_index starts with 0", + next_data_start_index.expr(), + ); }, ); @@ -383,7 +388,7 @@ mod test { tx_id, log_id: log_id.try_into().unwrap(), field_tag: TxLogFieldTag::Topic, - index: idx.try_into().unwrap(), + index: idx, value: *topic, }); } diff --git a/zkevm-circuits/src/evm_circuit/witness.rs b/zkevm-circuits/src/evm_circuit/witness.rs index 9fa4d95563..a5a089b3bf 100644 --- a/zkevm-circuits/src/evm_circuit/witness.rs +++ b/zkevm-circuits/src/evm_circuit/witness.rs @@ -509,9 +509,9 @@ pub enum Rw { log_id: u64, // pack this can index together into address? field_tag: TxLogFieldTag, // topic index (0..4) if field_tag is TxLogFieldTag:Topic - // byte index (0..32) if field_tag is TxLogFieldTag:Data + // byte index if field_tag is TxLogFieldTag:Data // 0 for other field tags - index: u8, + index: usize, // when it is topic field, value can be word type value: Word,