labrador/core/
statement.rs

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