openvm_poseidon2_air/
permute.rs
1use 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)]
25pub struct BabyBearPoseidon2LinearLayers;
26
27impl<FA: FieldAlgebra> GenericPoseidon2LinearLayers<FA, WIDTH> for BabyBearPoseidon2LinearLayers {
32 fn internal_linear_layer(state: &mut [FA; WIDTH]) {
33 let diag_m1_matrix = &<BabyBearInternalLayerParameters as InternalLayerBaseParameters<
34 _,
35 16,
36 >>::INTERNAL_DIAG_MONTY;
37 assert_eq!(
38 TypeId::of::<FA::F>(),
39 TypeId::of::<BabyBear>(),
40 "BabyBear is the only supported field type"
41 );
42 let diag_m1_matrix =
43 unsafe { std::mem::transmute::<&[BabyBear; WIDTH], &[FA::F; WIDTH]>(diag_m1_matrix) };
44 babybear_internal_linear_layer(state, diag_m1_matrix);
45 }
46
47 fn external_linear_layer(state: &mut [FA; WIDTH]) {
48 mds_light_permutation(state, &MDSMat4);
49 }
50}
51
52#[derive(Debug, Derivative)]
59#[derivative(Clone)]
60pub struct Poseidon2InternalLayer<F: FieldAlgebra, LinearLayers> {
61 pub internal_constants: Vec<F>,
62 _marker: PhantomData<LinearLayers>,
63}
64
65impl<AF: FieldAlgebra, LinearLayers> InternalLayerConstructor<AF>
66 for Poseidon2InternalLayer<AF::F, LinearLayers>
67{
68 fn new_from_constants(internal_constants: Vec<AF::F>) -> Self {
69 Self {
70 internal_constants,
71 _marker: PhantomData,
72 }
73 }
74}
75
76impl<FA: FieldAlgebra, LinearLayers, const WIDTH: usize>
77 InternalLayer<FA, WIDTH, BABY_BEAR_POSEIDON2_SBOX_DEGREE>
78 for Poseidon2InternalLayer<FA::F, LinearLayers>
79where
80 LinearLayers: GenericPoseidon2LinearLayers<FA, WIDTH>,
81{
82 fn permute_state(&self, state: &mut [FA; WIDTH]) {
84 self.internal_constants.iter().for_each(|&rc| {
85 add_rc_and_sbox_generic::<_, BABY_BEAR_POSEIDON2_SBOX_DEGREE>(&mut state[0], rc);
86 LinearLayers::internal_linear_layer(state);
87 })
88 }
89}
90
91#[derive(Debug, Derivative)]
92#[derivative(Clone)]
93pub struct Poseidon2ExternalLayer<F: FieldAlgebra, LinearLayers, const WIDTH: usize> {
94 pub constants: ExternalLayerConstants<F, WIDTH>,
95 _marker: PhantomData<LinearLayers>,
96}
97
98impl<FA: FieldAlgebra, LinearLayers, const WIDTH: usize> ExternalLayerConstructor<FA, WIDTH>
99 for Poseidon2ExternalLayer<FA::F, LinearLayers, WIDTH>
100{
101 fn new_from_constants(external_layer_constants: ExternalLayerConstants<FA::F, WIDTH>) -> Self {
102 Self {
103 constants: external_layer_constants,
104 _marker: PhantomData,
105 }
106 }
107}
108
109impl<FA: FieldAlgebra, LinearLayers, const WIDTH: usize>
110 ExternalLayer<FA, WIDTH, BABY_BEAR_POSEIDON2_SBOX_DEGREE>
111 for Poseidon2ExternalLayer<FA::F, LinearLayers, WIDTH>
112where
113 LinearLayers: GenericPoseidon2LinearLayers<FA, WIDTH>,
114{
115 fn permute_state_initial(&self, state: &mut [FA; WIDTH]) {
116 LinearLayers::external_linear_layer(state);
117 external_permute_state::<FA, LinearLayers, WIDTH>(
118 state,
119 self.constants.get_initial_constants(),
120 );
121 }
122
123 fn permute_state_terminal(&self, state: &mut [FA; WIDTH]) {
124 external_permute_state::<FA, LinearLayers, WIDTH>(
125 state,
126 self.constants.get_terminal_constants(),
127 );
128 }
129}
130
131fn external_permute_state<FA: FieldAlgebra, LinearLayers, const WIDTH: usize>(
132 state: &mut [FA; WIDTH],
133 constants: &[[FA::F; WIDTH]],
134) where
135 LinearLayers: GenericPoseidon2LinearLayers<FA, WIDTH>,
136{
137 for elem in constants.iter() {
138 state.iter_mut().zip(elem.iter()).for_each(|(s, &rc)| {
139 add_rc_and_sbox_generic::<_, BABY_BEAR_POSEIDON2_SBOX_DEGREE>(s, rc)
140 });
141 LinearLayers::external_linear_layer(state);
142 }
143}