1#![allow(missing_docs)]
2
3use crate::{Com, StarkGenericConfig, ZeroCommitment};
4use p3_baby_bear::{BabyBear, DiffusionMatrixBabyBear};
5use p3_challenger::DuplexChallenger;
6use p3_commit::ExtensionMmcs;
7use p3_dft::Radix2DitParallel;
8use p3_field::{extension::BinomialExtensionField, AbstractField, Field};
9use p3_fri::{
10 BatchOpening, CommitPhaseProofStep, FriConfig, FriProof, QueryProof, TwoAdicFriPcs,
11 TwoAdicFriPcsProof,
12};
13use p3_merkle_tree::FieldMerkleTreeMmcs;
14use p3_poseidon2::{Poseidon2, Poseidon2ExternalMatrixGeneral};
15use p3_symmetric::{Hash, PaddingFreeSponge, TruncatedPermutation};
16use serde::{Deserialize, Serialize};
17use sp1_primitives::poseidon2_init;
18
19pub const DIGEST_SIZE: usize = 8;
20
21pub type InnerVal = BabyBear;
23pub type InnerChallenge = BinomialExtensionField<InnerVal, 4>;
24pub type InnerPerm =
25 Poseidon2<InnerVal, Poseidon2ExternalMatrixGeneral, DiffusionMatrixBabyBear, 16, 7>;
26pub type InnerHash = PaddingFreeSponge<InnerPerm, 16, 8, DIGEST_SIZE>;
27pub type InnerDigestHash = Hash<InnerVal, InnerVal, DIGEST_SIZE>;
28pub type InnerDigest = [InnerVal; DIGEST_SIZE];
29pub type InnerCompress = TruncatedPermutation<InnerPerm, 2, 8, 16>;
30pub type InnerValMmcs = FieldMerkleTreeMmcs<
31 <InnerVal as Field>::Packing,
32 <InnerVal as Field>::Packing,
33 InnerHash,
34 InnerCompress,
35 8,
36>;
37pub type InnerChallengeMmcs = ExtensionMmcs<InnerVal, InnerChallenge, InnerValMmcs>;
38pub type InnerChallenger = DuplexChallenger<InnerVal, InnerPerm, 16, 8>;
39pub type InnerDft = Radix2DitParallel;
40pub type InnerPcs = TwoAdicFriPcs<InnerVal, InnerDft, InnerValMmcs, InnerChallengeMmcs>;
41pub type InnerQueryProof = QueryProof<InnerChallenge, InnerChallengeMmcs>;
42pub type InnerCommitPhaseStep = CommitPhaseProofStep<InnerChallenge, InnerChallengeMmcs>;
43pub type InnerFriProof = FriProof<InnerChallenge, InnerChallengeMmcs, InnerVal>;
44pub type InnerBatchOpening = BatchOpening<InnerVal, InnerValMmcs>;
45pub type InnerPcsProof =
46 TwoAdicFriPcsProof<InnerVal, InnerChallenge, InnerValMmcs, InnerChallengeMmcs>;
47
48#[must_use]
50pub fn inner_perm() -> InnerPerm {
51 poseidon2_init()
52}
53
54#[must_use]
56pub fn sp1_fri_config() -> FriConfig<InnerChallengeMmcs> {
57 let perm = inner_perm();
58 let hash = InnerHash::new(perm.clone());
59 let compress = InnerCompress::new(perm.clone());
60 let challenge_mmcs = InnerChallengeMmcs::new(InnerValMmcs::new(hash, compress));
61 let num_queries = match std::env::var("FRI_QUERIES") {
62 Ok(value) => value.parse().unwrap(),
63 Err(_) => 100,
64 };
65 FriConfig { log_blowup: 1, num_queries, proof_of_work_bits: 16, mmcs: challenge_mmcs }
66}
67
68#[must_use]
70pub fn inner_fri_config() -> FriConfig<InnerChallengeMmcs> {
71 let perm = inner_perm();
72 let hash = InnerHash::new(perm.clone());
73 let compress = InnerCompress::new(perm.clone());
74 let challenge_mmcs = InnerChallengeMmcs::new(InnerValMmcs::new(hash, compress));
75 let num_queries = match std::env::var("FRI_QUERIES") {
76 Ok(value) => value.parse().unwrap(),
77 Err(_) => 100,
78 };
79 FriConfig { log_blowup: 1, num_queries, proof_of_work_bits: 16, mmcs: challenge_mmcs }
80}
81
82#[derive(Deserialize)]
84#[serde(from = "std::marker::PhantomData<BabyBearPoseidon2Inner>")]
85pub struct BabyBearPoseidon2Inner {
86 pub perm: InnerPerm,
87 pub pcs: InnerPcs,
88}
89
90impl Clone for BabyBearPoseidon2Inner {
91 fn clone(&self) -> Self {
92 Self::new()
93 }
94}
95
96impl Serialize for BabyBearPoseidon2Inner {
97 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
98 where
99 S: serde::Serializer,
100 {
101 std::marker::PhantomData::<BabyBearPoseidon2Inner>.serialize(serializer)
102 }
103}
104
105impl From<std::marker::PhantomData<BabyBearPoseidon2Inner>> for BabyBearPoseidon2Inner {
106 fn from(_: std::marker::PhantomData<BabyBearPoseidon2Inner>) -> Self {
107 Self::new()
108 }
109}
110
111impl BabyBearPoseidon2Inner {
112 #[must_use]
113 pub fn new() -> Self {
114 let perm = inner_perm();
115 let hash = InnerHash::new(perm.clone());
116 let compress = InnerCompress::new(perm.clone());
117 let val_mmcs = InnerValMmcs::new(hash, compress);
118 let dft = InnerDft {};
119 let fri_config = inner_fri_config();
120 let pcs = InnerPcs::new(27, dft, val_mmcs, fri_config);
121 Self { perm, pcs }
122 }
123}
124
125impl Default for BabyBearPoseidon2Inner {
126 fn default() -> Self {
127 Self::new()
128 }
129}
130
131impl StarkGenericConfig for BabyBearPoseidon2Inner {
132 type Val = InnerVal;
133 type Domain = <InnerPcs as p3_commit::Pcs<InnerChallenge, InnerChallenger>>::Domain;
134 type Pcs = InnerPcs;
135 type Challenge = InnerChallenge;
136 type Challenger = InnerChallenger;
137
138 fn pcs(&self) -> &Self::Pcs {
139 &self.pcs
140 }
141
142 fn challenger(&self) -> Self::Challenger {
143 InnerChallenger::new(self.perm.clone())
144 }
145}
146
147impl ZeroCommitment<BabyBearPoseidon2Inner> for InnerPcs {
148 fn zero_commitment(&self) -> Com<BabyBearPoseidon2Inner> {
149 InnerDigestHash::from([InnerVal::zero(); DIGEST_SIZE])
150 }
151}
152
153pub mod baby_bear_poseidon2 {
154
155 use p3_baby_bear::{BabyBear, DiffusionMatrixBabyBear};
156 use p3_challenger::DuplexChallenger;
157 use p3_commit::ExtensionMmcs;
158 use p3_dft::Radix2DitParallel;
159 use p3_field::{extension::BinomialExtensionField, AbstractField, Field};
160 use p3_fri::{FriConfig, TwoAdicFriPcs};
161 use p3_merkle_tree::FieldMerkleTreeMmcs;
162 use p3_poseidon2::{Poseidon2, Poseidon2ExternalMatrixGeneral};
163 use p3_symmetric::{Hash, PaddingFreeSponge, TruncatedPermutation};
164 use serde::{Deserialize, Serialize};
165 use sp1_primitives::RC_16_30;
166
167 use crate::{Com, StarkGenericConfig, ZeroCommitment, DIGEST_SIZE};
168
169 pub type Val = BabyBear;
170 pub type Challenge = BinomialExtensionField<Val, 4>;
171
172 pub type Perm = Poseidon2<Val, Poseidon2ExternalMatrixGeneral, DiffusionMatrixBabyBear, 16, 7>;
173 pub type MyHash = PaddingFreeSponge<Perm, 16, 8, DIGEST_SIZE>;
174 pub type DigestHash = Hash<Val, Val, DIGEST_SIZE>;
175 pub type MyCompress = TruncatedPermutation<Perm, 2, 8, 16>;
176 pub type ValMmcs = FieldMerkleTreeMmcs<
177 <Val as Field>::Packing,
178 <Val as Field>::Packing,
179 MyHash,
180 MyCompress,
181 8,
182 >;
183 pub type ChallengeMmcs = ExtensionMmcs<Val, Challenge, ValMmcs>;
184 pub type Dft = Radix2DitParallel;
185 pub type Challenger = DuplexChallenger<Val, Perm, 16, 8>;
186 type Pcs = TwoAdicFriPcs<Val, Dft, ValMmcs, ChallengeMmcs>;
187
188 #[must_use]
189 pub fn my_perm() -> Perm {
190 const ROUNDS_F: usize = 8;
191 const ROUNDS_P: usize = 13;
192 let mut round_constants = RC_16_30.to_vec();
193 let internal_start = ROUNDS_F / 2;
194 let internal_end = (ROUNDS_F / 2) + ROUNDS_P;
195 let internal_round_constants = round_constants
196 .drain(internal_start..internal_end)
197 .map(|vec| vec[0])
198 .collect::<Vec<_>>();
199 let external_round_constants = round_constants;
200 Perm::new(
201 ROUNDS_F,
202 external_round_constants,
203 Poseidon2ExternalMatrixGeneral,
204 ROUNDS_P,
205 internal_round_constants,
206 DiffusionMatrixBabyBear,
207 )
208 }
209
210 #[must_use]
211 pub fn default_fri_config() -> FriConfig<ChallengeMmcs> {
212 let perm = my_perm();
213 let hash = MyHash::new(perm.clone());
214 let compress = MyCompress::new(perm.clone());
215 let challenge_mmcs = ChallengeMmcs::new(ValMmcs::new(hash, compress));
216 let num_queries = match std::env::var("FRI_QUERIES") {
217 Ok(value) => value.parse().unwrap(),
218 Err(_) => 100,
219 };
220 FriConfig { log_blowup: 1, num_queries, proof_of_work_bits: 16, mmcs: challenge_mmcs }
221 }
222
223 #[must_use]
224 pub fn compressed_fri_config() -> FriConfig<ChallengeMmcs> {
225 let perm = my_perm();
226 let hash = MyHash::new(perm.clone());
227 let compress = MyCompress::new(perm.clone());
228 let challenge_mmcs = ChallengeMmcs::new(ValMmcs::new(hash, compress));
229 let num_queries = match std::env::var("FRI_QUERIES") {
230 Ok(value) => value.parse().unwrap(),
231 Err(_) => 50,
232 };
233 FriConfig { log_blowup: 2, num_queries, proof_of_work_bits: 16, mmcs: challenge_mmcs }
234 }
235
236 #[must_use]
237 pub fn ultra_compressed_fri_config() -> FriConfig<ChallengeMmcs> {
238 let perm = my_perm();
239 let hash = MyHash::new(perm.clone());
240 let compress = MyCompress::new(perm.clone());
241 let challenge_mmcs = ChallengeMmcs::new(ValMmcs::new(hash, compress));
242 let num_queries = match std::env::var("FRI_QUERIES") {
243 Ok(value) => value.parse().unwrap(),
244 Err(_) => 33,
245 };
246 FriConfig { log_blowup: 3, num_queries, proof_of_work_bits: 16, mmcs: challenge_mmcs }
247 }
248
249 enum BabyBearPoseidon2Type {
250 Default,
251 Compressed,
252 }
253
254 #[derive(Deserialize)]
255 #[serde(from = "std::marker::PhantomData<BabyBearPoseidon2>")]
256 pub struct BabyBearPoseidon2 {
257 pub perm: Perm,
258 pcs: Pcs,
259 config_type: BabyBearPoseidon2Type,
260 }
261
262 impl BabyBearPoseidon2 {
263 #[must_use]
264 pub fn new() -> Self {
265 let perm = my_perm();
266 let hash = MyHash::new(perm.clone());
267 let compress = MyCompress::new(perm.clone());
268 let val_mmcs = ValMmcs::new(hash, compress);
269 let dft = Dft {};
270 let fri_config = default_fri_config();
271 let pcs = Pcs::new(27, dft, val_mmcs, fri_config);
272 Self { pcs, perm, config_type: BabyBearPoseidon2Type::Default }
273 }
274
275 #[must_use]
276 pub fn compressed() -> Self {
277 let perm = my_perm();
278 let hash = MyHash::new(perm.clone());
279 let compress = MyCompress::new(perm.clone());
280 let val_mmcs = ValMmcs::new(hash, compress);
281 let dft = Dft {};
282 let fri_config = compressed_fri_config();
283 let pcs = Pcs::new(27, dft, val_mmcs, fri_config);
284 Self { pcs, perm, config_type: BabyBearPoseidon2Type::Compressed }
285 }
286
287 #[must_use]
288 pub fn ultra_compressed() -> Self {
289 let perm = my_perm();
290 let hash = MyHash::new(perm.clone());
291 let compress = MyCompress::new(perm.clone());
292 let val_mmcs = ValMmcs::new(hash, compress);
293 let dft = Dft {};
294 let fri_config = ultra_compressed_fri_config();
295 let pcs = Pcs::new(27, dft, val_mmcs, fri_config);
296 Self { pcs, perm, config_type: BabyBearPoseidon2Type::Compressed }
297 }
298 }
299
300 impl Clone for BabyBearPoseidon2 {
301 fn clone(&self) -> Self {
302 match self.config_type {
303 BabyBearPoseidon2Type::Default => Self::new(),
304 BabyBearPoseidon2Type::Compressed => Self::compressed(),
305 }
306 }
307 }
308
309 impl Default for BabyBearPoseidon2 {
310 fn default() -> Self {
311 Self::new()
312 }
313 }
314
315 impl Serialize for BabyBearPoseidon2 {
317 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
318 where
319 S: serde::Serializer,
320 {
321 std::marker::PhantomData::<BabyBearPoseidon2>.serialize(serializer)
322 }
323 }
324
325 impl From<std::marker::PhantomData<BabyBearPoseidon2>> for BabyBearPoseidon2 {
326 fn from(_: std::marker::PhantomData<BabyBearPoseidon2>) -> Self {
327 Self::new()
328 }
329 }
330
331 impl StarkGenericConfig for BabyBearPoseidon2 {
332 type Val = BabyBear;
333 type Domain = <Pcs as p3_commit::Pcs<Challenge, Challenger>>::Domain;
334 type Pcs = Pcs;
335 type Challenge = Challenge;
336 type Challenger = Challenger;
337
338 fn pcs(&self) -> &Self::Pcs {
339 &self.pcs
340 }
341
342 fn challenger(&self) -> Self::Challenger {
343 Challenger::new(self.perm.clone())
344 }
345 }
346
347 impl ZeroCommitment<BabyBearPoseidon2> for Pcs {
348 fn zero_commitment(&self) -> Com<BabyBearPoseidon2> {
349 DigestHash::from([Val::zero(); DIGEST_SIZE])
350 }
351 }
352}