Skip to content

Commit 2a16df8

Browse files
authored
Merge branch 'main' into feat/heap-profiling
2 parents 0ff1b1b + e8e7ef8 commit 2a16df8

6 files changed

Lines changed: 181 additions & 182 deletions

File tree

prover/src/tables/memw.rs

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
//! - `timestamp`: DWordWL (64-bit timestamp, 2 cols)
1212
//! - `write2/4/8`: Bit (access width flags)
1313
//! - `old[8]`: BaseField[8] (previous values at address)
14-
//! - `add_limb_overflow[7]`: Bit[7] (carry flags for base_address + i)
14+
//! - `carry[7]`: Bit[7] (carry flags for base_address + i)
1515
//! - `old_timestamp[8]`: DWordWL[8] (previous timestamps, 16 cols)
1616
//! - `mu_read`, `mu_write`: multiplicity columns
1717
//!
1818
//! ## Virtual (computed inline)
19-
//! - `address_add[i]` = (base_address_0 + i+1 - 2^32 * overflow[i], base_address_1 + overflow[i])
19+
//! - `address_add[i]` = (base_address_0 + i+1 - 2^32 * carry[i], base_address_1 + carry[i])
2020
//! - `w2`: write2 + write4 + write8 (writing at least 2 bytes)
2121
//! - `w4`: write4 + write8 (writing at least 4 bytes)
2222
//! - `μ_sum`: μ_read + μ_write
@@ -25,6 +25,8 @@
2525
//! - 8 LT timestamp checks (old_timestamp[i] < timestamp)
2626
//! - 16 Memory bus tokens (read old + write new, per byte)
2727
//! - 2 MEMW output interactions (read + write, from CPU)
28+
//!
29+
//! ## Constraints (11 total: 2 custom + 2 IS_BIT for multiplicities + 7 IS_BIT for carry)
2830
2931
use math::field::element::FieldElement;
3032
use math::field::traits::{IsField, IsSubFieldOf};
@@ -72,8 +74,8 @@ pub mod cols {
7274
pub const OLD: [usize; 8] = [16, 17, 18, 19, 20, 21, 22, 23];
7375

7476
// Auxiliary columns
75-
/// add_limb_overflow[7]: Bit columns indicating carry when adding i+1 to base_address_0
76-
pub const ADD_LIMB_OVERFLOW: [usize; 7] = [24, 25, 26, 27, 28, 29, 30];
77+
/// carry[7]: Bit columns indicating carry when adding i+1 to base_address_0
78+
pub const CARRY: [usize; 7] = [24, 25, 26, 27, 28, 29, 30];
7779

7880
/// old_timestamp[8]: each is DWordWL (2 words = 2 columns)
7981
/// Total: 8 * 2 = 16 columns
@@ -206,11 +208,11 @@ pub fn generate_memw_trace(
206208
data[base + cols::OLD[i]] = FE::from(op.old[i]);
207209
}
208210

209-
// Auxiliary: add_limb_overflow[7]
210-
// overflow[i] = 1 if (base_address_lo + i+1) >= 2^32
211+
// Auxiliary: carry[7]
212+
// carry[i] = 1 if (base_address_lo + i+1) >= 2^32
211213
for i in 0..7 {
212214
let overflows = base_addr_lo + (i as u64 + 1) >= (1u64 << 32);
213-
data[base + cols::ADD_LIMB_OVERFLOW[i]] = FE::from(overflows as u64);
215+
data[base + cols::CARRY[i]] = FE::from(overflows as u64);
214216
}
215217

216218
// Auxiliary: old_timestamp[8] - each as DWordWL (2 words)
@@ -245,18 +247,17 @@ pub fn bus_interactions() -> Vec<BusInteraction> {
245247
// Memory bus interactions (16 total)
246248
// -------------------------------------------------------------------------
247249
// address_add[i] is VIRTUAL:
248-
// lo = base_address_0 + (i+1) - 2^32 * add_limb_overflow[i]
249-
// hi = base_address_1 + add_limb_overflow[i]
250+
// lo = base_address_0 + (i+1) - 2^32 * carry[i]
251+
// hi = base_address_1 + carry[i]
250252
//
251253
// Safety: `hi` is at most `base_address_1 + 1`. This never reaches 2^32
252254
// because the CPU table splits addresses into (lo, hi) with both halves
253255
// in [0, 2^32), and the Memw bus ties MEMW's base_address to the CPU's
254256
// value. MEMW only receives accesses where base_address_1 <= 0xFFFF_FFFE
255257
// (addresses near u64::MAX are rejected by the executor before proving).
256-
// Consequently, `add_limb_overflow[i]` is implicitly correct: a wrong
257-
// carry bit produces a memory token at a wrong address that has no
258-
// matching PAGE/REGISTER token, causing multiset imbalance and an
259-
// invalid proof.
258+
// Consequently, `carry[i]` is implicitly correct: a wrong carry bit
259+
// produces a memory token at a wrong address that has no matching
260+
// PAGE/REGISTER token, causing multiset imbalance and an invalid proof.
260261

261262
// CM8: memory[is_register, base_address, old_timestamp[0], old[0]] with +μ_sum
262263
interactions.push(BusInteraction::sender(
@@ -323,8 +324,8 @@ pub fn bus_interactions() -> Vec<BusInteraction> {
323324
));
324325

325326
// CM10/11: byte 1, multiplicity w2 = write2 + write4 + write8
326-
// address_add[0] is virtual: lo = base_address_0 + 1 - 2^32 * overflow[0]
327-
// hi = base_address_1 + overflow[0]
327+
// address_add[0] is virtual: lo = base_address_0 + 1 - 2^32 * carry[0]
328+
// hi = base_address_1 + carry[0]
328329
let addr_add_0_lo = BusValue::linear(vec![
329330
LinearTerm::Column {
330331
coefficient: 1,
@@ -333,7 +334,7 @@ pub fn bus_interactions() -> Vec<BusInteraction> {
333334
LinearTerm::Constant(1),
334335
LinearTerm::Column {
335336
coefficient: -(1i64 << 32),
336-
column: cols::ADD_LIMB_OVERFLOW[0],
337+
column: cols::CARRY[0],
337338
},
338339
]);
339340
let addr_add_0_hi = BusValue::linear(vec![
@@ -343,7 +344,7 @@ pub fn bus_interactions() -> Vec<BusInteraction> {
343344
},
344345
LinearTerm::Column {
345346
coefficient: 1,
346-
column: cols::ADD_LIMB_OVERFLOW[0],
347+
column: cols::CARRY[0],
347348
},
348349
]);
349350

@@ -401,7 +402,7 @@ pub fn bus_interactions() -> Vec<BusInteraction> {
401402

402403
// CM12/13: bytes 2-3 with multiplicity w4 = write4 + write8
403404
for i in 2..=3 {
404-
let overflow_col = cols::ADD_LIMB_OVERFLOW[i - 1];
405+
let overflow_col = cols::CARRY[i - 1];
405406
let addr_add_lo = BusValue::linear(vec![
406407
LinearTerm::Column {
407408
coefficient: 1,
@@ -479,7 +480,7 @@ pub fn bus_interactions() -> Vec<BusInteraction> {
479480

480481
// CM14/15: bytes 4-7 with multiplicity write8
481482
for i in 4..=7 {
482-
let overflow_col = cols::ADD_LIMB_OVERFLOW[i - 1];
483+
let overflow_col = cols::CARRY[i - 1];
483484
let addr_add_lo = BusValue::linear(vec![
484485
LinearTerm::Column {
485486
coefficient: 1,
@@ -857,7 +858,7 @@ where
857858
}
858859

859860
// =========================================================================
860-
// Constraints (9 total: 2 custom + 7 IS_BIT)
861+
// Constraints (11 total: 2 custom + 2 IS_BIT for multiplicities + 7 IS_BIT for carry)
861862
// =========================================================================
862863

863864
/// MEMW table constraint kinds.
@@ -946,10 +947,12 @@ impl TransitionConstraint<GoldilocksField, GoldilocksExtension> for MemwConstrai
946947

947948
/// Creates all constraints for the MEMW table.
948949
///
949-
/// 9 constraints total:
950+
/// 11 constraints total:
950951
/// - IS_BIT<μ_sum> (1)
951952
/// - w2 => μ_sum (1)
952-
/// - IS_BIT for add_limb_overflow[0..6] (7)
953+
/// - IS_BIT<μ_read> (1)
954+
/// - IS_BIT<μ_write> (1)
955+
/// - IS_BIT for carry[0..6] (7)
953956
pub fn constraints() -> Vec<Box<dyn TransitionConstraint<GoldilocksField, GoldilocksExtension>>> {
954957
let mut constraints: Vec<Box<dyn TransitionConstraint<GoldilocksField, GoldilocksExtension>>> =
955958
Vec::new();
@@ -970,8 +973,19 @@ pub fn constraints() -> Vec<Box<dyn TransitionConstraint<GoldilocksField, Goldil
970973
)));
971974
idx += 1;
972975

973-
// IS_BIT for add_limb_overflow[0..6]
974-
for &col in &cols::ADD_LIMB_OVERFLOW {
976+
// IS_BIT<μ_read>
977+
constraints.push(Box::new(IsBitConstraint::unconditional(cols::MU_READ, idx)));
978+
idx += 1;
979+
980+
// IS_BIT<μ_write>
981+
constraints.push(Box::new(IsBitConstraint::unconditional(
982+
cols::MU_WRITE,
983+
idx,
984+
)));
985+
idx += 1;
986+
987+
// IS_BIT for carry[0..6]
988+
for &col in &cols::CARRY {
975989
constraints.push(Box::new(IsBitConstraint::unconditional(col, idx)));
976990
idx += 1;
977991
}
@@ -1013,45 +1027,45 @@ mod tests {
10131027
}
10141028

10151029
#[test]
1016-
fn test_add_limb_overflow() {
1017-
// Address 0xFFFF_FFFF should overflow when adding 1
1030+
fn test_carry_flags() {
1031+
// Address 0xFFFF_FFFF should carry when adding 1
10181032
let op =
10191033
MemwOperation::new(false, 0xFFFF_FFFF, [0; 8], 100, 8, false).with_old([0; 8], [50; 8]);
10201034
let trace = generate_memw_trace(&[op]);
10211035

1022-
// All 7 overflow flags should be 1 since 0xFFFF_FFFF + i >= 2^32 for i >= 1
1036+
// All 7 carry flags should be 1 since 0xFFFF_FFFF + i >= 2^32 for i >= 1
10231037
for i in 0..7 {
1024-
let val = trace.get_main(0, cols::ADD_LIMB_OVERFLOW[i]);
1025-
assert_eq!(*val, FE::one(), "overflow[{i}] should be 1");
1038+
let val = trace.get_main(0, cols::CARRY[i]);
1039+
assert_eq!(*val, FE::one(), "carry[{i}] should be 1");
10261040
}
10271041

1028-
// Address 0x0000_0000 should not overflow
1042+
// Address 0x0000_0000 should not carry
10291043
let op2 =
10301044
MemwOperation::new(false, 0x0000_0000, [0; 8], 100, 8, false).with_old([0; 8], [50; 8]);
10311045
let trace2 = generate_memw_trace(&[op2]);
10321046
for i in 0..7 {
1033-
let val = trace2.get_main(0, cols::ADD_LIMB_OVERFLOW[i]);
1034-
assert_eq!(*val, FE::zero(), "overflow[{i}] should be 0");
1047+
let val = trace2.get_main(0, cols::CARRY[i]);
1048+
assert_eq!(*val, FE::zero(), "carry[{i}] should be 0");
10351049
}
10361050

10371051
// Address 0xFFFF_FFFE with width=8 exercises mixed per-byte carry bits:
1038-
// overflow[0]=0 (0xFFFF_FFFE+1 = 0xFFFF_FFFF < 2^32)
1039-
// overflow[1..6]=1 (0xFFFF_FFFE+2..8 >= 2^32)
1052+
// carry[0]=0 (0xFFFF_FFFE+1 = 0xFFFF_FFFF < 2^32)
1053+
// carry[1..6]=1 (0xFFFF_FFFE+2..8 >= 2^32)
10401054
let op3 =
10411055
MemwOperation::new(false, 0xFFFF_FFFE, [0; 8], 100, 8, false).with_old([0; 8], [50; 8]);
10421056
let trace3 = generate_memw_trace(&[op3]);
1043-
let val0 = trace3.get_main(0, cols::ADD_LIMB_OVERFLOW[0]);
1057+
let val0 = trace3.get_main(0, cols::CARRY[0]);
10441058
assert_eq!(
10451059
*val0,
10461060
FE::zero(),
1047-
"overflow[0] should be 0 for base 0xFFFF_FFFE"
1061+
"carry[0] should be 0 for base 0xFFFF_FFFE"
10481062
);
10491063
for i in 1..7 {
1050-
let val = trace3.get_main(0, cols::ADD_LIMB_OVERFLOW[i]);
1064+
let val = trace3.get_main(0, cols::CARRY[i]);
10511065
assert_eq!(
10521066
*val,
10531067
FE::one(),
1054-
"overflow[{i}] should be 1 for base 0xFFFF_FFFE"
1068+
"carry[{i}] should be 1 for base 0xFFFF_FFFE"
10551069
);
10561070
}
10571071
}

0 commit comments

Comments
 (0)