labrador/core/
env_params.rs

1use crate::ring::zq::Zq;
2
3// Example Environment parameters used for LaBRADOR, can be expanded as required by testing.
4#[derive(Clone)]
5pub struct EnvironmentParameters {
6    /// Relation R Parameters
7    pub n: usize, // rank (size of each witness s_i)
8    pub r: usize, // multiplicity (number of witness elements)
9
10    /// Decomposition Parameters
11    pub b: Zq, // z decomposition base
12    pub b_1: Zq,    // t_i decomposition base
13    pub t_1: usize, // t_i number of parts
14    pub b_2: Zq,    // g_ij decomposition base
15    pub t_2: usize, // g_ij number of parts
16
17    /// Norm Bounds
18    pub beta: Zq, // Bound for witness s_i
19    pub gamma: Zq,   // Bound for z
20    pub gamma_1: Zq, // Bound for t
21    pub gamma_2: Zq, // Bound for g and h
22
23    /// Commitment Matrices Sizes
24    pub kappa: usize, // Number of rows in A
25    pub kappa_1: usize, // Number of rows in B
26    pub kappa_2: usize, // Number of rows in C
27
28    /// Security Parameter
29    pub lambda: usize, // security parameter
30
31    /// Function Families Sizes
32    pub constraint_k: usize, // Number of constraints of the form f
33    pub constraint_l: usize, // Number of constraints of the form f'
34
35    /// Other Parameters
36    pub log_q: usize, // Size of log(q) in bits, where q is the modulo
37}
38
39#[allow(clippy::too_many_arguments)]
40impl EnvironmentParameters {
41    pub fn new(
42        n: usize,
43        r: usize,
44        b: Zq,
45        b_1: Zq,
46        t_1: usize,
47        b_2: Zq,
48        t_2: usize,
49        beta: Zq,
50        gamma: Zq,
51        gamma_1: Zq,
52        gamma_2: Zq,
53        kappa: usize,
54        kappa_1: usize,
55        kappa_2: usize,
56        lambda: usize,
57        constraint_k: usize,
58        constraint_l: usize,
59        log_q: usize,
60    ) -> Self {
61        Self {
62            n,
63            r,
64            b,
65            b_1,
66            t_1,
67            b_2,
68            t_2,
69            beta,
70            gamma,
71            gamma_1,
72            gamma_2,
73            kappa,
74            kappa_1,
75            kappa_2,
76            lambda,
77            constraint_k,
78            constraint_l,
79            log_q,
80        }
81    }
82}
83
84impl Default for EnvironmentParameters {
85    fn default() -> Self {
86        Self {
87            n: 5,
88            r: 3,
89            b: Zq::new(2),
90            b_1: Zq::new(16),
91            t_1: 4,
92            b_2: Zq::new(16),
93            t_2: 4,
94            beta: Zq::new(65535),
95            gamma: Zq::new(16),
96            gamma_1: Zq::new(16),
97            gamma_2: Zq::new(16),
98            kappa: 4,
99            kappa_1: 5,
100            kappa_2: 5,
101            lambda: 128,
102            constraint_k: 5,
103            constraint_l: 5,
104            log_q: 32,
105        }
106    }
107}
108
109// Todo: Revise and complete the following functionality
110// /// Calculate optimal decomposition parameters based on Section 5.4 of the paper
111// #[allow(clippy::as_conversions)]
112// pub fn calculate_optimal_parameters(
113//     n: usize,  // Dimension of the witness vector
114//     s: f64,    // Standard deviation of witness coefficients
115//     beta: f64, // Ajtai commitment parameter
116// ) -> GarbageParameters {
117//     // Calculate estimated standard deviations based on Section 5.4
118//     // For g_{ij}, std dev is approximately s_g = sqrt(n*d) * s^2
119//     // For h_{ij}, std dev is approximately s_h = beta * sqrt(n*d) * s
120//     let n_d_sqrt = (n * d) as f64;
121//     let s_g = n_d_sqrt * s * s;
122//     let s_h = beta * n_d_sqrt * s;
123
124//     // Calculate optimal bases using formula from Section 5.4
125//     // B_i ≈ sqrt(12 * s_i)
126//     let b2 = ((12.0 * s_g).sqrt() as u32).max(2);
127//     let b1 = ((12.0 * s_h).sqrt() as u32).max(2);
128
129//     // Calculate optimal number of parts
130//     // t_i ≈ log_B_i(q)
131//     let t2 = ((32.0 / (b2 as f64).log2()).ceil() as usize).max(2);
132//     let t1 = ((32.0 / (b1 as f64).log2()).ceil() as usize).max(2);
133
134//     GarbageParameters {
135//         g_base: Zq::new(b2),
136//         g_parts: t2,
137//         h_base: Zq::new(b1),
138//         h_parts: t1,
139//     }
140// }
141
142// #[test]
143// #[allow(clippy::as_conversions)]
144// fn test_optimal_parameters_accuracy() {
145//     // Choose small, simple values for manual calculation
146//     let n = 4; // Small dimension
147//     let d = 4; // Small degree
148//     let s = 2.0; // Simple standard deviation
149//     let beta = 1.0; // Simple beta value
150
151//     // Manually calculate the expected values according to the paper's formulas
152//     let n_d_sqrt = (n * d) as f64; // = 4.0
153
154//     // s_g = sqrt(n*d) * s^2 = 4.0 * 4.0 = 16.0
155//     let s_g = n_d_sqrt * s * s;
156
157//     // s_h = beta * sqrt(n*d) * s = 1.0 * 4.0 * 2.0 = 8.0
158//     let s_h = beta * n_d_sqrt * s;
159
160//     // b2 ≈ sqrt(12 * s_g) = sqrt(12 * 16.0) = sqrt(192) ≈ 13.856... => 13
161//     let expected_b2 = (12.0 * s_g).sqrt() as u32;
162
163//     // b1 ≈ sqrt(12 * s_h) = sqrt(12 * 8.0) = sqrt(96) ≈ 9.798... => 9
164//     let expected_b1 = (12.0 * s_h).sqrt() as u32;
165
166//     // For q = 2^32:
167//     // t2 ≈ log_b2(q) = log_13(2^32) = 32/log_2(13) ≈ 32/3.7 ≈ 8.65 => 9
168//     let expected_t2 = ((32.0 / (expected_b2 as f64).log2()).ceil() as usize).max(2);
169
170//     // t1 ≈ log_b1(q) = log_9(2^32) = 32/log_2(9) ≈ 32/3.17 ≈ 10.09 => 11
171//     let expected_t1 = ((32.0 / (expected_b1 as f64).log2()).ceil() as usize).max(2);
172
173//     // Call the function under test
174//     let params =
175//         GarbagePolynomialCommitment::<TEST_M, TEST_N, TEST_D>::calculate_optimal_parameters(
176//             n, d, s, beta,
177//         );
178
179//     // Check results
180//     assert!(
181//         params.g_base.to_u128() >= expected_b2 as u128 - 1
182//             && params.g_base.to_u128() <= expected_b2 as u128 + 1,
183//         "g_base {}, expected {}",
184//         params.g_base.to_u128(),
185//         expected_b2
186//     );
187
188//     assert!(
189//         params.h_base.to_u128() >= expected_b1 as u128 - 1
190//             && params.h_base.to_u128() <= expected_b1 as u128 + 1,
191//         "h_base {}, expected {}",
192//         params.h_base.to_u128(),
193//         expected_b1
194//     );
195
196//     // For part counts, use approximate comparison due to potential floating point differences
197//     assert!(
198//         params.g_parts >= expected_t2 - 1 && params.g_parts <= expected_t2 + 1,
199//         "g_parts {}, expected {}",
200//         params.g_parts,
201//         expected_t2
202//     );
203
204//     assert!(
205//         params.h_parts >= expected_t1 - 1 && params.h_parts <= expected_t1 + 1,
206//         "h_parts {}, expected {}",
207//         params.h_parts,
208//         expected_t1
209//     );
210// }