openvm_stark_sdk/config/
fri_params.rs

1use openvm_stark_backend::interaction::LogUpSecurityParameters;
2use serde::{Deserialize, Serialize};
3
4use crate::config::log_up_params::log_up_security_params_baby_bear_100_bits;
5
6#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
7pub struct FriParameters {
8    pub log_blowup: usize,
9    pub log_final_poly_len: usize,
10    pub num_queries: usize,
11    pub proof_of_work_bits: usize,
12}
13
14impl FriParameters {
15    /// Conjectured bits of security.
16    /// See ethSTARK paper (<https://eprint.iacr.org/2021/582.pdf>) section 5.10.1 equation (19)
17    ///
18    /// `challenge_field_bits` is the number of bits in the challenge field (extension field) of the STARK config.
19    pub fn get_conjectured_security_bits(&self, challenge_field_bits: usize) -> usize {
20        let fri_query_security_bits = self.num_queries * self.log_blowup + self.proof_of_work_bits;
21        // The paper says min(fri_field_bits, fri_query_security_bits) - 1 but plonky2 (https://github.com/0xPolygonZero/plonky2/blob/41dc325e61ab8d4c0491e68e667c35a4e8173ffa/starky/src/config.rs#L86C1-L87C1) omits the -1
22        challenge_field_bits.min(fri_query_security_bits)
23    }
24
25    pub fn standard_fast() -> Self {
26        standard_fri_params_with_100_bits_conjectured_security(1)
27    }
28
29    pub fn standard_with_100_bits_conjectured_security(log_blowup: usize) -> Self {
30        standard_fri_params_with_100_bits_conjectured_security(log_blowup)
31    }
32
33    pub fn max_constraint_degree(&self) -> usize {
34        (1 << self.log_blowup) + 1
35    }
36
37    /// New FRI parameters for testing usage with the specific `log_blowup`.
38    /// If the environment variable `OPENVM_FAST_TEST` is set to "1", then the parameters are **not secure** and meant for fast testing only.
39    ///
40    /// In production, use `Self::standard_with_100_bits_conjectured_security` instead.
41    pub fn new_for_testing(log_blowup: usize) -> Self {
42        if let Ok("1") = std::env::var("OPENVM_FAST_TEST").as_deref() {
43            Self {
44                log_blowup,
45                log_final_poly_len: 0,
46                num_queries: 2,
47                proof_of_work_bits: 0,
48            }
49        } else {
50            Self::standard_with_100_bits_conjectured_security(log_blowup)
51        }
52    }
53}
54
55/// Pre-defined FRI parameters with 100 bits of conjectured security.
56/// Security bits calculated following ethSTARK (<https://eprint.iacr.org/2021/582.pdf>) 5.10.1 eq (19)
57///
58/// Assumes that the challenge field used as more than 100 bits.
59pub fn standard_fri_params_with_100_bits_conjectured_security(log_blowup: usize) -> FriParameters {
60    let fri_params = match log_blowup {
61        // plonky2 standard fast config uses num_queries=84: https://github.com/0xPolygonZero/plonky2/blob/41dc325e61ab8d4c0491e68e667c35a4e8173ffa/starky/src/config.rs#L49
62        // plonky3's default is num_queries=100, so we will use that. See https://github.com/Plonky3/Plonky3/issues/380 for related security discussion.
63        1 => FriParameters {
64            log_blowup,
65            log_final_poly_len: 0,
66            num_queries: 100,
67            proof_of_work_bits: 16,
68        },
69        2 => FriParameters {
70            log_blowup,
71            log_final_poly_len: 0,
72            num_queries: 42,
73            proof_of_work_bits: 16,
74        },
75        // plonky2 standard recursion config: https://github.com/0xPolygonZero/plonky2/blob/41dc325e61ab8d4c0491e68e667c35a4e8173ffa/plonky2/src/plonk/circuit_data.rs#L101
76        3 => FriParameters {
77            log_blowup,
78            log_final_poly_len: 0,
79            num_queries: 28,
80            proof_of_work_bits: 16,
81        },
82        4 => FriParameters {
83            log_blowup,
84            log_final_poly_len: 0,
85            num_queries: 21,
86            proof_of_work_bits: 16,
87        },
88        _ => todo!("No standard FRI params defined for log blowup {log_blowup}",),
89    };
90    assert!(fri_params.get_conjectured_security_bits(100) >= 100);
91    tracing::info!("FRI parameters | log_blowup: {log_blowup:<2} | num_queries: {:<2} | proof_of_work_bits: {:<2}", fri_params.num_queries, fri_params.proof_of_work_bits);
92    fri_params
93}
94
95#[derive(Clone, Debug)]
96pub struct SecurityParameters {
97    pub fri_params: FriParameters,
98    pub log_up_params: LogUpSecurityParameters,
99}
100
101impl SecurityParameters {
102    pub fn standard_fast() -> Self {
103        Self {
104            fri_params: FriParameters::standard_fast(),
105            log_up_params: log_up_security_params_baby_bear_100_bits(),
106        }
107    }
108    pub fn standard_100_bits_with_fri_log_blowup(log_blowup: usize) -> Self {
109        Self {
110            fri_params: FriParameters::standard_with_100_bits_conjectured_security(log_blowup),
111            log_up_params: log_up_security_params_baby_bear_100_bits(),
112        }
113    }
114}