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

Commit 9e559e5

Browse files
author
Aurélien Nicolas
committed
memory_opt: Prevent an event from spilling into the disabled rows.
1 parent 212e12d commit 9e559e5

File tree

1 file changed

+11
-21
lines changed

1 file changed

+11
-21
lines changed

zkevm-circuits/src/copy_circuit.rs

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,6 @@ impl<F: Field> SubCircuitConfig<F> for CopyCircuitConfig<F> {
244244
)(meta),
245245
]);
246246
vec![
247-
// If a row is not enabled (fixed), it is not in an event.
248-
// TODO: not currently possible due to API limitations.
249-
// (1.expr() - enabled.expr()) * is_event.expr(),
250-
251247
// If a row is anything but padding (filler of the table), it is in an event.
252248
enabled.expr()
253249
* ((1.expr() - is_event.expr())
@@ -321,6 +317,9 @@ impl<F: Field> SubCircuitConfig<F> for CopyCircuitConfig<F> {
321317
- meta.query_advice(is_last, Rotation::cur())
322318
- meta.query_advice(is_last, Rotation::next());
323319

320+
// Prevent an event from spilling into the disabled rows. This also ensures that eventually is_last=1.
321+
cb.require_zero("the next row is enabled", is_continue.expr() * not::expr(meta.query_fixed(q_enable, Rotation::next())));
322+
324323
let is_word_end = is_word_end.is_equal_expression.expr();
325324

326325
// Apply the same constraints for the RLCs of words before and after the write.
@@ -736,13 +735,6 @@ impl<F: Field> CopyCircuitConfig<F> {
736735
{
737736
let is_read = step_idx % 2 == 0;
738737

739-
region.assign_fixed(
740-
|| format!("q_enable at row: {offset}"),
741-
self.q_enable,
742-
*offset,
743-
|| Value::known(F::one()),
744-
)?;
745-
746738
// Copy table assignments
747739
for (&column, &(value, label)) in
748740
<CopyTable as LookupTable<F>>::advice_columns(&self.copy_table)
@@ -880,9 +872,7 @@ impl<F: Field> CopyCircuitConfig<F> {
880872
.sum::<usize>();
881873

882874
// The `+ 2` is used to take into account the two extra empty copy rows needed
883-
// to satisfy the query at `Rotation(2)` performed inside of the
884-
// `rows[2].value == rows[0].value * r + rows[1].value` requirement in the RLC
885-
// Accumulation gate.
875+
// to satisfy the queries at `Rotation(2)`.
886876
assert!(
887877
copy_rows_needed + 2 <= max_copy_rows,
888878
"copy rows not enough {copy_rows_needed} vs {max_copy_rows}"
@@ -976,14 +966,14 @@ impl<F: Field> CopyCircuitConfig<F> {
976966
lt_chip: &LtChip<F, 8>,
977967
lt_word_end_chip: &IsEqualChip<F>,
978968
) -> Result<(), Error> {
969+
// q_enable
970+
region.assign_fixed(
971+
|| "q_enable",
972+
self.q_enable,
973+
*offset,
974+
|| Value::known(F::from(!is_last_two)),
975+
)?;
979976
if !is_last_two {
980-
// q_enable
981-
region.assign_fixed(
982-
|| "q_enable",
983-
self.q_enable,
984-
*offset,
985-
|| Value::known(F::one()),
986-
)?;
987977
// q_step
988978
if *offset % 2 == 0 {
989979
self.q_step.enable(region, *offset)?;

0 commit comments

Comments
 (0)