openvm_poseidon2_air/
lib.rsuse std::sync::Arc;
use openvm_stark_backend::{
p3_field::{Field, PrimeField},
p3_matrix::dense::RowMajorMatrix,
};
pub use openvm_stark_sdk::p3_baby_bear;
pub use p3_poseidon2;
use p3_poseidon2::Poseidon2;
use p3_poseidon2_air::generate_trace_rows;
pub use p3_poseidon2_air::{self, Poseidon2Air};
pub use p3_symmetric::{self, Permutation};
mod air;
mod babybear;
mod config;
mod permute;
pub use air::*;
pub use babybear::*;
pub use config::*;
pub use permute::*;
#[cfg(test)]
mod tests;
pub const POSEIDON2_WIDTH: usize = 16;
pub const BABY_BEAR_POSEIDON2_HALF_FULL_ROUNDS: usize = 4;
pub const BABY_BEAR_POSEIDON2_FULL_ROUNDS: usize = 8;
pub const BABY_BEAR_POSEIDON2_PARTIAL_ROUNDS: usize = 13;
pub const BABY_BEAR_POSEIDON2_SBOX_DEGREE: u64 = 7;
#[derive(Debug)]
pub struct Poseidon2SubChip<F: Field, const SBOX_REGISTERS: usize> {
pub air: Arc<Poseidon2SubAir<F, SBOX_REGISTERS>>,
pub(crate) executor: Poseidon2Executor<F>,
pub(crate) constants: Plonky3RoundConstants<F>,
}
impl<F: PrimeField, const SBOX_REGISTERS: usize> Poseidon2SubChip<F, SBOX_REGISTERS> {
pub fn new(config: Poseidon2Config<F>) -> Self {
Self {
air: Arc::new(Poseidon2SubAir::new(config.constants.to_round_constants())),
executor: Poseidon2Executor::new(config.constants),
constants: config.constants.to_round_constants(),
}
}
pub fn permute(&self, input_state: [F; POSEIDON2_WIDTH]) -> [F; POSEIDON2_WIDTH] {
match &self.executor {
Poseidon2Executor::BabyBearMds(permuter) => permuter.permute(input_state),
}
}
pub fn permute_mut(&self, input_state: &mut [F; POSEIDON2_WIDTH]) {
match &self.executor {
Poseidon2Executor::BabyBearMds(permuter) => permuter.permute_mut(input_state),
};
}
pub fn generate_trace(&self, inputs: Vec<[F; POSEIDON2_WIDTH]>) -> RowMajorMatrix<F>
where
F: PrimeField,
{
match self.air.as_ref() {
Poseidon2SubAir::BabyBearMds(_) => generate_trace_rows::<
F,
BabyBearPoseidon2LinearLayers,
POSEIDON2_WIDTH,
BABY_BEAR_POSEIDON2_SBOX_DEGREE,
SBOX_REGISTERS,
BABY_BEAR_POSEIDON2_HALF_FULL_ROUNDS,
BABY_BEAR_POSEIDON2_PARTIAL_ROUNDS,
>(inputs, &self.constants),
}
}
}
pub fn from_config<F: PrimeField, const SBOX_REGISTERS: usize>(
config: Poseidon2Config<F>,
) -> (Poseidon2SubAir<F, SBOX_REGISTERS>, Poseidon2Executor<F>) {
(
Poseidon2SubAir::new(config.constants.to_round_constants()),
Poseidon2Executor::new(config.constants),
)
}
#[derive(Clone, Debug)]
pub enum Poseidon2Executor<F: Field> {
BabyBearMds(Plonky3Poseidon2Executor<F, BabyBearPoseidon2LinearLayers>),
}
impl<F: PrimeField> Poseidon2Executor<F> {
pub fn new(constants: Poseidon2Constants<F>) -> Self {
let (external_constants, internal_constants) = constants.to_external_internal_constants();
Self::BabyBearMds(Plonky3Poseidon2Executor::new(
external_constants,
internal_constants,
))
}
}
pub type Plonky3Poseidon2Executor<F, LinearLayers> = Poseidon2<
<F as Field>::Packing,
Poseidon2ExternalLayer<F, LinearLayers, POSEIDON2_WIDTH>,
Poseidon2InternalLayer<F, LinearLayers>,
POSEIDON2_WIDTH,
BABY_BEAR_POSEIDON2_SBOX_DEGREE,
>;