openvm_recursion_circuit/transcript/
poseidon2.rs1use core::borrow::Borrow;
2use std::{array::from_fn, sync::Arc};
3
4use openvm_circuit_primitives::ColumnsAir;
5use openvm_poseidon2_air::{
6 Poseidon2SubAir, Poseidon2SubCols, BABY_BEAR_POSEIDON2_HALF_FULL_ROUNDS,
7};
8use openvm_recursion_circuit_derive::AlignedBorrow;
9use openvm_stark_backend::{
10 air_builders::sub::SubAirBuilder, interaction::InteractionBuilder, BaseAirWithPublicValues,
11 PartitionedBaseAir,
12};
13use p3_air::{Air, AirBuilder, BaseAir};
14use p3_field::Field;
15use p3_matrix::Matrix;
16
17use crate::bus::{
18 Poseidon2CompressBus, Poseidon2CompressMessage, Poseidon2PermuteBus, Poseidon2PermuteMessage,
19};
20
21pub const CHUNK: usize = 8;
22pub use openvm_poseidon2_air::POSEIDON2_WIDTH;
23
24#[repr(C)]
25#[derive(AlignedBorrow)]
26pub struct Poseidon2Cols<T, const SBOX_REGISTERS: usize> {
27 pub inner: Poseidon2SubCols<T, SBOX_REGISTERS>,
28 pub permute_mult: T,
29 pub compress_mult: T,
30}
31
32pub struct Poseidon2Air<F: Field, const SBOX_REGISTERS: usize> {
33 pub subair: Arc<Poseidon2SubAir<F, SBOX_REGISTERS>>,
34 pub poseidon2_permute_bus: Poseidon2PermuteBus,
35 pub poseidon2_compress_bus: Poseidon2CompressBus,
36}
37
38impl<F: Field, const SBOX_REGISTERS: usize> ColumnsAir for Poseidon2Air<F, SBOX_REGISTERS> {}
41
42impl<F: Field, const SBOX_REGISTERS: usize> BaseAir<F> for Poseidon2Air<F, SBOX_REGISTERS> {
43 fn width(&self) -> usize {
44 Poseidon2Cols::<F, SBOX_REGISTERS>::width()
45 }
46}
47
48impl<F: Field, const SBOX_REGISTERS: usize> BaseAirWithPublicValues<F>
49 for Poseidon2Air<F, SBOX_REGISTERS>
50{
51}
52impl<F: Field, const SBOX_REGISTERS: usize> PartitionedBaseAir<F>
53 for Poseidon2Air<F, SBOX_REGISTERS>
54{
55}
56
57impl<AB: AirBuilder + InteractionBuilder, const SBOX_REGISTERS: usize> Air<AB>
58 for Poseidon2Air<AB::F, SBOX_REGISTERS>
59{
60 fn eval(&self, builder: &mut AB) {
61 let main = builder.main();
62 let local = main
63 .row_slice(0)
64 .expect("window should have at least one row");
65 let local: &Poseidon2Cols<AB::Var, SBOX_REGISTERS> = (*local).borrow();
66
67 let mut sub_builder =
68 SubAirBuilder::<AB, Poseidon2SubAir<AB::F, SBOX_REGISTERS>, AB::F>::new(
69 builder,
70 0..self.subair.width(),
71 );
72 self.subair.eval(&mut sub_builder);
73
74 self.poseidon2_permute_bus.add_key_with_lookups(
75 builder,
76 Poseidon2PermuteMessage {
77 input: local.inner.inputs,
78 output: local.inner.ending_full_rounds[BABY_BEAR_POSEIDON2_HALF_FULL_ROUNDS - 1]
79 .post,
80 },
81 local.permute_mult,
82 );
83
84 self.poseidon2_compress_bus.add_key_with_lookups(
85 builder,
86 Poseidon2CompressMessage {
87 input: local.inner.inputs,
88 output: from_fn(|i| {
89 local.inner.ending_full_rounds[BABY_BEAR_POSEIDON2_HALF_FULL_ROUNDS - 1].post[i]
90 }),
91 },
92 local.compress_mult,
93 );
94 }
95}