Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.

Commit 4c4d117

Browse files
authored
Auditing: ErrorMemorycopy constrain src_len & memory expansion (#1321)
* constrain src_len = dst_len * add src_endset when calculate mcopy expansion gadget * add field * assign memory_expansion_mcopy * fix fmt * assign is_mcopy * fix addr assign order * fix clippy * minor comment * Auditing improvement: test new_for_mcopy (#1326) * improve test new_for_mcopy * adjust next_memory_word_size * remove comment * update cur_memory_word_size zero
1 parent 27113df commit 4c4d117

File tree

1 file changed

+73
-21
lines changed

1 file changed

+73
-21
lines changed

zkevm-circuits/src/evm_circuit/execution/error_oog_memory_copy.rs

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
CommonMemoryAddressGadget, MemoryCopierGasGadget, MemoryExpandedAddressGadget,
1313
MemoryExpansionGadget,
1414
},
15-
or, select, CachedRegion, Cell, Word,
15+
not, or, select, CachedRegion, Cell, Word,
1616
},
1717
witness::{Block, Call, ExecStep, Transaction},
1818
},
@@ -40,10 +40,14 @@ pub(crate) struct ErrorOOGMemoryCopyGadget<F> {
4040
src_memory_addr: MemoryExpandedAddressGadget<F>,
4141
/// Destination offset and size to copy
4242
dst_memory_addr: MemoryExpandedAddressGadget<F>,
43-
memory_expansion: MemoryExpansionGadget<F, 1, N_BYTES_MEMORY_WORD_SIZE>,
43+
// mcopy expansion
44+
memory_expansion_mcopy: MemoryExpansionGadget<F, 2, N_BYTES_MEMORY_WORD_SIZE>,
45+
// other kind(CALLDATACOPY, CODECOPY, EXTCODECOPY, RETURNDATACOPY) expansion
46+
memory_expansion_normal: MemoryExpansionGadget<F, 1, N_BYTES_MEMORY_WORD_SIZE>,
4447
memory_copier_gas: MemoryCopierGasGadget<F, { GasCost::COPY }>,
4548
insufficient_gas: LtGadget<F, N_BYTES_GAS>,
4649
is_extcodecopy: IsZeroGadget<F>,
50+
is_mcopy: IsZeroGadget<F>,
4751
common_error_gadget: CommonErrorGadget<F>,
4852
}
4953

@@ -72,6 +76,7 @@ impl<F: Field> ExecutionGadget<F> for ErrorOOGMemoryCopyGadget<F> {
7276

7377
let is_extcodecopy =
7478
IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::EXTCODECOPY.expr());
79+
let is_mcopy = IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::MCOPY.expr());
7580

7681
cb.condition(is_extcodecopy.expr(), |cb| {
7782
cb.call_context_lookup(false.expr(), None, CallContextFieldTag::TxId, tx_id.expr());
@@ -95,12 +100,31 @@ impl<F: Field> ExecutionGadget<F> for ErrorOOGMemoryCopyGadget<F> {
95100
cb.stack_pop(src_memory_addr.offset_rlc());
96101
cb.stack_pop(dst_memory_addr.length_rlc());
97102

98-
let memory_expansion = MemoryExpansionGadget::construct(cb, [dst_memory_addr.end_offset()]);
99-
let memory_copier_gas = MemoryCopierGasGadget::construct(
100-
cb,
101-
dst_memory_addr.length(),
102-
memory_expansion.gas_cost(),
103+
// for mcopy
104+
let memory_expansion_mcopy = cb.condition(is_mcopy.expr(), |cb| {
105+
cb.require_equal(
106+
"mcopy src_address length == dst_address length",
107+
src_memory_addr.length_rlc(),
108+
dst_memory_addr.length_rlc(),
109+
);
110+
MemoryExpansionGadget::construct(
111+
cb,
112+
[src_memory_addr.end_offset(), dst_memory_addr.end_offset()],
113+
)
114+
});
115+
116+
// for others (CALLDATACOPY, CODECOPY, EXTCODECOPY, RETURNDATACOPY)
117+
let memory_expansion_normal = cb.condition(not::expr(is_mcopy.expr()), |cb| {
118+
MemoryExpansionGadget::construct(cb, [dst_memory_addr.end_offset()])
119+
});
120+
121+
let memory_expansion_cost = select::expr(
122+
is_mcopy.expr(),
123+
memory_expansion_mcopy.gas_cost(),
124+
memory_expansion_normal.gas_cost(),
103125
);
126+
let memory_copier_gas =
127+
MemoryCopierGasGadget::construct(cb, dst_memory_addr.length(), memory_expansion_cost);
104128

105129
let constant_gas_cost = select::expr(
106130
is_extcodecopy.expr(),
@@ -111,7 +135,7 @@ impl<F: Field> ExecutionGadget<F> for ErrorOOGMemoryCopyGadget<F> {
111135
GasCost::WARM_ACCESS.expr(),
112136
GasCost::COLD_ACCOUNT_ACCESS.expr(),
113137
),
114-
// Constant gas cost is same for CALLDATACOPY, CODECOPY and RETURNDATACOPY.
138+
// Constant gas cost is same for CALLDATACOPY, CODECOPY,RETURNDATACOPY and mcopy.
115139
OpcodeId::CALLDATACOPY.constant_gas_cost().expr(),
116140
);
117141

@@ -147,10 +171,12 @@ impl<F: Field> ExecutionGadget<F> for ErrorOOGMemoryCopyGadget<F> {
147171
external_address,
148172
src_memory_addr,
149173
dst_memory_addr,
150-
memory_expansion,
174+
memory_expansion_mcopy,
175+
memory_expansion_normal,
151176
memory_copier_gas,
152177
insufficient_gas,
153178
is_extcodecopy,
179+
is_mcopy,
154180
common_error_gadget,
155181
}
156182
}
@@ -166,6 +192,7 @@ impl<F: Field> ExecutionGadget<F> for ErrorOOGMemoryCopyGadget<F> {
166192
) -> Result<(), Error> {
167193
let opcode = step.opcode.unwrap();
168194
let is_extcodecopy = opcode == OpcodeId::EXTCODECOPY;
195+
let is_mcopy = opcode == OpcodeId::MCOPY;
169196

170197
log::debug!(
171198
"ErrorOutOfGasMemoryCopy: opcode = {}, gas_left = {}, gas_cost = {}",
@@ -195,21 +222,37 @@ impl<F: Field> ExecutionGadget<F> for ErrorOOGMemoryCopyGadget<F> {
195222
.assign(region, offset, Value::known(F::from(transaction.id as u64)))?;
196223
self.external_address
197224
.assign(region, offset, Some(external_address.to_le_bytes()))?;
198-
// self.src_offset
199-
// .assign(region, offset, Some(src_offset.to_le_bytes()))?;
200-
self.src_memory_addr
225+
226+
let src_memory_addr = self
227+
.src_memory_addr
201228
.assign(region, offset, src_offset, copy_size)?;
202-
let memory_addr = self
229+
let dst_memory_addr = self
203230
.dst_memory_addr
204231
.assign(region, offset, dst_offset, copy_size)?;
205-
let (_, memory_expansion_cost) =
206-
self.memory_expansion
207-
.assign(region, offset, step.memory_word_size(), [memory_addr])?;
232+
let (_, memory_expansion_cost) = self.memory_expansion_normal.assign(
233+
region,
234+
offset,
235+
step.memory_word_size(),
236+
[dst_memory_addr],
237+
)?;
238+
239+
// assign memory_expansion_mcopy
240+
let (_, memory_expansion_cost_mcopy) = self.memory_expansion_mcopy.assign(
241+
region,
242+
offset,
243+
step.memory_word_size(),
244+
[src_memory_addr, dst_memory_addr],
245+
)?;
246+
208247
let memory_copier_gas = self.memory_copier_gas.assign(
209248
region,
210249
offset,
211250
MemoryExpandedAddressGadget::<F>::length_value(dst_offset, copy_size),
212-
memory_expansion_cost,
251+
if is_mcopy {
252+
memory_expansion_cost_mcopy
253+
} else {
254+
memory_expansion_cost
255+
},
213256
)?;
214257
let constant_gas_cost = if is_extcodecopy {
215258
if is_warm {
@@ -231,6 +274,11 @@ impl<F: Field> ExecutionGadget<F> for ErrorOOGMemoryCopyGadget<F> {
231274
offset,
232275
F::from(opcode.as_u64()) - F::from(OpcodeId::EXTCODECOPY.as_u64()),
233276
)?;
277+
self.is_mcopy.assign(
278+
region,
279+
offset,
280+
F::from(opcode.as_u64()) - F::from(OpcodeId::MCOPY.as_u64()),
281+
)?;
234282
self.common_error_gadget.assign(
235283
region,
236284
offset,
@@ -313,7 +361,6 @@ mod tests {
313361
for (src_offset, dest_offset, copy_size) in TESTING_MCOPY_PARIS {
314362
let testing_data =
315363
TestingData::new_for_mcopy(*src_offset, *dest_offset, *copy_size, None);
316-
317364
test_root(&testing_data);
318365
test_internal(&testing_data);
319366
}
@@ -431,13 +478,18 @@ mod tests {
431478
};
432479

433480
let gas_cost = gas_cost.unwrap_or_else(|| {
434-
let cur_memory_word_size = (src_offset + 31) / 32;
435-
let memory_word_size = (dst_offset + copy_size + 31) / 32;
481+
// no memory operation before mcopy
482+
let cur_memory_word_size = 0;
483+
let next_memory_word_size = if copy_size == 0 {
484+
cur_memory_word_size
485+
} else {
486+
(std::cmp::max(src_offset, dst_offset) + copy_size + 31) / 32
487+
};
436488

437489
OpcodeId::PUSH32.constant_gas_cost().0 * 3
438490
+ memory_copier_gas_cost(
439491
cur_memory_word_size,
440-
memory_word_size,
492+
next_memory_word_size,
441493
copy_size,
442494
GasCost::COPY.as_u64(),
443495
)

0 commit comments

Comments
 (0)