1use crate::core::{env_params::EnvironmentParameters, statement::Statement};
2use crate::prover::{Challenges, Witness};
3use crate::ring::rq::Rq;
4use crate::ring::rq_vector::RqVector;
5use crate::ring::zq::Zq;
6
7pub struct AggregationOne {
9 pub a_ct_aggr: Vec<Vec<RqVector>>,
11 pub phi_ct_aggr: Vec<Vec<RqVector>>,
13 pub b_ct_aggr: RqVector,
15}
16
17impl AggregationOne {
18 pub fn new(
19 witness: &Witness,
20 st: &Statement,
21 ep: &EnvironmentParameters,
22 tr: &Challenges,
23 ) -> Self {
24 Self::aggregate(witness, st, ep, tr)
25 }
26
27 fn aggregate(
28 witness: &Witness,
29 st: &Statement,
30 ep: &EnvironmentParameters,
31 tr: &Challenges,
32 ) -> Self {
33 let a_ct_aggr: Vec<Vec<RqVector>> = Self::get_a_ct_aggr(&tr.psi, &st.a_ct, ep);
35
36 let phi_ct_aggr: Vec<Vec<RqVector>> =
38 Self::get_phi_ct_aggr(&st.phi_ct, &tr.pi, &tr.psi, &tr.omega, ep);
39
40 let b_ct_aggr: RqVector = Self::get_b_ct_aggr(&a_ct_aggr, &phi_ct_aggr, witness, ep);
42
43 Self {
44 a_ct_aggr,
45 phi_ct_aggr,
46 b_ct_aggr,
47 }
48 }
49
50 pub fn get_a_ct_aggr(
51 psi: &[Vec<Zq>],
52 a_ct: &[Vec<RqVector>],
53 ep: &EnvironmentParameters,
54 ) -> Vec<Vec<RqVector>> {
55 calculate_aggr_ct_a(psi, a_ct, ep)
56 }
57
58 pub fn get_phi_ct_aggr(
59 phi_ct: &[Vec<RqVector>],
60 pi: &[Vec<Vec<Zq>>],
61 psi: &[Vec<Zq>],
62 omega: &[Vec<Zq>],
63 ep: &EnvironmentParameters,
64 ) -> Vec<Vec<RqVector>> {
65 calculate_aggr_ct_phi(phi_ct, pi, psi, omega, ep)
66 }
67
68 pub fn get_b_ct_aggr(
69 a_ct_aggr: &[Vec<RqVector>],
70 phi_ct_aggr: &[Vec<RqVector>],
71 witness: &Witness,
72 ep: &EnvironmentParameters,
73 ) -> RqVector {
74 calculate_aggr_ct_b(a_ct_aggr, phi_ct_aggr, &witness.s, ep)
75 }
76}
77
78pub struct AggregationTwo {
80 pub a_i: Vec<RqVector>,
82 pub phi_i: Vec<RqVector>,
84 pub b_i: Rq,
86}
87
88impl AggregationTwo {
89 pub fn new(
90 aggr_one: &AggregationOne,
91 st: &Statement,
92 ep: &EnvironmentParameters,
93 tr: &Challenges,
94 ) -> Self {
95 Self::aggregate(aggr_one, st, ep, tr)
96 }
97
98 fn aggregate(
99 aggr_one: &AggregationOne,
100 st: &Statement,
101 ep: &EnvironmentParameters,
102 tr: &Challenges,
103 ) -> Self {
104 let a_i = Self::get_a_i(
106 &st.a_constraint,
107 &aggr_one.a_ct_aggr,
108 &tr.random_alpha,
109 &tr.random_beta,
110 ep,
111 );
112
113 let phi_i = Self::get_phi_i(
115 &st.phi_constraint,
116 &aggr_one.phi_ct_aggr,
117 &tr.random_alpha,
118 &tr.random_beta,
119 ep,
120 );
121
122 let b_i = Self::get_b_i(
124 &st.b_constraint,
125 &aggr_one.b_ct_aggr,
126 &tr.random_alpha,
127 &tr.random_beta,
128 ep,
129 );
130
131 Self { a_i, phi_i, b_i }
132 }
133
134 pub fn get_a_i(
135 a_constraint: &[Vec<RqVector>],
136 a_ct_aggr: &[Vec<RqVector>],
137 random_alpha: &RqVector,
138 random_beta: &RqVector,
139 ep: &EnvironmentParameters,
140 ) -> Vec<RqVector> {
141 calculate_aggr_a(a_constraint, a_ct_aggr, random_alpha, random_beta, ep)
142 }
143
144 pub fn get_phi_i(
145 phi_constraint: &[Vec<RqVector>],
146 phi_ct_aggr: &[Vec<RqVector>],
147 random_alpha: &RqVector,
148 random_beta: &RqVector,
149 ep: &EnvironmentParameters,
150 ) -> Vec<RqVector> {
151 calculate_aggr_phi(phi_constraint, phi_ct_aggr, random_alpha, random_beta, ep)
152 }
153
154 pub fn get_b_i(
155 b_constraint: &RqVector,
156 b_ct_aggr: &RqVector,
157 random_alpha: &RqVector,
158 random_beta: &RqVector,
159 ep: &EnvironmentParameters,
160 ) -> Rq {
161 calculate_aggr_b(b_constraint, b_ct_aggr, random_alpha, random_beta, ep)
162 }
163}
164
165#[rustfmt::skip]
173fn calculate_aggr_ct_a(
174 random_psi: &[Vec<Zq>],
175 a_ct: &[Vec<RqVector>],
176 ep: &EnvironmentParameters,
177) -> Vec<Vec<RqVector>> {
178 let aprimes: Vec<Vec<RqVector>> = (0..ep.kappa).map(|k| {
179 let psi_k = &random_psi[k];
180 (0..ep.r).map(|i| {
181 (0..ep.r).map(|j| {
182 (0..ep.constraint_l).map(|l| {
184 &a_ct[l][i].get_elements()[j]
185 * &psi_k[l]
186 })
187 .fold(
188 Rq::zero(),
190 |acc, val| acc + val,
191 )
192 }).collect::<RqVector>()
193 }).collect::<Vec<RqVector>>()
194 }).collect();
195
196 aprimes
197}
198
199fn calculate_aggr_ct_phi(
211 phi_ct: &[Vec<RqVector>],
212 pi: &[Vec<Vec<Zq>>],
213 random_psi: &[Vec<Zq>],
214 random_omega: &[Vec<Zq>],
215 ep: &EnvironmentParameters,
216) -> Vec<Vec<RqVector>> {
217 let phi_ct_aggr: Vec<Vec<RqVector>> = (0..ep.kappa)
218 .map(|k| {
219 (0..ep.r)
220 .map(|i| {
221 let left_side = (0..ep.constraint_l)
223 .map(|l| {
224 phi_ct[l][i]
225 .iter()
226 .map(|phi| phi * &random_psi[k][l])
227 .collect::<RqVector>()
228 })
229 .fold(RqVector::new(vec![Rq::zero(); ep.n]), |acc, val| {
230 acc.iter().zip(val.iter()).map(|(a, b)| a + b).collect()
231 });
232
233 let right_side = (0..(2 * ep.lambda))
236 .map(|j| {
237 let omega_j = random_omega[k][j];
238 (0..ep.n)
239 .map(|chunk_index| {
240 let start = chunk_index * Rq::DEGREE;
241 let end = start + Rq::DEGREE;
242
243 let pi_poly = Rq::new(pi[i][j][start..end].try_into().unwrap());
244 let pi_poly_conjugate = pi_poly.conjugate_automorphism();
245 &pi_poly_conjugate * &omega_j
246 })
247 .collect::<RqVector>()
248 })
249 .fold(RqVector::new(vec![Rq::zero(); ep.n]), |acc, val| {
250 acc.iter().zip(val.iter()).map(|(a, b)| a + b).collect()
251 });
252
253 &left_side + &right_side
254 })
255 .collect::<Vec<RqVector>>()
256 })
257 .collect::<Vec<Vec<RqVector>>>();
258
259 phi_ct_aggr
260}
261
262#[rustfmt::skip]
271fn calculate_aggr_ct_b(
272 a_ct_aggr: &[Vec<RqVector>],
273 phi_ct_aggr: &[Vec<RqVector>],
274 witness: &[RqVector],
275 ep: &EnvironmentParameters,
276) -> RqVector {
277 (0..ep.kappa).map(|k| {
278 (0..ep.r).map(|i| {
279 (0..ep.r).map(|j| {
280 a_ct_aggr[k][i].get_elements()[j].clone()
282 * witness[i].inner_product_poly_vector(&witness[j])
283 })
284 .fold(
285 Rq::zero(),
287 |acc, val| acc + val,
288 )
289 + phi_ct_aggr[k][i].inner_product_poly_vector(&witness[i])
291 }) .fold(Rq::zero(), |acc, val| {
293 acc + val
294 })
295 }).collect()
296}
297
298fn calculate_aggr_a(
309 a_constraint: &[Vec<RqVector>],
310 a_ct_aggr: &[Vec<RqVector>],
311 random_alpha: &RqVector,
312 random_beta: &RqVector,
313 ep: &EnvironmentParameters,
314) -> Vec<RqVector> {
315 let a_i: Vec<RqVector> = (0..ep.r)
316 .map(|i| {
317 (0..ep.r)
318 .map(|j| {
319 let left_side = (0..ep.constraint_k)
321 .map(|k| {
322 a_constraint[k][i].get_elements()[j].clone()
323 * random_alpha.get_elements()[k].clone()
324 })
325 .fold(Rq::zero(), |acc, val| acc + val);
326
327 let right_side = (0..ep.kappa)
329 .map(|k| {
330 a_ct_aggr[k][i].get_elements()[j].clone()
331 * random_beta.get_elements()[k].clone()
332 })
333 .fold(Rq::zero(), |acc, val| acc + val);
334
335 left_side + right_side
336 })
337 .collect::<RqVector>()
338 })
339 .collect::<Vec<RqVector>>();
340
341 a_i
342}
343
344fn calculate_aggr_phi(
355 phi_constraint: &[Vec<RqVector>],
356 phi_ct_aggr: &[Vec<RqVector>],
357 random_alpha: &RqVector,
358 random_beta: &RqVector,
359 ep: &EnvironmentParameters,
360) -> Vec<RqVector> {
361 let phi_i: Vec<RqVector> = (0..ep.r)
362 .map(|i| {
363 let left_side: RqVector = (0..ep.constraint_k)
365 .map(|k| {
366 phi_constraint[k][i]
367 .iter()
368 .map(|phi| phi * &random_alpha.get_elements()[k])
369 .collect::<RqVector>()
370 })
371 .fold(RqVector::new(vec![Rq::zero(); ep.n]), |acc, val| {
372 acc.iter().zip(val.iter()).map(|(a, b)| a + b).collect()
373 });
374
375 let right_side: RqVector = (0..ep.kappa)
377 .map(|k| {
378 phi_ct_aggr[k][i]
379 .iter()
380 .map(|phi| phi * &random_beta.get_elements()[k])
381 .collect::<RqVector>()
382 })
383 .fold(RqVector::new(vec![Rq::zero(); ep.n]), |acc, val| {
384 acc.iter().zip(val.iter()).map(|(a, b)| a + b).collect()
385 });
386
387 &left_side + &right_side
388 })
389 .collect::<Vec<RqVector>>();
390
391 phi_i
392}
393
394fn calculate_aggr_b(
405 b_constraint: &RqVector,
406 b_ct_aggr: &RqVector,
407 random_alpha: &RqVector,
408 random_beta: &RqVector,
409 ep: &EnvironmentParameters,
410) -> Rq {
411 let left_side = (0..ep.constraint_k)
412 .map(|k| b_constraint.get_elements()[k].clone() * random_alpha.get_elements()[k].clone())
413 .fold(Rq::zero(), |acc, val| acc + val);
414
415 let right_side = (0..ep.kappa)
416 .map(|k| b_ct_aggr.get_elements()[k].clone() * random_beta.get_elements()[k].clone())
417 .fold(Rq::zero(), |acc, val| acc + val);
418
419 left_side + right_side
420}
421
422pub fn calculate_hij(
430 phi_i: &[RqVector],
431 s: &[RqVector],
432 ep: &EnvironmentParameters,
433) -> Vec<RqVector> {
434 (0..ep.r)
435 .map(|i| {
436 (0..ep.r)
437 .map(|j| {
438 let left_side = &phi_i[i].inner_product_poly_vector(&s[j]);
439 let right_side = &phi_i[j].inner_product_poly_vector(&s[i]);
440 left_side + right_side
441 })
442 .collect()
443 })
444 .collect()
445}
446
447pub fn calculate_gij(s: &[RqVector], r: usize) -> Vec<RqVector> {
455 (0..r)
456 .map(|i| {
457 (0..r)
458 .map(|j| s[i].inner_product_poly_vector(&s[j]))
459 .collect()
460 })
461 .collect()
462}
463
464pub fn calculate_z(x: &[RqVector], random_c: &RqVector) -> RqVector {
472 x.iter()
473 .zip(random_c.iter())
474 .map(|(s_row, c_element)| s_row * c_element)
475 .fold(
476 RqVector::new(vec![Rq::zero(); x[0].get_elements().len()]),
477 |acc, x| &acc + &x,
478 )
479}
480
481pub fn calculate_u_1(
483 b: &[Vec<Vec<RqVector>>],
484 c: &[Vec<Vec<Vec<RqVector>>>],
485 t_i: &[Vec<RqVector>],
486 g_ij: &[Vec<RqVector>],
487 ep: &EnvironmentParameters,
488) -> RqVector {
489 let mut u_1 = vec![Rq::zero(); ep.kappa_1];
490 for i in 0..ep.r {
492 for k in 0..ep.t_1 {
493 let b_ik_t_ik = &t_i[i][k] * &b[i][k];
494 u_1 = u_1
495 .iter()
496 .zip(b_ik_t_ik.iter())
497 .map(|(a, b)| a + b)
498 .collect();
499 }
500 }
501 for i in 0..ep.r {
503 for j in i..ep.r {
504 for k in 0..ep.t_2 {
505 let c_ijk_g_ij = &g_ij[i][j] * &c[i][j][k];
506 u_1 = u_1
507 .iter()
508 .zip(c_ijk_g_ij.iter())
509 .map(|(a, b)| a + b)
510 .collect();
511 }
512 }
513 }
514
515 RqVector::new(u_1)
516}
517
518pub fn calculate_u_2(
520 d: &[Vec<Vec<Vec<RqVector>>>],
521 h_ij: &[Vec<RqVector>],
522 ep: &EnvironmentParameters,
523) -> RqVector {
524 let flat_vec: Vec<(usize, usize, usize)> = (0..ep.r)
526 .flat_map(|i| (i..ep.r).flat_map(move |j| (0..ep.t_2).map(move |k| (i, j, k))))
527 .collect();
528
529 flat_vec
530 .into_iter()
531 .fold(RqVector::new(vec![Rq::zero(); ep.n]), |acc, (i, j, k)| {
532 let d_ijk_h_ij = &h_ij[i][j] * &d[i][j][k];
533 acc.iter()
534 .zip(d_ijk_h_ij.iter())
535 .map(|(a, b)| a + b)
536 .collect::<RqVector>()
537 })
538}
539
540