labrador/relation/
statement.rs

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