Skip to content

Commit 38a9ba4

Browse files
committed
adjust degree
1 parent e4da12f commit 38a9ba4

3 files changed

Lines changed: 49 additions & 28 deletions

File tree

extensions/native/circuit/src/poseidon2/air.rs

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ impl<AB: InteractionBuilder, const SBOX_REGISTERS: usize> Air<AB>
9494
inside_row,
9595
simple,
9696
multi_observe_row,
97+
not_hint_multi_observe,
9798
end_inside_row,
9899
end_top_level,
99100
start_top_level,
@@ -723,6 +724,7 @@ impl<AB: InteractionBuilder, const SBOX_REGISTERS: usize> Air<AB>
723724
hint_id,
724725
ctx,
725726
read_ctx,
727+
chunk_ts_count,
726728
is_first,
727729
is_last,
728730
curr_len,
@@ -748,6 +750,16 @@ impl<AB: InteractionBuilder, const SBOX_REGISTERS: usize> Air<AB>
748750
builder.when(multi_observe_row).assert_bool(is_last);
749751
builder.when(multi_observe_row).assert_bool(should_permute);
750752
builder.when(multi_observe_row).assert_bool(is_hint);
753+
builder.assert_eq(
754+
not_hint_multi_observe,
755+
multi_observe_row * (AB::Expr::ONE - is_hint),
756+
);
757+
let hint_multi_observe: AB::Expr = multi_observe_row - not_hint_multi_observe;
758+
// chunk_ts_count = (end_idx - start_idx) * (2 - is_hint)
759+
builder.when(multi_observe_row).assert_eq(
760+
chunk_ts_count,
761+
(end_idx - start_idx) * AB::F::TWO - (end_idx - start_idx) * is_hint,
762+
);
751763

752764
self.execution_bridge
753765
.execute_and_increment_pc(
@@ -813,49 +825,48 @@ impl<AB: InteractionBuilder, const SBOX_REGISTERS: usize> Air<AB>
813825
)
814826
.eval(builder, multi_observe_row * is_first);
815827

816-
// ts_per_element = 2 - is_hint (non-hint: read+write=2, hint: write-only=1)
817-
let is_hint_expr: AB::Expr = is_hint.into();
818-
let ts_per_element: AB::Expr = AB::Expr::TWO - is_hint_expr.clone();
828+
// Per-element constraints for chunk rows.
819829
for i in 0..CHUNK {
820-
let i_var: AB::Expr = AB::F::from_canonical_usize(i).into();
821-
let start_idx_expr: AB::Expr = start_idx.into();
822-
let element_start_ts: AB::Expr =
823-
start_timestamp.into() + (i_var.clone() - start_idx_expr.clone()) * ts_per_element.clone();
830+
let i_var = AB::F::from_canonical_usize(i);
831+
832+
// Hint mode: lookup from hint space.
833+
self.hint_bridge.lookup(
834+
builder,
835+
hint_id,
836+
curr_len + i_var - start_idx,
837+
data[i],
838+
hint_multi_observe.clone() * aux_read_enabled[i],
839+
);
824840

825-
// Non-hint mode: read from memory
841+
// Non-hint mode: read from memory.
826842
self.memory_bridge
827843
.read(
828844
MemoryAddress::new(
829845
self.address_space,
830-
input_ptr + curr_len + i_var.clone() - start_idx_expr.clone(),
846+
input_ptr + curr_len + i_var - start_idx,
831847
),
832848
[data[i]],
833-
element_start_ts.clone(),
849+
start_timestamp + i_var * AB::F::TWO - start_idx * AB::F::TWO,
834850
&read_data[i],
835851
)
836-
.eval(
837-
builder,
838-
multi_observe_row * aux_read_enabled[i] * (AB::Expr::ONE - is_hint_expr.clone()),
839-
);
840-
841-
// Hint mode: lookup from hint space
842-
self.hint_bridge.lookup(
843-
builder,
844-
hint_id,
845-
curr_len + i_var.clone() - start_idx_expr.clone(),
846-
data[i],
847-
multi_observe_row * aux_read_enabled[i] * is_hint_expr.clone(),
848-
);
852+
.eval(builder, not_hint_multi_observe * aux_read_enabled[i]);
853+
self.memory_bridge
854+
.write(
855+
MemoryAddress::new(self.address_space, state_ptr + i_var),
856+
[data[i]],
857+
start_timestamp + i_var * AB::F::TWO - start_idx * AB::F::TWO + AB::F::ONE,
858+
&write_data[i],
859+
)
860+
.eval(builder, not_hint_multi_observe * aux_read_enabled[i]);
849861

850-
// Write to sponge state (always, for both modes)
851862
self.memory_bridge
852863
.write(
853864
MemoryAddress::new(self.address_space, state_ptr + i_var),
854865
[data[i]],
855-
element_start_ts + (AB::Expr::ONE - is_hint_expr.clone()),
866+
start_timestamp + i_var - start_idx,
856867
&write_data[i],
857868
)
858-
.eval(builder, multi_observe_row * aux_read_enabled[i]);
869+
.eval(builder, hint_multi_observe.clone() * aux_read_enabled[i]);
859870
}
860871

861872
for i in 0..(CHUNK - 1) {
@@ -926,7 +937,7 @@ impl<AB: InteractionBuilder, const SBOX_REGISTERS: usize> Air<AB>
926937
.write(
927938
MemoryAddress::new(self.address_space, state_ptr),
928939
full_sponge_output,
929-
start_timestamp + (end_idx - start_idx) * (AB::Expr::TWO - is_hint_expr.clone()),
940+
start_timestamp + chunk_ts_count,
930941
&write_sponge_state,
931942
)
932943
.eval(builder, multi_observe_row * should_permute);
@@ -955,7 +966,7 @@ impl<AB: InteractionBuilder, const SBOX_REGISTERS: usize> Air<AB>
955966
.write(
956967
MemoryAddress::new(self.address_space, ctx_ptr),
957968
[final_idx],
958-
start_timestamp + (end_idx - start_idx) * (AB::Expr::TWO - is_hint_expr) + should_permute,
969+
start_timestamp + chunk_ts_count + should_permute,
959970
&write_final_idx,
960971
)
961972
.eval(builder, multi_observe_row * is_last);

extensions/native/circuit/src/poseidon2/chip.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,10 @@ where
771771
multi_observe_cols.hint_id = hint_id;
772772
multi_observe_cols.ctx = ctx;
773773

774+
// chunk_ts_count will be filled per-chunk row below
775+
774776
cols.multi_observe_row = F::ONE;
777+
cols.not_hint_multi_observe = if is_hint { F::ZERO } else { F::ONE };
775778
cols.very_first_timestamp = init_timestamp;
776779

777780
if i == 0 {
@@ -802,6 +805,7 @@ where
802805

803806
multi_observe_cols.start_idx = F::from_canonical_usize(chunk_start);
804807
multi_observe_cols.end_idx = F::from_canonical_usize(chunk_end);
808+
multi_observe_cols.chunk_ts_count = F::from_canonical_usize((chunk_end - chunk_start) * ts_per_element);
805809

806810
multi_observe_cols.is_first = F::ZERO;
807811
multi_observe_cols.is_last = if i == num_chunks - 1 { F::ONE } else { F::ZERO };

extensions/native/circuit/src/poseidon2/columns.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ pub struct NativePoseidon2Cols<T, const SBOX_REGISTERS: usize> {
3131
/// Indicates that this row is a multi_observe row.
3232
pub multi_observe_row: T,
3333

34+
/// Materialized column: multi_observe_row * (1 - is_hint).
35+
/// Lives in main cols (not overlaid specific) so it is 0 on non-multi_observe rows.
36+
pub not_hint_multi_observe: T,
37+
3438
/// Indicates the last row in an inside-row block.
3539
pub end_inside_row: T,
3640
/// Indicates the last row in a top-level block.
@@ -228,6 +232,8 @@ pub struct MultiObserveCols<T> {
228232
pub ctx: [T; 4],
229233
pub read_ctx: MemoryReadAuxCols<T>,
230234

235+
pub chunk_ts_count: T,
236+
231237
pub is_first: T,
232238
pub is_last: T,
233239
pub curr_len: T,

0 commit comments

Comments
 (0)