labrador/relation/
witness.rs1use rand::rng;
2
3use crate::ring::{rq::Rq, rq_vector::RqVector, zq::Zq};
4
5pub struct Witness {
6 pub s: Vec<RqVector>,
7}
8
9impl Witness {
10 pub fn new(rank: usize, multiplicity: usize, bound: Zq) -> Self {
11 #[allow(clippy::as_conversions)]
12 let std = (bound.get_value() as f64) / f64::sqrt((rank * multiplicity * Rq::DEGREE) as f64);
13 #[allow(clippy::as_conversions)]
14 let std = std as u32;
15 loop {
16 let s: Vec<RqVector> = (0..multiplicity)
17 .map(|_| RqVector::random_with_bound(&mut rng(), rank, std))
18 .collect();
19 if Self::validate_l2_norm(&s, bound) {
20 return Self { s };
21 }
22 }
23 }
24
25 fn validate_l2_norm(candidate: &[RqVector], bound: Zq) -> bool {
26 for witness in candidate {
27 if witness.l2_norm_squared() > bound * bound {
28 return false;
29 }
30 }
31 true
32 }
33}
34
35#[cfg(test)]
36mod tests {
37
38 use crate::ring::{rq::Rq, rq_vector::RqVector, zq::Zq};
39
40 use super::Witness;
41
42 #[test]
43 fn test_witness_vector_norm() {
44 let bound = Zq::new(320000);
45 let witness_vector = Witness::new(40, 100, bound);
46 assert_eq!(witness_vector.s.len(), 100);
47 assert_eq!(witness_vector.s[0].get_length(), 40);
48 for witness in witness_vector.s.iter() {
49 let l2_norm = witness.l2_norm_squared();
50 assert!(l2_norm < bound * bound)
51 }
52 }
53
54 #[test]
55 fn test_witness_with_larger_bound() {
56 let poly1 = Rq::new([Zq::new(10000); Rq::DEGREE]);
57 let poly2 = Rq::new([Zq::new(142310); Rq::DEGREE]);
58 let poly3 = Rq::new([Zq::new(9310); Rq::DEGREE]);
59 let poly_vector = vec![poly1, poly2, poly3];
60 assert!(!Witness::validate_l2_norm(
61 &[RqVector::new(poly_vector)],
62 Zq::new(1000)
63 ));
64 }
65}