ark_bulletproofs/
util.rs

1#![deny(missing_docs)]
2#![allow(non_snake_case)]
3
4use ark_ec::AffineRepr;
5use ark_std::{vec, vec::Vec, One, Zero};
6use clear_on_drop::clear::Clear;
7
8use crate::inner_product_proof::inner_product;
9
10/// Represents a degree-3 vector polynomial
11/// \\(\mathbf{a} + \mathbf{b} \cdot x + \mathbf{c} \cdot x^2 + \mathbf{d} \cdot x^3 \\).
12#[cfg(feature = "yoloproofs")]
13pub struct VecPoly3<G: AffineRepr>(
14    pub Vec<G::ScalarField>,
15    pub Vec<G::ScalarField>,
16    pub Vec<G::ScalarField>,
17    pub Vec<G::ScalarField>,
18);
19
20/// Represents a degree-6 scalar polynomial, without the zeroth degree
21/// \\(a \cdot x + b \cdot x^2 + c \cdot x^3 + d \cdot x^4 + e \cdot x^5 + f \cdot x^6\\)
22#[cfg(feature = "yoloproofs")]
23pub struct Poly6<G: AffineRepr> {
24    pub t1: G::ScalarField,
25    pub t2: G::ScalarField,
26    pub t3: G::ScalarField,
27    pub t4: G::ScalarField,
28    pub t5: G::ScalarField,
29    pub t6: G::ScalarField,
30}
31
32/// Provides an iterator over the powers of a `Fr`.
33///
34/// This struct is created by the `exp_iter` function.
35pub struct FrExp<G: AffineRepr> {
36    x: G::ScalarField,
37    next_exp_x: G::ScalarField,
38}
39
40impl<G: AffineRepr> Iterator for FrExp<G> {
41    type Item = G::ScalarField;
42
43    fn next(&mut self) -> Option<G::ScalarField> {
44        let exp_x = self.next_exp_x;
45        self.next_exp_x *= self.x;
46        Some(exp_x)
47    }
48
49    fn size_hint(&self) -> (usize, Option<usize>) {
50        (usize::MAX, None)
51    }
52}
53
54/// Return an iterator of the powers of `x`.
55pub fn exp_iter<G: AffineRepr>(x: G::ScalarField) -> FrExp<G> {
56    let next_exp_x = G::ScalarField::one();
57    FrExp { x, next_exp_x }
58}
59
60#[cfg(feature = "yoloproofs")]
61impl<G: AffineRepr> VecPoly3<G> {
62    pub fn zero(n: usize) -> Self {
63        VecPoly3(
64            vec![G::ScalarField::zero(); n],
65            vec![G::ScalarField::zero(); n],
66            vec![G::ScalarField::zero(); n],
67            vec![G::ScalarField::zero(); n],
68        )
69    }
70
71    /// Compute an inner product of `lhs`, `rhs` which have the property that:
72    /// - `lhs.0` is zero;
73    /// - `rhs.2` is zero;
74    /// This is the case in the constraint system proof.
75    pub fn special_inner_product(lhs: &Self, rhs: &Self) -> Poly6<G> {
76        // TODO: make checks that l_poly.0 and r_poly.2 are zero.
77
78        let t1 = inner_product(&lhs.1, &rhs.0);
79        let t2 = inner_product(&lhs.1, &rhs.1) + inner_product(&lhs.2, &rhs.0);
80        let t3 = inner_product(&lhs.2, &rhs.1) + inner_product(&lhs.3, &rhs.0);
81        let t4 = inner_product(&lhs.1, &rhs.3) + inner_product(&lhs.3, &rhs.1);
82        let t5 = inner_product(&lhs.2, &rhs.3);
83        let t6 = inner_product(&lhs.3, &rhs.3);
84
85        Poly6 {
86            t1,
87            t2,
88            t3,
89            t4,
90            t5,
91            t6,
92        }
93    }
94
95    pub fn eval(&self, x: G::ScalarField) -> Vec<G::ScalarField> {
96        let n = self.0.len();
97        let mut out = vec![G::ScalarField::zero(); n];
98        for i in 0..n {
99            out[i] = self.0[i] + x * (self.1[i] + x * (self.2[i] + x * self.3[i]));
100        }
101        out
102    }
103}
104
105#[cfg(feature = "yoloproofs")]
106impl<G: AffineRepr> Poly6<G> {
107    pub fn eval(&self, x: G::ScalarField) -> G::ScalarField {
108        x * (self.t1 + x * (self.t2 + x * (self.t3 + x * (self.t4 + x * (self.t5 + x * self.t6)))))
109    }
110}
111
112#[cfg(feature = "yoloproofs")]
113impl<G: AffineRepr> Drop for VecPoly3<G> {
114    fn drop(&mut self) {
115        for e in self.0.iter_mut() {
116            e.clear();
117        }
118        for e in self.1.iter_mut() {
119            e.clear();
120        }
121        for e in self.2.iter_mut() {
122            e.clear();
123        }
124        for e in self.3.iter_mut() {
125            e.clear();
126        }
127    }
128}
129
130#[cfg(feature = "yoloproofs")]
131impl<G: AffineRepr> Drop for Poly6<G> {
132    fn drop(&mut self) {
133        self.t1.clear();
134        self.t2.clear();
135        self.t3.clear();
136        self.t4.clear();
137        self.t5.clear();
138        self.t6.clear();
139    }
140}
141
142#[cfg(test)]
143mod tests {
144    use super::*;
145
146    #[test]
147    fn exp_2_is_powers_of_2() {
148        type G = ark_secq256k1::Affine;
149        type F = ark_secq256k1::Fr;
150
151        let exp_2: Vec<_> = exp_iter::<G>(F::from(2u64)).take(4).collect();
152
153        assert_eq!(exp_2[0], F::from(1u64));
154        assert_eq!(exp_2[1], F::from(2u64));
155        assert_eq!(exp_2[2], F::from(4u64));
156        assert_eq!(exp_2[3], F::from(8u64));
157    }
158
159    #[test]
160    fn test_inner_product() {
161        type F = ark_secq256k1::Fr;
162
163        let a = vec![F::from(1u64), F::from(2u64), F::from(3u64), F::from(4u64)];
164        let b = vec![F::from(2u64), F::from(3u64), F::from(4u64), F::from(5u64)];
165        assert_eq!(F::from(40u64), inner_product(&a, &b));
166    }
167
168    #[test]
169    fn vec_of_scalars_clear_on_drop() {
170        type F = ark_secq256k1::Fr;
171
172        let mut v = vec![F::from(24u64), F::from(42u64)];
173
174        for e in v.iter_mut() {
175            e.clear();
176        }
177
178        fn flat_slice<T>(x: &[T]) -> &[u8] {
179            use core::mem;
180            use core::slice;
181
182            unsafe { slice::from_raw_parts(x.as_ptr() as *const u8, mem::size_of_val(x)) }
183        }
184
185        assert_eq!(flat_slice(&v.as_slice()), &[0u8; 64][..]);
186        assert_eq!(v[0], F::zero());
187        assert_eq!(v[1], F::zero());
188    }
189}