#![deny(missing_docs)]
#![allow(non_snake_case)]
use ark_ec::AffineRepr;
use ark_std::{vec, vec::Vec, One, Zero};
use clear_on_drop::clear::Clear;
use crate::inner_product_proof::inner_product;
#[cfg(feature = "yoloproofs")]
pub struct VecPoly3<G: AffineRepr>(
pub Vec<G::ScalarField>,
pub Vec<G::ScalarField>,
pub Vec<G::ScalarField>,
pub Vec<G::ScalarField>,
);
#[cfg(feature = "yoloproofs")]
pub struct Poly6<G: AffineRepr> {
pub t1: G::ScalarField,
pub t2: G::ScalarField,
pub t3: G::ScalarField,
pub t4: G::ScalarField,
pub t5: G::ScalarField,
pub t6: G::ScalarField,
}
pub struct FrExp<G: AffineRepr> {
x: G::ScalarField,
next_exp_x: G::ScalarField,
}
impl<G: AffineRepr> Iterator for FrExp<G> {
type Item = G::ScalarField;
fn next(&mut self) -> Option<G::ScalarField> {
let exp_x = self.next_exp_x;
self.next_exp_x *= self.x;
Some(exp_x)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(usize::MAX, None)
}
}
pub fn exp_iter<G: AffineRepr>(x: G::ScalarField) -> FrExp<G> {
let next_exp_x = G::ScalarField::one();
FrExp { x, next_exp_x }
}
#[cfg(feature = "yoloproofs")]
impl<G: AffineRepr> VecPoly3<G> {
pub fn zero(n: usize) -> Self {
VecPoly3(
vec![G::ScalarField::zero(); n],
vec![G::ScalarField::zero(); n],
vec![G::ScalarField::zero(); n],
vec![G::ScalarField::zero(); n],
)
}
pub fn special_inner_product(lhs: &Self, rhs: &Self) -> Poly6<G> {
let t1 = inner_product(&lhs.1, &rhs.0);
let t2 = inner_product(&lhs.1, &rhs.1) + inner_product(&lhs.2, &rhs.0);
let t3 = inner_product(&lhs.2, &rhs.1) + inner_product(&lhs.3, &rhs.0);
let t4 = inner_product(&lhs.1, &rhs.3) + inner_product(&lhs.3, &rhs.1);
let t5 = inner_product(&lhs.2, &rhs.3);
let t6 = inner_product(&lhs.3, &rhs.3);
Poly6 {
t1,
t2,
t3,
t4,
t5,
t6,
}
}
pub fn eval(&self, x: G::ScalarField) -> Vec<G::ScalarField> {
let n = self.0.len();
let mut out = vec![G::ScalarField::zero(); n];
for i in 0..n {
out[i] = self.0[i] + x * (self.1[i] + x * (self.2[i] + x * self.3[i]));
}
out
}
}
#[cfg(feature = "yoloproofs")]
impl<G: AffineRepr> Poly6<G> {
pub fn eval(&self, x: G::ScalarField) -> G::ScalarField {
x * (self.t1 + x * (self.t2 + x * (self.t3 + x * (self.t4 + x * (self.t5 + x * self.t6)))))
}
}
#[cfg(feature = "yoloproofs")]
impl<G: AffineRepr> Drop for VecPoly3<G> {
fn drop(&mut self) {
for e in self.0.iter_mut() {
e.clear();
}
for e in self.1.iter_mut() {
e.clear();
}
for e in self.2.iter_mut() {
e.clear();
}
for e in self.3.iter_mut() {
e.clear();
}
}
}
#[cfg(feature = "yoloproofs")]
impl<G: AffineRepr> Drop for Poly6<G> {
fn drop(&mut self) {
self.t1.clear();
self.t2.clear();
self.t3.clear();
self.t4.clear();
self.t5.clear();
self.t6.clear();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn exp_2_is_powers_of_2() {
type G = ark_secq256k1::Affine;
type F = ark_secq256k1::Fr;
let exp_2: Vec<_> = exp_iter::<G>(F::from(2u64)).take(4).collect();
assert_eq!(exp_2[0], F::from(1u64));
assert_eq!(exp_2[1], F::from(2u64));
assert_eq!(exp_2[2], F::from(4u64));
assert_eq!(exp_2[3], F::from(8u64));
}
#[test]
fn test_inner_product() {
type F = ark_secq256k1::Fr;
let a = vec![F::from(1u64), F::from(2u64), F::from(3u64), F::from(4u64)];
let b = vec![F::from(2u64), F::from(3u64), F::from(4u64), F::from(5u64)];
assert_eq!(F::from(40u64), inner_product(&a, &b));
}
#[test]
fn vec_of_scalars_clear_on_drop() {
type F = ark_secq256k1::Fr;
let mut v = vec![F::from(24u64), F::from(42u64)];
for e in v.iter_mut() {
e.clear();
}
fn flat_slice<T>(x: &[T]) -> &[u8] {
use core::mem;
use core::slice;
unsafe { slice::from_raw_parts(x.as_ptr() as *const u8, mem::size_of_val(x)) }
}
assert_eq!(flat_slice(&v.as_slice()), &[0u8; 64][..]);
assert_eq!(v[0], F::zero());
assert_eq!(v[1], F::zero());
}
}