2022-07-26 02:05:15 -05:00
|
|
|
use core::ops::{Add, Sub, Mul, Index};
|
|
|
|
|
|
|
|
|
|
use group::ff::Field;
|
|
|
|
|
use dalek_ff_group::{Scalar, EdwardsPoint};
|
|
|
|
|
|
|
|
|
|
use multiexp::multiexp;
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
|
|
|
pub(crate) struct ScalarVector(pub(crate) Vec<Scalar>);
|
|
|
|
|
macro_rules! math_op {
|
|
|
|
|
($Op: ident, $op: ident, $f: expr) => {
|
|
|
|
|
impl $Op<Scalar> for ScalarVector {
|
|
|
|
|
type Output = ScalarVector;
|
|
|
|
|
fn $op(self, b: Scalar) -> ScalarVector {
|
|
|
|
|
ScalarVector(self.0.iter().map(|a| $f((a, &b))).collect())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl $Op<Scalar> for &ScalarVector {
|
|
|
|
|
type Output = ScalarVector;
|
|
|
|
|
fn $op(self, b: Scalar) -> ScalarVector {
|
|
|
|
|
ScalarVector(self.0.iter().map(|a| $f((a, &b))).collect())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl $Op<ScalarVector> for ScalarVector {
|
|
|
|
|
type Output = ScalarVector;
|
|
|
|
|
fn $op(self, b: ScalarVector) -> ScalarVector {
|
2022-07-26 05:31:15 -04:00
|
|
|
debug_assert_eq!(self.len(), b.len());
|
2022-07-26 02:05:15 -05:00
|
|
|
ScalarVector(self.0.iter().zip(b.0.iter()).map($f).collect())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl $Op<&ScalarVector> for &ScalarVector {
|
|
|
|
|
type Output = ScalarVector;
|
|
|
|
|
fn $op(self, b: &ScalarVector) -> ScalarVector {
|
2022-07-26 05:31:15 -04:00
|
|
|
debug_assert_eq!(self.len(), b.len());
|
2022-07-26 02:05:15 -05:00
|
|
|
ScalarVector(self.0.iter().zip(b.0.iter()).map($f).collect())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
math_op!(Add, add, |(a, b): (&Scalar, &Scalar)| *a + *b);
|
|
|
|
|
math_op!(Sub, sub, |(a, b): (&Scalar, &Scalar)| *a - *b);
|
|
|
|
|
math_op!(Mul, mul, |(a, b): (&Scalar, &Scalar)| *a * *b);
|
|
|
|
|
|
|
|
|
|
impl ScalarVector {
|
|
|
|
|
pub(crate) fn new(len: usize) -> ScalarVector {
|
|
|
|
|
ScalarVector(vec![Scalar::zero(); len])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn powers(x: Scalar, len: usize) -> ScalarVector {
|
2022-07-26 08:06:56 -04:00
|
|
|
debug_assert!(len != 0);
|
2022-07-26 02:05:15 -05:00
|
|
|
|
2022-07-26 08:06:56 -04:00
|
|
|
let mut res = Vec::with_capacity(len);
|
2022-07-26 02:05:15 -05:00
|
|
|
res.push(Scalar::one());
|
|
|
|
|
for i in 1 .. len {
|
|
|
|
|
res.push(res[i - 1] * x);
|
|
|
|
|
}
|
|
|
|
|
ScalarVector(res)
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-27 04:05:43 -05:00
|
|
|
pub(crate) fn even_powers(x: Scalar, pow: usize) -> ScalarVector {
|
|
|
|
|
debug_assert!(pow != 0);
|
|
|
|
|
// Verify pow is a power of two
|
|
|
|
|
debug_assert_eq!(((pow - 1) & pow), 0);
|
|
|
|
|
|
|
|
|
|
let xsq = x * x;
|
|
|
|
|
let mut res = ScalarVector(Vec::with_capacity(pow / 2));
|
|
|
|
|
res.0.push(xsq);
|
|
|
|
|
|
|
|
|
|
let mut prev = 2;
|
|
|
|
|
while prev < pow {
|
|
|
|
|
res.0.push(res[res.len() - 1] * xsq);
|
|
|
|
|
prev += 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-26 08:06:56 -04:00
|
|
|
pub(crate) fn sum(mut self) -> Scalar {
|
|
|
|
|
self.0.drain(..).sum()
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-26 02:05:15 -05:00
|
|
|
pub(crate) fn len(&self) -> usize {
|
|
|
|
|
self.0.len()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn split(self) -> (ScalarVector, ScalarVector) {
|
|
|
|
|
let (l, r) = self.0.split_at(self.0.len() / 2);
|
|
|
|
|
(ScalarVector(l.to_vec()), ScalarVector(r.to_vec()))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Index<usize> for ScalarVector {
|
|
|
|
|
type Output = Scalar;
|
|
|
|
|
fn index(&self, index: usize) -> &Scalar {
|
|
|
|
|
&self.0[index]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn inner_product(a: &ScalarVector, b: &ScalarVector) -> Scalar {
|
2022-07-26 08:06:56 -04:00
|
|
|
(a * b).sum()
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-02 15:52:27 -04:00
|
|
|
pub(crate) fn weighted_powers(x: Scalar, len: usize) -> ScalarVector {
|
|
|
|
|
ScalarVector(ScalarVector::powers(x, len + 1).0[1 ..].to_vec())
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-26 08:06:56 -04:00
|
|
|
pub(crate) fn weighted_inner_product(a: &ScalarVector, b: &ScalarVector, y: Scalar) -> Scalar {
|
2022-07-27 04:05:43 -05:00
|
|
|
// y ** 0 is not used as a power
|
2022-08-02 15:52:27 -04:00
|
|
|
(a * b * weighted_powers(y, a.len())).sum()
|
2022-07-26 02:05:15 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Mul<&[EdwardsPoint]> for &ScalarVector {
|
|
|
|
|
type Output = EdwardsPoint;
|
|
|
|
|
fn mul(self, b: &[EdwardsPoint]) -> EdwardsPoint {
|
2022-07-26 05:31:15 -04:00
|
|
|
debug_assert_eq!(self.len(), b.len());
|
2022-07-26 02:05:15 -05:00
|
|
|
multiexp(&self.0.iter().cloned().zip(b.iter().cloned()).collect::<Vec<_>>())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn hadamard_fold(
|
|
|
|
|
l: &[EdwardsPoint],
|
|
|
|
|
r: &[EdwardsPoint],
|
|
|
|
|
a: Scalar,
|
|
|
|
|
b: Scalar,
|
|
|
|
|
) -> Vec<EdwardsPoint> {
|
|
|
|
|
let mut res = Vec::with_capacity(l.len() / 2);
|
|
|
|
|
for i in 0 .. l.len() {
|
|
|
|
|
res.push(multiexp(&[(a, l[i]), (b, r[i])]));
|
|
|
|
|
}
|
|
|
|
|
res
|
|
|
|
|
}
|