# copy circuit memory to memory ### current copy circuit behavior current copy event consists of field `bytes` CopyEvent { rw_counter_start, src_type: CopyDataType::Memory, src_id: NumberOrHash::Number(source.id), src_addr: source.offset.try_into().unwrap(), src_addr_end: (source.offset + source.length).try_into().unwrap(), dst_type: CopyDataType::Memory, dst_id: NumberOrHash::Number(destination.id), dst_addr: destination.offset.try_into().unwrap(), log_id: None, bytes: copy_steps, }, this field generate two steps for each byte: read step, write step。 copy circuit do the following two key constraints base on this two adjacement steps(rows). 1. constrain read_step_value = write_step_value 2. lookup read/write records in rw table, ensure read/write oepration occurs. for read step, look up input is tuple of (src_addr, src_id, src_tag, value). for write step, it is tuple of (dst_addr, dst_id, dst_tag, value). ### memory to memory adaption for copy memory --> memory cases, after padding read and write bytes to multiple of 32, there are two different bytes sequence in the copy event. 1. first add new `aux_bytes` in the copy event (buss mapping) ` CopyEvent { rw_counter_start, src_type: CopyDataType::Memory, src_id: NumberOrHash::Number(source.id), src_addr: source.offset.try_into().unwrap(), src_addr_end: (source.offset + source.length).try_into().unwrap(), dst_type: CopyDataType::Memory, dst_id: NumberOrHash::Number(destination.id), dst_addr: destination.offset.try_into().unwrap(), log_id: None, bytes: read_steps, **aux_bytes: Option(write_steps)** }, 2. copy circuit changes modify copy circuit to generate write steps with aux_bytes. read steps remains the same. but this will break copy circuit first key constrain: `read_step_value = write_step_value` for this problem, walk around is do rlc for only real copy bytes against both read and write steps, compare rlc_read_bytes == rlc_write_bytes. padding bytes won't be involved. ![](https://hackmd.io/_uploads/BJkIyi7r2.png) the table looks like as following: | q_step | tag | mask | Value | word_index | memory_word_rlc | slot_addr| rlc_acc_read |rlc_acc_write| |---|--|--|---|---| ---| --| -- | -- | | 1 |Memory| 1 | src_slot_byte0| 0 |rlc0 | 0 | 0 | 0 | | 0 |Memory| 0 | dst_slot_byte0| 0 |rlc1 | 0 | 0 | 0 | 1 |Memory| 0 | src_slot_byte1| 0 |rlc2 | 0 | src_slot_byte1 | 0 | 0 |Memory| 0 | dst_slot_byte1| 0 |rlc2 | 0 | 0 | dst_slot_byte1 | 1 |Memory| 0 | src_slot_byte2| 0 |rlc3 | 0 | src_slot_byte1*r + src_slot_byte2 | 0 | 0 |Memory| 0 | dst_slot_byte2| 0 |rlc3 | 0 | 0 | dst_slot_byte1 * r + dst_slot_byte2 | 0 |Memory| ..| ...| .. | .. | .. | .. | | 1 |Memory| 0 | src_slot_byte31 |31|rlc0_31| 0 | src_slot_byte30*r + src_slot_byte31| 0 | | 1 |Memory| 0 | src_slot_byte31 |31|rlc0_31| 0 | 0| dst_slot_byte30 * r + dst_slot_byte31 | | .. |..| ..| ...| .. | .. at the end of copy event, assert rlc_acc_read == rlc_acc_write. memory_word_rlc is lookup RW input. mask: indicates whether it is a real copy byte or pad byte.