From 4c5e3fda8feb98c9f94d169e0295e815e405fe96 Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Fri, 14 Mar 2025 15:19:48 +0100 Subject: [PATCH 1/6] Keccakf32Memory: use compute_from instead of provide_value --- std/machines/hash/keccakf32_memory.asm | 71 ++++++++++++++++---------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/std/machines/hash/keccakf32_memory.asm b/std/machines/hash/keccakf32_memory.asm index de4ae884c3..eb9bfb13d4 100644 --- a/std/machines/hash/keccakf32_memory.asm +++ b/std/machines/hash/keccakf32_memory.asm @@ -8,7 +8,7 @@ use std::convert::fe; use std::prelude::set_hint; use std::prelude::Query; use std::prover::eval; -use std::prover::provide_value; +use std::prover::compute_from; use std::machines::large_field::memory::Memory; machine Keccakf32Memory(mem: Memory) with @@ -592,10 +592,10 @@ machine Keccakf32Memory(mem: Memory) with // } // } - let query_c: int, int, int -> int = query |x, limb, bit_in_limb| + let query_c: int, int, int, fe[] -> int = query |x, limb, bit_in_limb, a| utils::fold( 5, - |y| (int(eval(a[y * 10 + x * 2 + limb])) >> bit_in_limb) & 0x1, + |y| (int(a[y * 10 + x * 2 + limb]) >> bit_in_limb) & 0x1, 0, |acc, e| acc ^ e ); @@ -607,7 +607,7 @@ machine Keccakf32Memory(mem: Memory) with let limb = z / 32; let bit_in_limb = z % 32; - provide_value(c_i, row, fe(query_c(x, limb, bit_in_limb))); + compute_from(c_i, row, a, |a| fe(query_c(x, limb, bit_in_limb, a))) }); }; @@ -622,17 +622,17 @@ machine Keccakf32Memory(mem: Memory) with // } // } - let query_c_prime: int, int -> int = query |x, z| - int(eval(c[x * 64 + z])) ^ - int(eval(c[((x + 4) % 5) * 64 + z])) ^ - int(eval(c[((x + 1) % 5) * 64 + (z + 63) % 64])); + let query_c_prime: int, int, fe[] -> int = query |x, z, c| + int(c[x * 64 + z]) ^ + int(c[((x + 4) % 5) * 64 + z]) ^ + int(c[((x + 1) % 5) * 64 + (z + 63) % 64]); query |row| { let _ = array::map_enumerated(c_prime, |i, c_i| { let x = i / 64; let z = i % 64; - provide_value(c_i, row, fe(query_c_prime(x, z))); + compute_from(c_i, row, c, |c| fe(query_c_prime(x, z, c))); }); }; @@ -652,10 +652,6 @@ machine Keccakf32Memory(mem: Memory) with // } // } - let query_a_prime: int, int, int, int, int -> int = query |x, y, z, limb, bit_in_limb| - ((int(eval(a[y * 10 + x * 2 + limb])) >> bit_in_limb) & 0x1) ^ - int(eval(c[x * 64 + z])) ^ - int(eval(c_prime[x * 64 + z])); query |row| { let _ = array::map_enumerated(a_prime, |i, a_i| { @@ -665,7 +661,14 @@ machine Keccakf32Memory(mem: Memory) with let limb = z / 32; let bit_in_limb = z % 32; - provide_value(a_i, row, fe(query_a_prime(x, y, z, limb, bit_in_limb))); + let a_elem = a[y * 10 + x * 2 + limb]; + let c_elem = c[x * 64 + z]; + let c_prime_elem = c_prime[x * 64 + z]; + + compute_from( + a_i, row, [a_elem, c_elem, c_prime_elem], + |inputs| fe(((int(inputs[0]) >> bit_in_limb) & 0x1) ^ int(inputs[1]) ^ int(inputs[2])) + ); }); }; @@ -687,13 +690,23 @@ machine Keccakf32Memory(mem: Memory) with // } // } - let query_a_prime_prime: int, int, int -> int = query |x, y, limb| + + let b_index: int, int, int -> int = |x, y, z| { + let a: int = (x + 3 * y) % 5; + let rot: int = R[a * 5 + x]; // b = x + x * 320 + a * 64 + (z + 64 - rot) % 64 + }; + let andn_int: int, int -> int = |a, b| (1 - a) * b; + + let query_a_prime_prime: int, int, int, fe[] -> int = query |x, y, limb, a_prime| utils::fold( 32, - |z| - int(eval(b(x, y, (limb + 1) * 32 - 1 - z))) ^ - int(eval(andn(b((x + 1) % 5, y, (limb + 1) * 32 - 1 - z), - b((x + 2) % 5, y, (limb + 1) * 32 - 1 - z)))), + |z| + int(a_prime[b_index(x, y, (limb + 1) * 32 - 1 - z)]) ^ + int(andn_int( + int(a_prime[b_index((x + 1) % 5, y, (limb + 1) * 32 - 1 - z)]), + int(a_prime[b_index((x + 2) % 5, y, (limb + 1) * 32 - 1 - z)]) + )), 0, |acc, e| acc * 2 + e ); @@ -704,7 +717,7 @@ machine Keccakf32Memory(mem: Memory) with let x = (i / 2) % 5; let limb = i % 2; - provide_value(a_i, row, fe(query_a_prime_prime(x, y, limb))); + compute_from(a_i, row, a_prime, |a_prime| fe(query_a_prime_prime(x, y, limb, a_prime))); }); }; @@ -730,10 +743,11 @@ machine Keccakf32Memory(mem: Memory) with let limb = i / 32; let bit_in_limb = i % 32; - provide_value( + compute_from( a_i, - row, - fe((int(eval(a_prime_prime[limb])) >> bit_in_limb) & 0x1) + row, + a_prime_prime, + |a_prime_prime| fe((int(a_prime_prime[limb]) >> bit_in_limb) & 0x1) ); }); }; @@ -745,16 +759,17 @@ machine Keccakf32Memory(mem: Memory) with // F::from_canonical_u16(row.a_prime_prime[0][0][limb].as_canonical_u64() as u16 ^ rc_lo); // } - let query_a_prime_prime_prime_0_0_limbs: int, int -> int = query |round, limb| - int(eval(a_prime_prime[limb])) ^ + let query_a_prime_prime_prime_0_0_limbs: int, int, fe[] -> int = query |round, limb, a_prime_prime| + int(a_prime_prime[limb]) ^ ((RC[round] >> (limb * 32)) & 0xffffffff); query |row| { let _ = array::new(2, |limb| { - provide_value( + compute_from( a_prime_prime_prime_0_0_limbs[limb], - row, - fe(query_a_prime_prime_prime_0_0_limbs(row % NUM_ROUNDS, limb) + row, + a_prime_prime, + |a_prime_prime| fe(query_a_prime_prime_prime_0_0_limbs(row % NUM_ROUNDS, limb, a_prime_prime) )); }); }; From 1c1564783e3ad0f90a3bf139ff90120befc0c14f Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Fri, 14 Mar 2025 16:07:51 +0100 Subject: [PATCH 2/6] Only require the elements actually needed --- std/machines/hash/keccakf32_memory.asm | 41 ++++++++++++-------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/std/machines/hash/keccakf32_memory.asm b/std/machines/hash/keccakf32_memory.asm index eb9bfb13d4..3a2e7a7926 100644 --- a/std/machines/hash/keccakf32_memory.asm +++ b/std/machines/hash/keccakf32_memory.asm @@ -592,14 +592,6 @@ machine Keccakf32Memory(mem: Memory) with // } // } - let query_c: int, int, int, fe[] -> int = query |x, limb, bit_in_limb, a| - utils::fold( - 5, - |y| (int(a[y * 10 + x * 2 + limb]) >> bit_in_limb) & 0x1, - 0, - |acc, e| acc ^ e - ); - query |row| { let _ = array::map_enumerated(c, |i, c_i| { let x = i / 64; @@ -607,7 +599,12 @@ machine Keccakf32Memory(mem: Memory) with let limb = z / 32; let bit_in_limb = z % 32; - compute_from(c_i, row, a, |a| fe(query_c(x, limb, bit_in_limb, a))) + let a_elems = array::new(5, |y| a[y * 10 + x * 2 + limb]); + + compute_from( + c_i, row, a_elems, + |a_elems_fe| fe(utils::fold( + 5, |y| (int(a_elems_fe[y]) >> bit_in_limb) & 0x1, 0, |acc, e| acc ^ e))) }); }; @@ -622,17 +619,18 @@ machine Keccakf32Memory(mem: Memory) with // } // } - let query_c_prime: int, int, fe[] -> int = query |x, z, c| - int(c[x * 64 + z]) ^ - int(c[((x + 4) % 5) * 64 + z]) ^ - int(c[((x + 1) % 5) * 64 + (z + 63) % 64]); - query |row| { let _ = array::map_enumerated(c_prime, |i, c_i| { let x = i / 64; let z = i % 64; - compute_from(c_i, row, c, |c| fe(query_c_prime(x, z, c))); + let c_elems = [ + c[x * 64 + z], + c[((x + 4) % 5) * 64 + z], + c[((x + 1) % 5) * 64 + (z + 63) % 64] + ]; + + compute_from(c_i, row, c_elems, |c_elems_fe| fe(int(c_elems_fe[0]) ^ int(c_elems_fe[1]) ^ int(c_elems_fe[2]))); }); }; @@ -717,6 +715,7 @@ machine Keccakf32Memory(mem: Memory) with let x = (i / 2) % 5; let limb = i % 2; + // Seems to be faster to require all 5 * 5 * 64 elements of a_prime compute_from(a_i, row, a_prime, |a_prime| fe(query_a_prime_prime(x, y, limb, a_prime))); }); }; @@ -759,18 +758,16 @@ machine Keccakf32Memory(mem: Memory) with // F::from_canonical_u16(row.a_prime_prime[0][0][limb].as_canonical_u64() as u16 ^ rc_lo); // } - let query_a_prime_prime_prime_0_0_limbs: int, int, fe[] -> int = query |round, limb, a_prime_prime| - int(a_prime_prime[limb]) ^ - ((RC[round] >> (limb * 32)) & 0xffffffff); - query |row| { let _ = array::new(2, |limb| { + let a_prime_prime_elem = a_prime_prime[limb]; + compute_from( a_prime_prime_prime_0_0_limbs[limb], row, - a_prime_prime, - |a_prime_prime| fe(query_a_prime_prime_prime_0_0_limbs(row % NUM_ROUNDS, limb, a_prime_prime) - )); + [a_prime_prime_elem], + |inputs| fe(int(inputs[0]) ^ ((RC[row % NUM_ROUNDS] >> (limb * 32)) & 0xffffffff)) + ); }); }; } From b0e93acb0687325385c10de65ec41888c7d0de6f Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Sun, 16 Mar 2025 21:14:03 +0100 Subject: [PATCH 3/6] Use compute_from_multi --- std/machines/hash/keccakf32_memory.asm | 105 +++++++++++-------------- 1 file changed, 44 insertions(+), 61 deletions(-) diff --git a/std/machines/hash/keccakf32_memory.asm b/std/machines/hash/keccakf32_memory.asm index 3a2e7a7926..337c2ba4d1 100644 --- a/std/machines/hash/keccakf32_memory.asm +++ b/std/machines/hash/keccakf32_memory.asm @@ -8,7 +8,7 @@ use std::convert::fe; use std::prelude::set_hint; use std::prelude::Query; use std::prover::eval; -use std::prover::compute_from; +use std::prover::compute_from_multi; use std::machines::large_field::memory::Memory; machine Keccakf32Memory(mem: Memory) with @@ -592,21 +592,21 @@ machine Keccakf32Memory(mem: Memory) with // } // } - query |row| { - let _ = array::map_enumerated(c, |i, c_i| { + query |row| compute_from_multi( + c, row, a, + |a_fe| array::new(array::len(c), |i| { let x = i / 64; let z = i % 64; let limb = z / 32; let bit_in_limb = z % 32; - let a_elems = array::new(5, |y| a[y * 10 + x * 2 + limb]); - - compute_from( - c_i, row, a_elems, - |a_elems_fe| fe(utils::fold( - 5, |y| (int(a_elems_fe[y]) >> bit_in_limb) & 0x1, 0, |acc, e| acc ^ e))) - }); - }; + fe(utils::fold( + 5, + |y| (int(a_fe[y * 10 + x * 2 + limb]) >> bit_in_limb) & 0x1, + 0, + |acc, e| acc ^ e + )) + })); // // Populate C'[x, z] = xor(C[x, z], C[x - 1, z], C[x + 1, z - 1]). // for x in 0..5 { @@ -619,20 +619,18 @@ machine Keccakf32Memory(mem: Memory) with // } // } - query |row| { - let _ = array::map_enumerated(c_prime, |i, c_i| { + query |row| compute_from_multi( + c_prime, row, c, + |c_fe| array::new(array::len(c_prime), |i| { let x = i / 64; let z = i % 64; - let c_elems = [ - c[x * 64 + z], - c[((x + 4) % 5) * 64 + z], - c[((x + 1) % 5) * 64 + (z + 63) % 64] - ]; - - compute_from(c_i, row, c_elems, |c_elems_fe| fe(int(c_elems_fe[0]) ^ int(c_elems_fe[1]) ^ int(c_elems_fe[2]))); - }); - }; + fe( + int(c_fe[x * 64 + z]) ^ + int(c_fe[((x + 4) % 5) * 64 + z]) ^ + int(c_fe[((x + 1) % 5) * 64 + (z + 63) % 64]) + ) + })); // // Populate A'. To avoid shifting indices, we rewrite // // A'[x, y, z] = xor(A[x, y, z], C[x - 1, z], C[x + 1, z - 1]) @@ -651,24 +649,21 @@ machine Keccakf32Memory(mem: Memory) with // } - query |row| { - let _ = array::map_enumerated(a_prime, |i, a_i| { + query |row| compute_from_multi( + a_prime, row, a + c + c_prime, + |inputs| array::new(array::len(a_prime), |i| { let y = i / 320; let x = (i / 64) % 5; let z = i % 64; let limb = z / 32; let bit_in_limb = z % 32; - let a_elem = a[y * 10 + x * 2 + limb]; - let c_elem = c[x * 64 + z]; - let c_prime_elem = c_prime[x * 64 + z]; + let a_elem = inputs[y * 10 + x * 2 + limb]; + let c_elem = inputs[x * 64 + z + array::len(a)]; + let c_prime_elem = inputs[x * 64 + z + array::len(a) + array::len(c)]; - compute_from( - a_i, row, [a_elem, c_elem, c_prime_elem], - |inputs| fe(((int(inputs[0]) >> bit_in_limb) & 0x1) ^ int(inputs[1]) ^ int(inputs[2])) - ); - }); - }; + fe(((int(a_elem) >> bit_in_limb) & 0x1) ^ int(c_elem) ^ int(c_prime_elem)) + })); // // Populate A''.P // // A''[x, y] = xor(B[x, y], andn(B[x + 1, y], B[x + 2, y])). @@ -709,16 +704,15 @@ machine Keccakf32Memory(mem: Memory) with |acc, e| acc * 2 + e ); - query |row| { - let _ = array::map_enumerated(a_prime_prime, |i, a_i| { + query |row| compute_from_multi( + a_prime_prime, row, a_prime, + |a_prime_fe| array::new(array::len(a_prime_prime), |i| { let y = i / 10; let x = (i / 2) % 5; let limb = i % 2; - // Seems to be faster to require all 5 * 5 * 64 elements of a_prime - compute_from(a_i, row, a_prime, |a_prime| fe(query_a_prime_prime(x, y, limb, a_prime))); - }); - }; + fe(query_a_prime_prime(x, y, limb, a_prime_fe)) + })); // // For the XOR, we split A''[0, 0] to bits. // let mut val = 0; // smaller address correspond to less significant limb @@ -737,19 +731,14 @@ machine Keccakf32Memory(mem: Memory) with // *bit = F::from_bool(val_bits[i]); // } - query |row| { - let _ = array::map_enumerated(a_prime_prime_0_0_bits, |i, a_i| { + query |row| compute_from_multi( + a_prime_prime_0_0_bits, row, a_prime_prime, + |a_prime_prime_fe| array::new(array::len(a_prime_prime_0_0_bits), |i| { let limb = i / 32; let bit_in_limb = i % 32; - compute_from( - a_i, - row, - a_prime_prime, - |a_prime_prime| fe((int(a_prime_prime[limb]) >> bit_in_limb) & 0x1) - ); - }); - }; + fe((int(a_prime_prime_fe[limb]) >> bit_in_limb) & 0x1) + })); // // A''[0, 0] is additionally xor'd with RC. // for limb in 0..U64_LIMBS { @@ -758,16 +747,10 @@ machine Keccakf32Memory(mem: Memory) with // F::from_canonical_u16(row.a_prime_prime[0][0][limb].as_canonical_u64() as u16 ^ rc_lo); // } - query |row| { - let _ = array::new(2, |limb| { - let a_prime_prime_elem = a_prime_prime[limb]; - - compute_from( - a_prime_prime_prime_0_0_limbs[limb], - row, - [a_prime_prime_elem], - |inputs| fe(int(inputs[0]) ^ ((RC[row % NUM_ROUNDS] >> (limb * 32)) & 0xffffffff)) - ); - }); - }; + query |row| compute_from_multi( + a_prime_prime_prime_0_0_limbs, row, array::sub_array(a_prime_prime, 0, 2), + |a_prime_prime_fe| array::new(2, |limb| { + fe(int(a_prime_prime_fe[limb]) ^ ((RC[row % NUM_ROUNDS] >> (limb * 32)) & 0xffffffff)) + })); + } From 4616435b3b16069fb965b6d8d9b094ba452da4bc Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Sun, 16 Mar 2025 22:03:42 +0100 Subject: [PATCH 4/6] Hard-code lengths --- std/machines/hash/keccakf32_memory.asm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/std/machines/hash/keccakf32_memory.asm b/std/machines/hash/keccakf32_memory.asm index 337c2ba4d1..ae30d05522 100644 --- a/std/machines/hash/keccakf32_memory.asm +++ b/std/machines/hash/keccakf32_memory.asm @@ -594,7 +594,7 @@ machine Keccakf32Memory(mem: Memory) with query |row| compute_from_multi( c, row, a, - |a_fe| array::new(array::len(c), |i| { + |a_fe| array::new(5 * 64, |i| { let x = i / 64; let z = i % 64; let limb = z / 32; @@ -621,7 +621,7 @@ machine Keccakf32Memory(mem: Memory) with query |row| compute_from_multi( c_prime, row, c, - |c_fe| array::new(array::len(c_prime), |i| { + |c_fe| array::new(5 * 64, |i| { let x = i / 64; let z = i % 64; @@ -651,7 +651,7 @@ machine Keccakf32Memory(mem: Memory) with query |row| compute_from_multi( a_prime, row, a + c + c_prime, - |inputs| array::new(array::len(a_prime), |i| { + |inputs| array::new(5 * 5 * 64, |i| { let y = i / 320; let x = (i / 64) % 5; let z = i % 64; @@ -659,8 +659,8 @@ machine Keccakf32Memory(mem: Memory) with let bit_in_limb = z % 32; let a_elem = inputs[y * 10 + x * 2 + limb]; - let c_elem = inputs[x * 64 + z + array::len(a)]; - let c_prime_elem = inputs[x * 64 + z + array::len(a) + array::len(c)]; + let c_elem = inputs[x * 64 + z + 5 * 5 * 2]; + let c_prime_elem = inputs[x * 64 + z + 5 * 5 * 2 + 5 * 64]; fe(((int(a_elem) >> bit_in_limb) & 0x1) ^ int(c_elem) ^ int(c_prime_elem)) })); @@ -706,7 +706,7 @@ machine Keccakf32Memory(mem: Memory) with query |row| compute_from_multi( a_prime_prime, row, a_prime, - |a_prime_fe| array::new(array::len(a_prime_prime), |i| { + |a_prime_fe| array::new(5 * 5 * 2, |i| { let y = i / 10; let x = (i / 2) % 5; let limb = i % 2; @@ -733,7 +733,7 @@ machine Keccakf32Memory(mem: Memory) with query |row| compute_from_multi( a_prime_prime_0_0_bits, row, a_prime_prime, - |a_prime_prime_fe| array::new(array::len(a_prime_prime_0_0_bits), |i| { + |a_prime_prime_fe| array::new(64, |i| { let limb = i / 32; let bit_in_limb = i % 32; From f14d12c05999be8ea0514239d97f49dd31d62a6f Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Tue, 18 Mar 2025 11:23:41 +0100 Subject: [PATCH 5/6] Remove unnecessary prover functions --- std/machines/hash/keccakf32_memory.asm | 123 +++---------------------- 1 file changed, 12 insertions(+), 111 deletions(-) diff --git a/std/machines/hash/keccakf32_memory.asm b/std/machines/hash/keccakf32_memory.asm index ae30d05522..c2ad80f2c0 100644 --- a/std/machines/hash/keccakf32_memory.asm +++ b/std/machines/hash/keccakf32_memory.asm @@ -578,6 +578,8 @@ machine Keccakf32Memory(mem: Memory) with }); // Prover function section (for witness generation). + // Hints are only needed for c and a_prime, the solver is able to figure out the + // rest of the witness. // // Populate C[x] = xor(A[x, 0], A[x, 1], A[x, 2], A[x, 3], A[x, 4]). // for x in 0..5 { @@ -608,30 +610,6 @@ machine Keccakf32Memory(mem: Memory) with )) })); - // // Populate C'[x, z] = xor(C[x, z], C[x - 1, z], C[x + 1, z - 1]). - // for x in 0..5 { - // for z in 0..64 { - // row.c_prime[x][z] = xor([ - // row.c[x][z], - // row.c[(x + 4) % 5][z], - // row.c[(x + 1) % 5][(z + 63) % 64], - // ]); - // } - // } - - query |row| compute_from_multi( - c_prime, row, c, - |c_fe| array::new(5 * 64, |i| { - let x = i / 64; - let z = i % 64; - - fe( - int(c_fe[x * 64 + z]) ^ - int(c_fe[((x + 4) % 5) * 64 + z]) ^ - int(c_fe[((x + 1) % 5) * 64 + (z + 63) % 64]) - ) - })); - // // Populate A'. To avoid shifting indices, we rewrite // // A'[x, y, z] = xor(A[x, y, z], C[x - 1, z], C[x + 1, z - 1]) // // as @@ -648,7 +626,6 @@ machine Keccakf32Memory(mem: Memory) with // } // } - query |row| compute_from_multi( a_prime, row, a + c + c_prime, |inputs| array::new(5 * 5 * 64, |i| { @@ -665,92 +642,16 @@ machine Keccakf32Memory(mem: Memory) with fe(((int(a_elem) >> bit_in_limb) & 0x1) ^ int(c_elem) ^ int(c_prime_elem)) })); - // // Populate A''.P - // // A''[x, y] = xor(B[x, y], andn(B[x + 1, y], B[x + 2, y])). - // for y in 0..5 { - // for x in 0..5 { - // for limb in 0..U64_LIMBS { - // row.a_prime_prime[y][x][limb] = (limb * BITS_PER_LIMB..(limb + 1) * BITS_PER_LIMB) - // .rev() - // .fold(F::zero(), |acc, z| { - // let bit = xor([ - // row.b(x, y, z), - // andn(row.b((x + 1) % 5, y, z), row.b((x + 2) % 5, y, z)), - // ]); - // acc.double() + bit - // }); - // } - // } - // } - - - let b_index: int, int, int -> int = |x, y, z| { - let a: int = (x + 3 * y) % 5; - let rot: int = R[a * 5 + x]; // b = x - x * 320 + a * 64 + (z + 64 - rot) % 64 - }; - let andn_int: int, int -> int = |a, b| (1 - a) * b; - - let query_a_prime_prime: int, int, int, fe[] -> int = query |x, y, limb, a_prime| - utils::fold( - 32, - |z| - int(a_prime[b_index(x, y, (limb + 1) * 32 - 1 - z)]) ^ - int(andn_int( - int(a_prime[b_index((x + 1) % 5, y, (limb + 1) * 32 - 1 - z)]), - int(a_prime[b_index((x + 2) % 5, y, (limb + 1) * 32 - 1 - z)]) - )), - 0, - |acc, e| acc * 2 + e + // TODO: This hint is correct but not needed (the solver can figure this out). + // We keep it here because it prevents the JIT solver from succeeding (because of the + // use of `provide_value`), because it currently fails when compiling Rust code. + // Once these issues are resolved, we can remove this hint. + query |row| { + std::prover::provide_value( + a_prime_prime_0_0_bits[0], + row, + fe((int(eval(a_prime_prime[0]))) & 0x1) ); - - query |row| compute_from_multi( - a_prime_prime, row, a_prime, - |a_prime_fe| array::new(5 * 5 * 2, |i| { - let y = i / 10; - let x = (i / 2) % 5; - let limb = i % 2; - - fe(query_a_prime_prime(x, y, limb, a_prime_fe)) - })); - - // // For the XOR, we split A''[0, 0] to bits. - // let mut val = 0; // smaller address correspond to less significant limb - // for limb in 0..U64_LIMBS { - // let val_limb = row.a_prime_prime[0][0][limb].as_canonical_u64(); - // val |= val_limb << (limb * BITS_PER_LIMB); - // } - // let val_bits: Vec = (0..64) // smaller address correspond to less significant bit - // .scan(val, |acc, _| { - // let bit = (*acc & 1) != 0; - // *acc >>= 1; - // Some(bit) - // }) - // .collect(); - // for (i, bit) in row.a_prime_prime_0_0_bits.iter_mut().enumerate() { - // *bit = F::from_bool(val_bits[i]); - // } - - query |row| compute_from_multi( - a_prime_prime_0_0_bits, row, a_prime_prime, - |a_prime_prime_fe| array::new(64, |i| { - let limb = i / 32; - let bit_in_limb = i % 32; - - fe((int(a_prime_prime_fe[limb]) >> bit_in_limb) & 0x1) - })); - - // // A''[0, 0] is additionally xor'd with RC. - // for limb in 0..U64_LIMBS { - // let rc_lo = rc_value_limb(round, limb); - // row.a_prime_prime_prime_0_0_limbs[limb] = - // F::from_canonical_u16(row.a_prime_prime[0][0][limb].as_canonical_u64() as u16 ^ rc_lo); - // } - - query |row| compute_from_multi( - a_prime_prime_prime_0_0_limbs, row, array::sub_array(a_prime_prime, 0, 2), - |a_prime_prime_fe| array::new(2, |limb| { - fe(int(a_prime_prime_fe[limb]) ^ ((RC[row % NUM_ROUNDS] >> (limb * 32)) & 0xffffffff)) - })); + }; } From d00db1b32b066198198be5a8fa41ab77b778923b Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Tue, 18 Mar 2025 11:25:32 +0100 Subject: [PATCH 6/6] Reintroduce array::len calls for clarity --- std/machines/hash/keccakf32_memory.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/machines/hash/keccakf32_memory.asm b/std/machines/hash/keccakf32_memory.asm index c2ad80f2c0..3bc1507a47 100644 --- a/std/machines/hash/keccakf32_memory.asm +++ b/std/machines/hash/keccakf32_memory.asm @@ -596,7 +596,7 @@ machine Keccakf32Memory(mem: Memory) with query |row| compute_from_multi( c, row, a, - |a_fe| array::new(5 * 64, |i| { + |a_fe| array::new(array::len(c), |i| { let x = i / 64; let z = i % 64; let limb = z / 32; @@ -628,7 +628,7 @@ machine Keccakf32Memory(mem: Memory) with query |row| compute_from_multi( a_prime, row, a + c + c_prime, - |inputs| array::new(5 * 5 * 64, |i| { + |inputs| array::new(array::len(a_prime), |i| { let y = i / 320; let x = (i / 64) % 5; let z = i % 64;