openvm_poseidon2_air/
permute.rs1use std::{any::TypeId, marker::PhantomData};
2
3use derivative::Derivative;
4use openvm_stark_backend::p3_field::FieldAlgebra;
5use openvm_stark_sdk::p3_baby_bear::{BabyBear, BabyBearInternalLayerParameters};
6use p3_monty_31::InternalLayerBaseParameters;
7use p3_poseidon2::{
8 add_rc_and_sbox_generic, mds_light_permutation, ExternalLayer, ExternalLayerConstants,
9 ExternalLayerConstructor, GenericPoseidon2LinearLayers, InternalLayer,
10 InternalLayerConstructor, MDSMat4,
11};
12
13use super::{babybear_internal_linear_layer, BABY_BEAR_POSEIDON2_SBOX_DEGREE};
14
15const WIDTH: usize = crate::POSEIDON2_WIDTH;
16
17pub trait Poseidon2MatrixConfig: Clone + Sync {
18 fn int_diag_m1_matrix<F: FieldAlgebra>() -> [F; WIDTH];
19}
20
21#[derive(Debug, Clone)]
26pub struct BabyBearPoseidon2LinearLayers;
27
28impl<FA: FieldAlgebra> GenericPoseidon2LinearLayers<FA, WIDTH> for BabyBearPoseidon2LinearLayers {
34 fn internal_linear_layer(state: &mut [FA; WIDTH]) {
35 let diag_m1_matrix = &<BabyBearInternalLayerParameters as InternalLayerBaseParameters<
36 _,
37 16,
38 >>::INTERNAL_DIAG_MONTY;
39 assert_eq!(
40 TypeId::of::<FA::F>(),
41 TypeId::of::<BabyBear>(),
42 "BabyBear is the only supported field type"
43 );
44 let diag_m1_matrix =
46 unsafe { std::mem::transmute::<&[BabyBear; WIDTH], &[FA::F; WIDTH]>(diag_m1_matrix) };
47 babybear_internal_linear_layer(state, diag_m1_matrix);
48 }
49
50 fn external_linear_layer(state: &mut [FA; WIDTH]) {
51 mds_light_permutation(state, &MDSMat4);
52 }
53}
54
55#[derive(Debug, Derivative)]
62#[derivative(Clone)]
63pub struct Poseidon2InternalLayer<F: FieldAlgebra, LinearLayers> {
64 pub internal_constants: Vec<F>,
65 _marker: PhantomData<LinearLayers>,
66}
67
68impl<AF: FieldAlgebra, LinearLayers> InternalLayerConstructor<AF>
69 for Poseidon2InternalLayer<AF::F, LinearLayers>
70{
71 fn new_from_constants(internal_constants: Vec<AF::F>) -> Self {
72 Self {
73 internal_constants,
74 _marker: PhantomData,
75 }
76 }
77}
78
79impl<FA: FieldAlgebra, LinearLayers, const WIDTH: usize>
80 InternalLayer<FA, WIDTH, BABY_BEAR_POSEIDON2_SBOX_DEGREE>
81 for Poseidon2InternalLayer<FA::F, LinearLayers>
82where
83 LinearLayers: GenericPoseidon2LinearLayers<FA, WIDTH>,
84{
85 fn permute_state(&self, state: &mut [FA; WIDTH]) {
87 self.internal_constants.iter().for_each(|&rc| {
88 add_rc_and_sbox_generic::<_, BABY_BEAR_POSEIDON2_SBOX_DEGREE>(&mut state[0], rc);
89 LinearLayers::internal_linear_layer(state);
90 })
91 }
92}
93
94#[derive(Debug, Derivative)]
95#[derivative(Clone)]
96pub struct Poseidon2ExternalLayer<F: FieldAlgebra, LinearLayers, const WIDTH: usize> {
97 pub constants: ExternalLayerConstants<F, WIDTH>,
98 _marker: PhantomData<LinearLayers>,
99}
100
101impl<FA: FieldAlgebra, LinearLayers, const WIDTH: usize> ExternalLayerConstructor<FA, WIDTH>
102 for Poseidon2ExternalLayer<FA::F, LinearLayers, WIDTH>
103{
104 fn new_from_constants(external_layer_constants: ExternalLayerConstants<FA::F, WIDTH>) -> Self {
105 Self {
106 constants: external_layer_constants,
107 _marker: PhantomData,
108 }
109 }
110}
111
112impl<FA: FieldAlgebra, LinearLayers, const WIDTH: usize>
113 ExternalLayer<FA, WIDTH, BABY_BEAR_POSEIDON2_SBOX_DEGREE>
114 for Poseidon2ExternalLayer<FA::F, LinearLayers, WIDTH>
115where
116 LinearLayers: GenericPoseidon2LinearLayers<FA, WIDTH>,
117{
118 fn permute_state_initial(&self, state: &mut [FA; WIDTH]) {
119 LinearLayers::external_linear_layer(state);
120 external_permute_state::<FA, LinearLayers, WIDTH>(
121 state,
122 self.constants.get_initial_constants(),
123 );
124 }
125
126 fn permute_state_terminal(&self, state: &mut [FA; WIDTH]) {
127 external_permute_state::<FA, LinearLayers, WIDTH>(
128 state,
129 self.constants.get_terminal_constants(),
130 );
131 }
132}
133
134fn external_permute_state<FA: FieldAlgebra, LinearLayers, const WIDTH: usize>(
135 state: &mut [FA; WIDTH],
136 constants: &[[FA::F; WIDTH]],
137) where
138 LinearLayers: GenericPoseidon2LinearLayers<FA, WIDTH>,
139{
140 for elem in constants.iter() {
141 state.iter_mut().zip(elem.iter()).for_each(|(s, &rc)| {
142 add_rc_and_sbox_generic::<_, BABY_BEAR_POSEIDON2_SBOX_DEGREE>(s, rc)
143 });
144 LinearLayers::external_linear_layer(state);
145 }
146}