Skip to content

Commit 877a750

Browse files
committed
fix: loosened air_constraint to handle source < 16
1 parent c9336b6 commit 877a750

File tree

1 file changed

+58
-10
lines changed

1 file changed

+58
-10
lines changed

extensions/memcpy/circuit/src/iteration.rs

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,15 @@ pub struct MemcpyIterCols<T> {
7171
pub data_4: [T; MEMCPY_LOOP_NUM_LIMBS],
7272
pub read_aux: [MemoryReadAuxCols<T>; 4],
7373
pub write_aux: [MemoryWriteAuxCols<T, MEMCPY_LOOP_NUM_LIMBS>; 4],
74-
}
74+
} // number of columns is 68
75+
// other air constraints not that confident, check myself to see if confident with correctness
76+
77+
/*
78+
talk about bug in #zk-circuits the same way that previous comment was made
79+
- after have concrete idea of what the bug is, and why its failing
80+
- i mean i kinda do tho lol? just making sure that the AIR constraints are correct and make sense
81+
82+
*/
7583

7684
pub const NUM_MEMCPY_ITER_COLS: usize = size_of::<MemcpyIterCols<u8>>();
7785

@@ -125,7 +133,13 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
125133
let is_not_start = (local.is_boundary + AB::Expr::ONE)
126134
* (AB::Expr::TWO - local.is_boundary)
127135
* (AB::F::TWO).inverse();
136+
137+
let prev_is_not_start = (prev.is_boundary + AB::Expr::ONE)
138+
* (AB::Expr::TWO - prev.is_boundary)
139+
* (AB::F::TWO).inverse();
140+
128141
let prev_is_not_end = not::<AB::Expr>(
142+
// returns 0 if prev.isBoundary == 1, 1 otherwise, since we take the not
129143
(prev.is_boundary + AB::Expr::ONE) * prev.is_boundary * (AB::F::TWO).inverse(),
130144
);
131145

@@ -202,9 +216,17 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
202216
let mut is_valid_not_start_when = builder.when(local.is_valid_not_start);
203217
is_valid_not_start_when.assert_eq(len.clone(), prev_len - AB::Expr::from_canonical_u32(16));
204218

205-
// TODO: fix this constraint
206-
// is_valid_not_start_when
207-
// .assert_eq(local.source, prev.source + AB::Expr::from_canonical_u32(16));
219+
// TODO: fix this constraint? or why is this constraint failing
220+
221+
/*
222+
223+
error is if the initial source value is < 12, then -16, we do a saturating sub so its bounded below by 0
224+
then, it results in a mismatch of values
225+
*/
226+
is_valid_not_start_when.assert_eq(
227+
prev_is_not_start.clone() * local.source,
228+
prev_is_not_start.clone() * (prev.source + AB::Expr::from_canonical_u32(16)),
229+
);
208230

209231
is_valid_not_start_when.assert_eq(local.dest, prev.dest + AB::Expr::from_canonical_u32(16));
210232
local
@@ -217,7 +239,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
217239

218240
// make sure if previous row is valid and not end, then local.is_valid = 1
219241
builder
220-
.when(prev_is_not_end - not::<AB::Expr>(prev.is_valid))
242+
.when(prev_is_not_end.clone() - not::<AB::Expr>(prev.is_valid))
221243
.assert_one(local.is_valid);
222244

223245
// if prev.is_valid_start, then timestamp = prev_timestamp + is_shift_non_zero
@@ -461,8 +483,10 @@ where
461483
// Create a record sized to the exact number of 16-byte iterations (header + iterations)
462484
// This calculation must match extract_layout and fill_trace
463485

464-
let effective_len = len.saturating_sub(shift as u32); // n >= 16 + shift
465-
let num_iters = (effective_len >> 4) as usize;
486+
let head = if shift == 0 { 0 } else { 4 - shift as u32 };
487+
let effective_len = len.saturating_sub(head);
488+
let num_iters = (effective_len / 16) as usize; // floor((len - head)/16)
489+
466490
// eprintln!(
467491
// "PREFLIGHT: len={}, shift={}, effective_len={}, num_iters={}, allocated_rows={}",
468492
// len,
@@ -624,6 +648,16 @@ where
624648
}
625649
}
626650

651+
/*
652+
- generate_proving_ctx is what creates trace fill
653+
- row major matrix, so stored in a vector, row by row
654+
- look at common_main, is where trace is filled
655+
656+
- print into excel, look in trace
657+
658+
659+
- LAST STEP:
660+
*/
627661
impl<F: PrimeField32> TraceFiller<F> for MemcpyIterFiller {
628662
fn fill_trace(
629663
&self,
@@ -699,7 +733,14 @@ impl<F: PrimeField32> TraceFiller<F> for MemcpyIterFiller {
699733
timestamp - timestamp_delta
700734
};
701735

702-
let mut dest = record.inner.dest + ((num_rows - 1) << 4) as u32;
736+
// eprintln!("record.inner.source: {:?}", record.inner.source);
737+
// eprintln!(
738+
// "num_rows: {:?}, record.inner.source + ((num_rows - 1) << 4): {:?}",
739+
// num_rows,
740+
// record.inner.source + ((num_rows - 1) << 4) as u32
741+
// );
742+
743+
let mut dest = record.inner.dest + ((num_rows - 1) << 4) as u32; // got rid of -1 here???
703744
let mut source = (record.inner.source + ((num_rows - 1) << 4) as u32)
704745
.saturating_sub(12 * (record.inner.shift != 0) as u32);
705746
let mut len =
@@ -805,6 +846,11 @@ impl<F: PrimeField32> TraceFiller<F> for MemcpyIterFiller {
805846
cols.timestamp = F::from_canonical_u32(get_timestamp(false));
806847

807848
dest = dest.saturating_sub(16);
849+
850+
if source < 16 {
851+
eprintln!("source: {:?}", source);
852+
eprintln!("cols.is_boundary: {:?}", cols.is_boundary);
853+
}
808854
source = source.saturating_sub(16);
809855
len += 16;
810856

@@ -1006,8 +1052,10 @@ unsafe fn execute_e12_impl<F: PrimeField32, CTX: ExecutionCtxTrait>(
10061052
let mut source = u32::from_le_bytes(source).saturating_sub(12 * (shift != 0) as u32);
10071053
let mut len = u32::from_le_bytes(len);
10081054

1009-
let effective_len = len.saturating_sub(shift as u32); // n >= 16 + shift
1010-
let num_iters = (effective_len >> 4) as u32;
1055+
let head = if shift == 0 { 0 } else { 4 - shift as u32 };
1056+
let effective_len = len.saturating_sub(head);
1057+
let num_iters = (effective_len / 16) as u32; // floor((len - head)/16)
1058+
10111059
// Check address ranges are valid
10121060

10131061
/*

0 commit comments

Comments
 (0)