bp-pp 0.1.1

Rust library for Bulletproofs++ - range-proof protocol in discret loggarithm setting
Documentation
use std::cmp::max;
use std::ops::{Add, Mul, Sub};
use k256::elliptic_curve::Field;
use k256::elliptic_curve::ops::Invert;
use k256::Scalar;

pub fn reduce<T>(v: &[T]) -> (Vec<T>, Vec<T>) where T: Copy {
    let res0 = v.iter().
        enumerate().
        filter(|(i, _)| *i as i32 % 2 == 0).
        map(|(_, x)| *x).
        collect::<Vec<T>>();


    let res1 = v.iter().
        enumerate().
        filter(|(i, _)| *i as i32 % 2 == 1).
        map(|(_, x)| *x).
        collect::<Vec<T>>();

    (res0, res1)
}

pub fn vector_extend<T>(v: &[T], n: usize) -> Vec<T> where T: Copy + Default {
    (0..n).map(|i| if i < v.len() { v[i] } else { T::default() }).collect::<Vec<T>>()
}

pub fn weight_vector_mul<T>(a: &[T], b: &[Scalar], weight: &Scalar) -> T
    where
        T: Copy + Default + Mul<Scalar, Output=T> + Add<Output=T>
{
    let mut exp = Scalar::ONE;
    let mut result = T::default();

    let a_ext = vector_extend(a, max(a.len(), b.len()));
    let b_ext = &vector_extend(b, max(a.len(), b.len()));

    a_ext.iter().zip(b_ext).for_each(|(a_val, b_val)| {
        exp = exp.mul(weight);
        result = result.add(a_val.mul(b_val.mul(&exp)));
    });

    result
}

pub fn vector_mul<T>(a: &[T], b: &[Scalar]) -> T
    where
        T: Copy + Default + Mul<Scalar, Output=T> + Add<Output=T>
{
    let mut result = T::default();

    let a_ext = &vector_extend(a, max(a.len(), b.len()));
    let b_ext = &vector_extend(b, max(a.len(), b.len()));

    a_ext.iter().zip(b_ext).for_each(|(a_val, b_val)| {
        result = result.add(a_val.mul(*b_val));
    });

    result
}

pub fn vector_mul_on_scalar<'a, T>(a: &[T], s: &'a Scalar) -> Vec<T>
    where
        T: Copy + Mul<&'a Scalar, Output=T>
{
    a.iter().map(|x| x.mul(s)).collect::<Vec<T>>()
}

pub fn vector_add<T>(a: &[T], b: &[T]) -> Vec<T>
    where
        T: Copy + Default + Add<Output=T>
{
    let a_ext = &vector_extend(a, max(a.len(), b.len()));
    let b_ext = &vector_extend(b, max(a.len(), b.len()));
    a_ext.iter().zip(b_ext).map(|(a_val, b_val)| a_val.add(*b_val)).collect::<Vec<T>>()
}

pub fn vector_sub<'a, T>(a: &'a [T], b: &'a [T]) -> Vec<T>
    where
        T: Copy + Default + Sub<Output=T>
{
    let a_ext = &vector_extend(a, max(a.len(), b.len()));
    let b_ext = &vector_extend(b, max(a.len(), b.len()));
    a_ext.iter().zip(b_ext).map(|(a_val, b_val)| a_val.sub(*b_val)).collect::<Vec<T>>()
}

pub fn e(v: &Scalar, n: usize) -> Vec<Scalar> {
    let mut buf = Scalar::ONE;

    (0..n).map(|_| {
        let val = buf;
        buf = buf.mul(v);
        val
    }).collect::<Vec<Scalar>>()
}

pub fn pow(s: &Scalar, n: usize) -> Scalar {
    s.pow_vartime([n as u64])
}

#[allow(dead_code)]
pub fn vector_hadamard_mul<T>(a: &[T], b: &[Scalar]) -> Vec<T>
    where
        T: Copy + Default + Mul<Scalar, Output=T>
{
    let a_ext = &vector_extend(a, max(a.len(), b.len()));
    let b_ext = &vector_extend(b, max(a.len(), b.len()));
    a_ext.iter().zip(b_ext).map(|(a_val, b_val)| a_val.mul(*b_val)).collect::<Vec<T>>()
}

pub fn vector_tensor_mul<'a, T>(a: &'a [T], b: &'a [Scalar]) -> Vec<T>
    where
        T: Copy + Mul<&'a Scalar, Output=T>
{
    b.iter().map(|x| vector_mul_on_scalar(a, x)).collect::<Vec<Vec<T>>>().concat()
}

pub fn diag_inv(x: &Scalar, n: usize) -> Vec<Vec<Scalar>> {
    let x_inv = x.invert_vartime().unwrap();
    let mut val = Scalar::ONE;

    (0..n).map(|i|
        (0..n).map(|j|
            if i == j {
                val = val.mul(x_inv);
                val
            } else {
                Scalar::ZERO
            }
        ).collect::<Vec<Scalar>>()
    ).collect::<Vec<Vec<Scalar>>>()
}

pub fn vector_mul_on_matrix<T>(a: &[T], m: &[Vec<Scalar>]) -> Vec<T>
    where
        T: Copy + Default + Mul<Scalar, Output=T> + Add<Output=T>
{
    (0..m[0].len()).map(|j| {
        let column = m.iter().map(|row| row[j]).collect::<Vec<Scalar>>();
        vector_mul(a, &column)
    }).collect::<Vec<T>>()
}

#[allow(dead_code)]
pub fn matrix_mul_on_vector<T>(a: &[T], m: &[Vec<Scalar>]) -> Vec<T>
    where
        T: Copy + Default + Mul<Scalar, Output=T> + Add<Output=T>
{
    m.iter().map(|v| vector_mul(a, v)).collect::<Vec<T>>()
}


pub fn minus<T>(v: &T) -> T where T: Copy + Mul<Scalar, Output=T> {
    v.mul(Scalar::ZERO.sub(&Scalar::ONE))
}