Skip to content

Commit 68b0b1a

Browse files
committed
Add compression logic
1 parent 22d9296 commit 68b0b1a

File tree

4 files changed

+42
-15
lines changed

4 files changed

+42
-15
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797
# cargo build --verbose --target ${{ env.target }} -p p3-fri-air
9898
# cargo build --verbose --target ${{ env.target }} -p p3-interpolation-air
9999
cargo build --verbose --target ${{ env.target }} -p p3-mmcs-air
100-
cargo build --verbose --target ${{ env.target }} -p p3-poseidon2-air
100+
cargo build --verbose --target ${{ env.target }} -p p3-poseidon2-circuit-air
101101
cargo build --verbose --target ${{ env.target }} -p p3-symmetric-air
102102
cargo build --verbose --target ${{ env.target }} -p p3-recursion
103103

poseidon2-circuit-air/src/air.rs

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -156,24 +156,30 @@ pub(crate) fn eval<
156156
) {
157157
air.p3_poseidon2.eval(builder);
158158

159+
// SPONGE CONSTRAINTS
159160
let next_no_reset = AB::Expr::ONE - next.reset.clone();
160161
for i in 0..(CAPACITY * D) {
161162
// The first row has capacity zeroed.
162163
builder
164+
.when(local.is_sponge.clone())
163165
.when_first_row()
164166
.assert_zero(local.poseidon2.inputs[RATE * D + i].clone());
165167

166168
// When resetting the state, we just have to clear the capacity. The rate will be overwritten by the input.
167169
builder
170+
.when(local.is_sponge.clone())
168171
.when(local.reset.clone())
169172
.assert_zero(local.poseidon2.inputs[RATE * D + i].clone());
170173

171174
// If the next row doesn't reset, propagate the capacity.
172-
builder.when(next_no_reset.clone()).assert_zero(
173-
next.poseidon2.inputs[RATE * D + i].clone()
174-
- local.poseidon2.ending_full_rounds[HALF_FULL_ROUNDS - 1].post[RATE * D + i]
175-
.clone(),
176-
);
175+
builder
176+
.when(local.is_sponge.clone())
177+
.when(next_no_reset.clone())
178+
.assert_zero(
179+
next.poseidon2.inputs[RATE * D + i].clone()
180+
- local.poseidon2.ending_full_rounds[HALF_FULL_ROUNDS - 1].post[RATE * D + i]
181+
.clone(),
182+
);
177183
}
178184

179185
let mut next_absorb = [AB::Expr::ZERO; RATE];
@@ -187,10 +193,14 @@ pub(crate) fn eval<
187193
for index in 0..(RATE * D) {
188194
let i = index / D;
189195
let j = index % D;
190-
builder.when(next_no_absorb[i].clone()).assert_zero(
191-
next.poseidon2.inputs[i * D + j].clone()
192-
- local.poseidon2.ending_full_rounds[HALF_FULL_ROUNDS - 1].post[i * D + j].clone(),
193-
);
196+
builder
197+
.when(local.is_sponge.clone())
198+
.when(next_no_absorb[i].clone())
199+
.assert_zero(
200+
next.poseidon2.inputs[i * D + j].clone()
201+
- local.poseidon2.ending_full_rounds[HALF_FULL_ROUNDS - 1].post[i * D + j]
202+
.clone(),
203+
);
194204
}
195205

196206
let mut current_absorb = [AB::Expr::ZERO; RATE];
@@ -201,11 +211,15 @@ pub(crate) fn eval<
201211
}
202212
let current_no_absorb =
203213
array::from_fn::<_, RATE, _>(|i| AB::Expr::ONE - current_absorb[i].clone());
214+
builder.assert_eq(
215+
local.is_sponge.clone() * local.reset.clone(),
216+
local.sponge_reset.clone(),
217+
);
204218
// During a reset, the rate elements not being absorbed are zeroed.
205219
for (i, col) in current_no_absorb.iter().enumerate().take(RATE) {
206220
let arr = array::from_fn::<_, D, _>(|j| local.poseidon2.inputs[i * D + j].clone().into());
207221
builder
208-
.when(local.reset.clone() * col.clone())
222+
.when(local.sponge_reset.clone() * col.clone())
209223
.assert_zeros(arr);
210224
}
211225

@@ -215,6 +229,11 @@ pub(crate) fn eval<
215229
// * local.rate[i] comes from input lookups.
216230
// - If is_squeeze = 1:
217231
// * local.rate is sent to output lookups.
232+
233+
// COMPRESSION CONSTRAINTS
234+
// TODO: Add all lookups:
235+
// - local input state comes from input lookups.
236+
// - send local output state to output lookups.
218237
}
219238

220239
impl<

poseidon2-circuit-air/src/columns.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@ use p3_poseidon2_air::Poseidon2Cols;
66
///
77
/// They extend the P3 columns with some circuit-specific columns.
88
///
9+
/// `is_sponge` (transparent): if `1`, this row performs a sponge operation (absorb or squeeze);
10+
/// otherwise, it performs a compression.
911
/// `reset` (transparent): indicates whether the state is being reset this row.
12+
/// `sponge_reset`: auxiliary column to keep constraint degrees below three.
1013
/// `absorb_flags` (transparent): for each rate element, indicates if it is being absorbed this row.
1114
/// At most one flag is set to 1 per row: if `absorb_flags[i]` is 1, then all elements up to the `i`-th
1215
/// are absorbed; the rest are propagated from the previous row.
13-
/// `input_indices` (transparent): for each rate element, indicates the index in the witness table for the
14-
/// memory lookup. It's either received (for an absorb) or sent (for a squeeze).
16+
/// `input_indices` (transparent): for each input element, indicates the index in the witness table for the
17+
/// memory lookup. It's either received (for an absorb or a compression) or sent (for a squeeze).
18+
/// `output_indices` (transparent): for each output element, indicates the index in the witness table for the
19+
/// memory lookup. Only used by compressions to send the output.
1520
#[repr(C)]
1621
pub struct Poseidon2CircuitCols<
1722
T,
@@ -25,9 +30,12 @@ pub struct Poseidon2CircuitCols<
2530
pub poseidon2:
2631
Poseidon2Cols<T, WIDTH, SBOX_DEGREE, SBOX_REGISTERS, HALF_FULL_ROUNDS, PARTIAL_ROUNDS>,
2732

33+
pub is_sponge: T,
2834
pub reset: T,
35+
pub sponge_reset: T,
2936
pub absorb_flags: [T; RATE],
30-
pub input_indices: [T; RATE],
37+
pub input_indices: [T; WIDTH],
38+
pub output_indices: [T; RATE],
3139
}
3240

3341
pub const fn num_cols<

poseidon2-circuit-air/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! And AIR for the Poseidon2 permutation.
1+
//! An AIR for the Poseidon2 table for recursion. Handles sponge operations and compressions.
22
33
#![no_std]
44

0 commit comments

Comments
 (0)