sp1_recursion_core/stark/
config.rs

1use p3_baby_bear::BabyBear;
2use p3_bn254_fr::{Bn254Fr, DiffusionMatrixBN254};
3use p3_challenger::MultiField32Challenger;
4use p3_commit::ExtensionMmcs;
5use p3_dft::Radix2DitParallel;
6use p3_field::{extension::BinomialExtensionField, AbstractField};
7use p3_fri::{
8    BatchOpening, CommitPhaseProofStep, FriConfig, FriProof, QueryProof, TwoAdicFriPcs,
9    TwoAdicFriPcsProof,
10};
11use p3_merkle_tree::FieldMerkleTreeMmcs;
12use p3_poseidon2::{Poseidon2, Poseidon2ExternalMatrixGeneral};
13use p3_symmetric::{Hash, MultiField32PaddingFreeSponge, TruncatedPermutation};
14use serde::{Deserialize, Serialize};
15use sp1_stark::{Com, StarkGenericConfig, ZeroCommitment};
16
17use super::{poseidon2::bn254_poseidon2_rc3, sp1_dev_mode};
18
19pub const DIGEST_SIZE: usize = 1;
20
21pub const OUTER_MULTI_FIELD_CHALLENGER_WIDTH: usize = 3;
22pub const OUTER_MULTI_FIELD_CHALLENGER_RATE: usize = 2;
23pub const OUTER_MULTI_FIELD_CHALLENGER_DIGEST_SIZE: usize = 1;
24
25/// A configuration for outer recursion.
26pub type OuterVal = BabyBear;
27pub type OuterChallenge = BinomialExtensionField<OuterVal, 4>;
28pub type OuterPerm = Poseidon2<Bn254Fr, Poseidon2ExternalMatrixGeneral, DiffusionMatrixBN254, 3, 5>;
29pub type OuterHash =
30    MultiField32PaddingFreeSponge<OuterVal, Bn254Fr, OuterPerm, 3, 16, DIGEST_SIZE>;
31pub type OuterDigestHash = Hash<OuterVal, Bn254Fr, DIGEST_SIZE>;
32pub type OuterDigest = [Bn254Fr; DIGEST_SIZE];
33pub type OuterCompress = TruncatedPermutation<OuterPerm, 2, 1, 3>;
34pub type OuterValMmcs = FieldMerkleTreeMmcs<BabyBear, Bn254Fr, OuterHash, OuterCompress, 1>;
35pub type OuterChallengeMmcs = ExtensionMmcs<OuterVal, OuterChallenge, OuterValMmcs>;
36pub type OuterDft = Radix2DitParallel;
37pub type OuterChallenger = MultiField32Challenger<
38    OuterVal,
39    Bn254Fr,
40    OuterPerm,
41    OUTER_MULTI_FIELD_CHALLENGER_WIDTH,
42    OUTER_MULTI_FIELD_CHALLENGER_RATE,
43>;
44pub type OuterPcs = TwoAdicFriPcs<OuterVal, OuterDft, OuterValMmcs, OuterChallengeMmcs>;
45
46pub type OuterQueryProof = QueryProof<OuterChallenge, OuterChallengeMmcs>;
47pub type OuterCommitPhaseStep = CommitPhaseProofStep<OuterChallenge, OuterChallengeMmcs>;
48pub type OuterFriProof = FriProof<OuterChallenge, OuterChallengeMmcs, OuterVal>;
49pub type OuterBatchOpening = BatchOpening<OuterVal, OuterValMmcs>;
50pub type OuterPcsProof =
51    TwoAdicFriPcsProof<OuterVal, OuterChallenge, OuterValMmcs, OuterChallengeMmcs>;
52
53/// The permutation for outer recursion.
54pub fn outer_perm() -> OuterPerm {
55    const ROUNDS_F: usize = 8;
56    const ROUNDS_P: usize = 56;
57    let mut round_constants = bn254_poseidon2_rc3();
58    let internal_start = ROUNDS_F / 2;
59    let internal_end = (ROUNDS_F / 2) + ROUNDS_P;
60    let internal_round_constants =
61        round_constants.drain(internal_start..internal_end).map(|vec| vec[0]).collect::<Vec<_>>();
62    let external_round_constants = round_constants;
63    OuterPerm::new(
64        ROUNDS_F,
65        external_round_constants,
66        Poseidon2ExternalMatrixGeneral,
67        ROUNDS_P,
68        internal_round_constants,
69        DiffusionMatrixBN254,
70    )
71}
72
73/// The FRI config for outer recursion.
74pub fn outer_fri_config() -> FriConfig<OuterChallengeMmcs> {
75    let perm = outer_perm();
76    let hash = OuterHash::new(perm.clone()).unwrap();
77    let compress = OuterCompress::new(perm.clone());
78    let challenge_mmcs = OuterChallengeMmcs::new(OuterValMmcs::new(hash, compress));
79    let num_queries = if sp1_dev_mode() {
80        1
81    } else {
82        match std::env::var("FRI_QUERIES") {
83            Ok(value) => value.parse().unwrap(),
84            Err(_) => 25,
85        }
86    };
87    FriConfig { log_blowup: 4, num_queries, proof_of_work_bits: 16, mmcs: challenge_mmcs }
88}
89
90/// The FRI config for outer recursion.
91pub fn outer_fri_config_with_blowup(log_blowup: usize) -> FriConfig<OuterChallengeMmcs> {
92    let perm = outer_perm();
93    let hash = OuterHash::new(perm.clone()).unwrap();
94    let compress = OuterCompress::new(perm.clone());
95    let challenge_mmcs = OuterChallengeMmcs::new(OuterValMmcs::new(hash, compress));
96    let num_queries = if sp1_dev_mode() {
97        1
98    } else {
99        match std::env::var("FRI_QUERIES") {
100            Ok(value) => value.parse().unwrap(),
101            Err(_) => 100 / log_blowup,
102        }
103    };
104    FriConfig { log_blowup, num_queries, proof_of_work_bits: 16, mmcs: challenge_mmcs }
105}
106
107#[derive(Deserialize)]
108#[serde(from = "std::marker::PhantomData<BabyBearPoseidon2Outer>")]
109pub struct BabyBearPoseidon2Outer {
110    pub perm: OuterPerm,
111    pub pcs: OuterPcs,
112}
113
114impl Clone for BabyBearPoseidon2Outer {
115    fn clone(&self) -> Self {
116        Self::new()
117    }
118}
119
120impl Serialize for BabyBearPoseidon2Outer {
121    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
122    where
123        S: serde::Serializer,
124    {
125        std::marker::PhantomData::<BabyBearPoseidon2Outer>.serialize(serializer)
126    }
127}
128
129impl From<std::marker::PhantomData<BabyBearPoseidon2Outer>> for BabyBearPoseidon2Outer {
130    fn from(_: std::marker::PhantomData<BabyBearPoseidon2Outer>) -> Self {
131        Self::new()
132    }
133}
134
135impl BabyBearPoseidon2Outer {
136    pub fn new() -> Self {
137        let perm = outer_perm();
138        let hash = OuterHash::new(perm.clone()).unwrap();
139        let compress = OuterCompress::new(perm.clone());
140        let val_mmcs = OuterValMmcs::new(hash, compress);
141        let dft = OuterDft {};
142        let fri_config = outer_fri_config();
143        let pcs = OuterPcs::new(27, dft, val_mmcs, fri_config);
144        Self { pcs, perm }
145    }
146    pub fn new_with_log_blowup(log_blowup: usize) -> Self {
147        let perm = outer_perm();
148        let hash = OuterHash::new(perm.clone()).unwrap();
149        let compress = OuterCompress::new(perm.clone());
150        let val_mmcs = OuterValMmcs::new(hash, compress);
151        let dft = OuterDft {};
152        let fri_config = outer_fri_config_with_blowup(log_blowup);
153        let pcs = OuterPcs::new(27, dft, val_mmcs, fri_config);
154        Self { pcs, perm }
155    }
156}
157
158impl Default for BabyBearPoseidon2Outer {
159    fn default() -> Self {
160        Self::new()
161    }
162}
163
164impl StarkGenericConfig for BabyBearPoseidon2Outer {
165    type Val = OuterVal;
166    type Domain = <OuterPcs as p3_commit::Pcs<OuterChallenge, OuterChallenger>>::Domain;
167    type Pcs = OuterPcs;
168    type Challenge = OuterChallenge;
169    type Challenger = OuterChallenger;
170
171    fn pcs(&self) -> &Self::Pcs {
172        &self.pcs
173    }
174
175    fn challenger(&self) -> Self::Challenger {
176        OuterChallenger::new(self.perm.clone()).unwrap()
177    }
178}
179
180impl ZeroCommitment<BabyBearPoseidon2Outer> for OuterPcs {
181    fn zero_commitment(&self) -> Com<BabyBearPoseidon2Outer> {
182        OuterDigestHash::from([Bn254Fr::zero(); DIGEST_SIZE])
183    }
184}
185
186/// The FRI config for testing recursion.
187pub fn test_fri_config() -> FriConfig<OuterChallengeMmcs> {
188    let perm = outer_perm();
189    let hash = OuterHash::new(perm.clone()).unwrap();
190    let compress = OuterCompress::new(perm.clone());
191    let challenge_mmcs = OuterChallengeMmcs::new(OuterValMmcs::new(hash, compress));
192    FriConfig { log_blowup: 1, num_queries: 1, proof_of_work_bits: 1, mmcs: challenge_mmcs }
193}