1use super::utils::SprsMat;
2use super::BrakedownPCParams;
3use super::LinCodeParametersInfo;
4use crate::linear_codes::utils::calculate_t;
5use crate::utils::ceil_div;
6use crate::utils::{ceil_mul, ent};
7use crate::{PCCommitterKey, PCUniversalParams, PCVerifierKey};
8
9use ark_crypto_primitives::crh::{CRHScheme, TwoToOneCRHScheme};
10use ark_crypto_primitives::merkle_tree::{Config, LeafParam, TwoToOneParam};
11use ark_ff::PrimeField;
12use ark_std::log2;
13use ark_std::rand::RngCore;
14use ark_std::vec::Vec;
15#[cfg(all(not(feature = "std"), target_arch = "aarch64"))]
16use num_traits::Float;
17
18impl<F, C, H> PCUniversalParams for BrakedownPCParams<F, C, H>
19where
20 F: PrimeField,
21 C: Config,
22 H: CRHScheme,
23{
24 fn max_degree(&self) -> usize {
25 usize::MAX
26 }
27}
28
29impl<F, C, H> PCCommitterKey for BrakedownPCParams<F, C, H>
30where
31 F: PrimeField,
32 C: Config,
33 H: CRHScheme,
34{
35 fn max_degree(&self) -> usize {
36 usize::MAX
37 }
38
39 fn supported_degree(&self) -> usize {
40 <BrakedownPCParams<F, C, H> as PCCommitterKey>::max_degree(self)
41 }
42}
43
44impl<F, C, H> PCVerifierKey for BrakedownPCParams<F, C, H>
45where
46 F: PrimeField,
47 C: Config,
48 H: CRHScheme,
49{
50 fn max_degree(&self) -> usize {
51 usize::MAX
52 }
53
54 fn supported_degree(&self) -> usize {
55 <BrakedownPCParams<F, C, H> as PCVerifierKey>::max_degree(self)
56 }
57}
58
59impl<F, C, H> LinCodeParametersInfo<C, H> for BrakedownPCParams<F, C, H>
60where
61 F: PrimeField,
62 C: Config,
63 H: CRHScheme,
64{
65 fn check_well_formedness(&self) -> bool {
66 self.check_well_formedness
67 }
68
69 fn distance(&self) -> (usize, usize) {
70 (self.rho_inv.1 * self.beta.0, self.rho_inv.0 * self.beta.1)
71 }
72
73 fn sec_param(&self) -> usize {
74 self.sec_param
75 }
76
77 fn compute_dimensions(&self, _n: usize) -> (usize, usize) {
78 (self.n, self.m)
79 }
80
81 fn leaf_hash_param(&self) -> &<<C as Config>::LeafHash as CRHScheme>::Parameters {
82 &self.leaf_hash_param
83 }
84
85 fn two_to_one_hash_param(
86 &self,
87 ) -> &<<C as Config>::TwoToOneHash as TwoToOneCRHScheme>::Parameters {
88 &self.two_to_one_hash_param
89 }
90
91 fn col_hash_params(&self) -> &<H as CRHScheme>::Parameters {
92 &self.col_hash_params
93 }
94}
95
96impl<F, C, H> BrakedownPCParams<F, C, H>
97where
98 F: PrimeField,
99 C: Config,
100 H: CRHScheme,
101{
102 pub fn default<R: RngCore>(
104 rng: &mut R,
105 poly_len: usize,
106 check_well_formedness: bool,
107 leaf_hash_param: LeafParam<C>,
108 two_to_one_hash_param: TwoToOneParam<C>,
109 col_hash_params: H::Parameters,
110 ) -> Self {
111 let sec_param = 128;
112 let a = (178, 1000);
113 let b = (61, 1000);
114 let r = (1521, 1000);
115 let base_len = 30;
116 let t = calculate_t::<F>(sec_param, (b.0 * r.1, b.1 * r.0), poly_len).unwrap(); let n = 1 << log2((ceil_div(2 * poly_len, t) as f64).sqrt().ceil() as usize);
118 let m = ceil_div(poly_len, n);
119 let c = Self::cn_const(a, b);
120 let d = Self::dn_const(a, b, r);
121 let ct = Constants { a, b, r, c, d };
122 let (a_dims, b_dims) = Self::mat_size(m, base_len, &ct);
123 let a_mats = Self::make_all(rng, &a_dims);
124 let b_mats = Self::make_all(rng, &b_dims);
125
126 Self::new(
127 sec_param,
128 a,
129 b,
130 r,
131 base_len,
132 n,
133 m,
134 a_dims,
135 b_dims,
136 a_mats,
137 b_mats,
138 check_well_formedness,
139 leaf_hash_param,
140 two_to_one_hash_param,
141 col_hash_params,
142 )
143 }
144
145 pub fn new(
147 sec_param: usize,
148 a: (usize, usize),
149 b: (usize, usize),
150 r: (usize, usize),
151 base_len: usize,
152 n: usize,
153 m: usize,
154 a_dims: Vec<(usize, usize, usize)>,
155 b_dims: Vec<(usize, usize, usize)>,
156 a_mats: Vec<SprsMat<F>>,
157 b_mats: Vec<SprsMat<F>>,
158 check_well_formedness: bool,
159 leaf_hash_param: LeafParam<C>,
160 two_to_one_hash_param: TwoToOneParam<C>,
161 col_hash_params: H::Parameters,
162 ) -> Self {
163 let m_ext = if a_dims.is_empty() {
164 ceil_mul(m, r)
165 } else {
166 Self::codeword_len(&a_dims, &b_dims)
167 };
168 let start = a_dims
169 .iter()
170 .scan(0, |acc, &(row, _, _)| {
171 *acc += row;
172 Some(*acc)
173 })
174 .collect::<Vec<_>>();
175 let end = b_dims
176 .iter()
177 .scan(m_ext, |acc, &(_, col, _)| {
178 *acc -= col;
179 Some(*acc)
180 })
181 .collect::<Vec<_>>();
182
183 Self {
184 sec_param,
185 alpha: a,
186 beta: b,
187 rho_inv: r,
188 base_len,
189 n,
190 m,
191 m_ext,
192 a_dims,
193 b_dims,
194 start,
195 end,
196 a_mats,
197 b_mats,
198 check_well_formedness,
199 leaf_hash_param,
200 two_to_one_hash_param,
201 col_hash_params,
202 }
203 }
204 fn mu(a: (usize, usize), r: (usize, usize)) -> f64 {
206 let nom = r.0 * (a.1 - a.0) - r.1 * a.1;
207 let den = r.1 * a.1;
208 nom as f64 / den as f64
209 }
210 fn nu(a: (usize, usize), b: (usize, usize)) -> f64 {
212 let c = (3usize, 100usize);
213 let nom = b.0 * (a.1 + a.0) * c.1 + c.0 * b.1 * a.1;
214 let den = b.1 * a.1 * c.1;
215 nom as f64 / den as f64
216 }
217 fn cn_const(a: (usize, usize), b: (usize, usize)) -> (f64, f64) {
219 let a = div(a);
220 let b = div(b);
221 let arg = 1.28 * b / a;
222 let nom = ent(b) + a * ent(arg);
223 let den = -b * arg.log2();
224 (nom, den)
225 }
226 fn cn(n: usize, ct: &Constants) -> usize {
228 use ark_std::cmp::{max, min};
229 let b = ct.b;
230 let c = ct.c;
231 min(
232 max(ceil_mul(n, (32 * b.0, 25 * b.1)), 4 + ceil_mul(n, b)),
233 ((110f64 / (n as f64) + c.0) / c.1).ceil() as usize,
234 )
235 }
236 fn dn_const(a: (usize, usize), b: (usize, usize), r: (usize, usize)) -> (f64, f64) {
238 let m = Self::mu(a, r);
239 let n = Self::nu(a, b);
240 let a = div(a);
241 let b = div(b);
242 let r = div(r);
243 let nm = n / m;
244 let nom = r * a * ent(b / r) + m * ent(nm);
245 let den = -a * b * nm.log2();
246 (nom, den)
247 }
248 fn dn(n: usize, ct: &Constants) -> usize {
250 use ark_std::cmp::min;
251 let b = ct.b;
252 let r = ct.r;
253 let d = ct.d;
254 min(
255 ceil_mul(n, (2 * b.0, b.1))
256 + ((ceil_mul(n, r) - n + 110) as f64 / F::MODULUS_BIT_SIZE as f64).ceil() as usize, ((110f64 / (n as f64) + d.0) / d.1).ceil() as usize,
258 )
259 }
260 fn mat_size(
261 mut n: usize,
262 base_len: usize,
263 ct: &Constants,
264 ) -> (Vec<(usize, usize, usize)>, Vec<(usize, usize, usize)>) {
265 let mut a_dims: Vec<(usize, usize, usize)> = Vec::default();
266 let a = ct.a;
267 let r = ct.r;
268
269 while n >= base_len {
270 let m = ceil_mul(n, a);
271 let cn = Self::cn(n, ct);
272 let cn = if cn < m { cn } else { m }; a_dims.push((n, m, cn));
274 n = m;
275 }
276
277 let b_dims = a_dims
278 .iter()
279 .map(|&(an, am, _)| {
280 let n = ceil_mul(am, r);
281 let m = ceil_mul(an, r) - an - n;
282 let dn = Self::dn(n, ct);
283 let dn = if dn < m { dn } else { m }; (n, m, dn)
285 })
286 .collect::<Vec<_>>();
287 (a_dims, b_dims)
288 }
289
290 pub(crate) fn codeword_len(
293 a_dims: &[(usize, usize, usize)],
294 b_dims: &[(usize, usize, usize)],
295 ) -> usize {
296 b_dims.iter().map(|(_, col, _)| col).sum::<usize>() + a_dims.iter().map(|(row, _, _)| row).sum::<usize>() + b_dims.last().unwrap().0 }
300
301 fn make_mat<R: RngCore>(n: usize, m: usize, d: usize, rng: &mut R) -> SprsMat<F> {
306 let mut tmp: Vec<usize> = (0..m).collect();
307 let mut mat: Vec<Vec<(usize, F)>> = vec![vec![]; m];
308 for i in 0..n {
309 let idxs = {
311 (0..d)
312 .map(|j| {
313 let r = rng.next_u64() as usize % (m - j);
314 tmp.swap(r, m - 1 - j);
315 tmp[m - 1 - j]
316 })
317 .collect::<Vec<usize>>()
318 };
319 for j in idxs {
321 mat[j].push((
322 i,
323 loop {
324 let r = F::rand(rng);
325 if r != F::zero() {
326 break r;
327 }
328 },
329 ))
330 }
331 }
332 SprsMat::<F>::new_from_columns(n, m, d, &mat)
333 }
334
335 fn make_all<R: RngCore>(rng: &mut R, dims: &[(usize, usize, usize)]) -> Vec<SprsMat<F>> {
336 dims.iter()
337 .map(|(n, m, d)| Self::make_mat(*n, *m, *d, rng))
338 .collect::<Vec<_>>()
339 }
340}
341
342#[inline]
343fn div(a: (usize, usize)) -> f64 {
344 a.0 as f64 / a.1 as f64
345}
346
347struct Constants {
348 a: (usize, usize),
349 b: (usize, usize),
350 r: (usize, usize),
351 c: (f64, f64),
352 d: (f64, f64),
353}