labrador/core/
statement.rs

1use crate::core::env_params::EnvironmentParameters;
2use crate::prover::Witness;
3use crate::ring::poly::{PolyRing, PolyVector, ZqVector};
4
5/// Statement is the input of the prover, which contains the constraints.
6/// All parameters are from line 1, st, in the verifier process, page 18 from the paper.
7pub struct Statement {
8    // $a_{ij}^k$
9    pub a_constraint: Vec<Vec<PolyVector>>,
10    // $\varphi_i^k$
11    pub phi_constraint: Vec<Vec<PolyVector>>,
12    // $b^{(k)}$
13    pub b_constraint: PolyVector,
14    // $a_{ij}^{'(l)}$
15    pub a_ct: Vec<Vec<PolyVector>>,
16    // $\varphi_i^{'(l)}$
17    pub phi_ct: Vec<Vec<PolyVector>>,
18    // $b_0^{'(l)}$
19    pub b_0_ct: ZqVector,
20}
21
22impl Statement {
23    pub fn new(witness: &Witness, ep: &EnvironmentParameters) -> Self {
24        // generate random a_constraint with size: constraint_k * r * n
25        let a_constraint: Vec<Vec<PolyVector>> = (0..ep.constraint_k)
26            .map(|_| {
27                (0..ep.r)
28                    .map(|_| PolyVector::random(ep.n, ep.deg_bound_d))
29                    .collect()
30            })
31            .collect();
32
33        // generate random phi_constraint with size: constraint_k * r * n
34        let phi_constraint: Vec<Vec<PolyVector>> = (0..ep.constraint_k)
35            .map(|_| {
36                (0..ep.r)
37                    .map(|_| PolyVector::random(ep.n, ep.deg_bound_d))
38                    .collect()
39            })
40            .collect();
41
42        // calculate b_constraint b^k with size: constraint_k
43        let b_constraint: PolyVector = (0..ep.constraint_k)
44            .map(|k| calculate_b_constraint(&witness.s, &a_constraint[k], &phi_constraint[k]))
45            .collect();
46
47        // generate example a_ct with size: constraint_l * r * n
48        let a_ct: Vec<Vec<PolyVector>> = (0..ep.constraint_l)
49            .map(|_| {
50                (0..ep.r)
51                    .map(|_| PolyVector::random(ep.n, ep.deg_bound_d))
52                    .collect()
53            })
54            .collect();
55
56        // generate random phi_ct with size: constraint_k * r * n
57        // it is a k length vector of matrix with size: r * n
58        let phi_ct: Vec<Vec<PolyVector>> = (0..ep.constraint_k)
59            .map(|_| {
60                (0..ep.r)
61                    .map(|_| PolyVector::random(ep.n, ep.deg_bound_d))
62                    .collect()
63            })
64            .collect();
65
66        // calculate b^l with size: constraint_l
67        let b_constraint_l: PolyVector = (0..ep.constraint_l)
68            .map(|l| calculate_b_constraint(&witness.s, &a_ct[l], &phi_ct[l]))
69            .collect();
70
71        // calculate b_0^l
72        let b_0_ct: ZqVector = (0..ep.constraint_l)
73            .map(|l| b_constraint_l.get_elements()[l].get_coeffs()[0])
74            .collect();
75
76        Self {
77            a_constraint,
78            phi_constraint,
79            b_constraint,
80            a_ct,
81            phi_ct,
82            b_0_ct,
83        }
84    }
85}
86
87/// calculate b^{k} = \sum(a_{ij}^{k}<s_i, s_j>) + \sum(<phi_{i}^{k}, s_i>), k \in [K]
88/// in Prover initialization process, page 17 from the paper.
89///
90/// @param: s: s_i
91/// @param: a_constraint: a_{ij}^{k}
92/// @param: phi_constraint: \phi_{i}^{k}
93///
94/// @return: b^{k}
95#[rustfmt::skip]
96pub fn calculate_b_constraint(
97    s: &[PolyVector],
98    a_constraint: &[PolyVector],
99    phi_constraint: &[PolyVector],
100) -> PolyRing {
101    let size_s = s.len();
102    // calculate \sum(a_{ij}^{k}<s_i, s_j>)
103    let left_side = (0..size_s).map(|i| {
104        (0..size_s).map(|j| {
105            &a_constraint[i].get_elements()[j]
106                * &s[i].inner_product_poly_vector(&s[j])
107        })
108        .fold(PolyRing::zero_poly(), |acc, val| &acc + &val )
109    })
110    .fold(PolyRing::zero_poly(), |acc, val| &acc + &val );
111
112    // calculate \sum(<phi_{i}^{k}, s_i>)
113    let right_side = (0..size_s).fold(PolyRing::zero_poly(), |acc, i| {
114        &acc + &phi_constraint[i].inner_product_poly_vector(&s[i])
115    });
116
117    &left_side + &right_side
118}