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