Skip to content

Commit 9e14e5d

Browse files
committed
fix that multi_observe works as observe_slice
1 parent 57316aa commit 9e14e5d

4 files changed

Lines changed: 35 additions & 27 deletions

File tree

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,7 @@ unsafe fn execute_multi_observe_e12_impl<
614614
pos += len;
615615
}
616616
}
617+
let final_idx = observation_chunks.last().map(|(_, end)| *end % CHUNK);
617618

618619
height += 1;
619620
let mut input_idx = 0;
@@ -632,6 +633,13 @@ unsafe fn execute_multi_observe_e12_impl<
632633

633634
height += 1;
634635
}
636+
if let Some(final_idx) = final_idx {
637+
exec_state.vm_write::<F, 1>(
638+
NATIVE_AS,
639+
pre_compute.init_pos_register,
640+
&[F::from_canonical_usize(final_idx)],
641+
);
642+
}
635643
*pc = pc.wrapping_add(DEFAULT_PC_STEP);
636644
*instret += 1;
637645

extensions/native/compiler/src/ir/poseidon.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ impl<C: Config> Builder<C> {
4242
len.clone(),
4343
));
4444

45+
// automatically updated by Poseidon2MultiObserve operation
4546
Usize::Var(init_pos)
4647
}
4748
},

extensions/native/recursion/src/challenger/duplex.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,22 @@ impl<C: Config> DuplexChallengerVariable<C> {
7777
}
7878
}
7979

80+
// Observes multiple elements from an array.
81+
// This is equivalent to calling `observe` multiple times, but more efficient.
82+
pub fn observe_slice_opt(&self, builder: &mut Builder<C>, arr: &Array<C, Felt<C::F>>) {
83+
let next_pos = builder.poseidon2_multi_observe(&self.sponge_state, self.input_ptr, &arr);
84+
85+
builder.assign(&self.input_ptr, self.io_empty_ptr + next_pos.clone());
86+
builder.if_ne(next_pos, Usize::from(0)).then_or_else(
87+
|builder| {
88+
builder.assign(&self.output_ptr, self.io_empty_ptr);
89+
},
90+
|builder| {
91+
builder.assign(&self.output_ptr, self.io_full_ptr);
92+
},
93+
);
94+
}
95+
8096
fn sample(&self, builder: &mut Builder<C>) -> Felt<C::F> {
8197
builder
8298
.if_ne(self.input_ptr.address, self.io_empty_ptr.address)

extensions/native/recursion/tests/recursion.rs

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@ use openvm_native_compiler::{
1515
asm::{AsmBuilder, AsmCompiler},
1616
conversion::{convert_program, CompilerOptions},
1717
ir::{Array, Builder, Config, Felt},
18-
prelude::Usize,
1918
};
2019
use openvm_native_recursion::{
21-
challenger::{duplex::DuplexChallengerVariable, CanObserveVariable},
20+
challenger::{duplex::DuplexChallengerVariable, CanObserveVariable, CanSampleVariable},
2221
testing_utils::inner::run_recursive_test,
2322
};
2423
use openvm_stark_backend::{
@@ -232,17 +231,12 @@ fn test_multi_observe() {
232231
}
233232

234233
fn build_test_program<C: Config>(builder: &mut Builder<C>) {
235-
let sample_lens: Vec<usize> = vec![10, 2, 1, 3, 20];
234+
let sample_lens: Vec<usize> = vec![10];
236235

237236
let mut rng = create_seeded_rng();
238-
let mut challenger = DuplexChallengerVariable::new(builder);
239237

240-
// Observe a setup label
241-
let label_f: Vec<u64> = vec![128, 3098, 192, 394, 1662, 928, 374, 281, 598, 182, 475, 729];
242-
for n in label_f {
243-
let f: Felt<C::F> = builder.constant(C::F::from_canonical_u64(n));
244-
challenger.observe(builder, f);
245-
}
238+
let mut c1 = DuplexChallengerVariable::new(builder);
239+
let mut c2 = DuplexChallengerVariable::new(builder);
246240

247241
for l in sample_lens {
248242
let sample_input: Array<C, Felt<C::F>> = builder.dyn_array(l);
@@ -251,24 +245,13 @@ fn build_test_program<C: Config>(builder: &mut Builder<C>) {
251245
builder.set(&sample_input, idx_vec[0], C::F::from_canonical_u32(f_u32));
252246
});
253247

254-
let next_input_ptr = builder.poseidon2_multi_observe(
255-
&challenger.sponge_state,
256-
challenger.input_ptr,
257-
&sample_input,
258-
);
248+
c1.observe_slice_opt(builder, &sample_input);
249+
c2.observe_slice(builder, sample_input);
250+
251+
let e1 = c1.sample(builder);
252+
let e2 = c2.sample(builder);
259253

260-
builder.assign(
261-
&challenger.input_ptr,
262-
challenger.io_empty_ptr + next_input_ptr.clone(),
263-
);
264-
builder.if_ne(next_input_ptr, Usize::from(0)).then_or_else(
265-
|builder| {
266-
builder.assign(&challenger.output_ptr, challenger.io_empty_ptr);
267-
},
268-
|builder| {
269-
builder.assign(&challenger.output_ptr, challenger.io_full_ptr);
270-
},
271-
);
254+
builder.assert_felt_eq(e1, e2);
272255
}
273256
builder.halt();
274257
}

0 commit comments

Comments
 (0)