arnaucube
arnaucube/NovaPublic Self-hosted repository
Accelerated MSM prep (#41)

* remove send + sync

* introduce a new associative type to capture any form of preprocessing on group elements

* update pasta_curves version

* simplify trait requirements

* fix clippy
Srinath Setty srinath@microsoft.com
Mon, 25 Apr 2022 21:09:47 -0700
commit

bcbdec2982ca6ff0e839fc3c03be8590154e42ff

parent

3445d7da61c328b7488bab628a156386e36e2117

5 files changed, 38 insertions(+), 47 deletions(-)

jump to
M Cargo.toml → Cargo.toml

@@ -22,7 +22,7 @@ rand_core = { version = "0.5", default-features = false }

rand_chacha = "0.3" itertools = "0.9.0" subtle = "2.4" -pasta_curves = "0.3.0" +pasta_curves = "0.3.1" neptune = "6.1" generic-array = "0.14.4" bellperson-nonnative = { version = "0.2.1", default-features = false, features = ["wasm"] }
M src/commitments.rs → src/commitments.rs

@@ -4,6 +4,7 @@ traits::{CompressedGroup, Group},

}; use core::{ fmt::Debug, + marker::PhantomData, ops::{Add, AddAssign, Mul, MulAssign}, }; use digest::{ExtendableOutput, Input};

@@ -13,7 +14,8 @@ use std::io::Read;

#[derive(Debug)] pub struct CommitGens<G: Group> { - gens: Vec<G>, + gens: Vec<G::PreprocessedGroupElement>, + _p: PhantomData<G>, } #[derive(Clone, Copy, Debug, PartialEq, Eq)]

@@ -31,14 +33,17 @@ pub fn new(label: &[u8], n: usize) -> Self {

let mut shake = Shake256::default(); shake.input(label); let mut reader = shake.xof_result(); - let mut gens: Vec<G> = Vec::new(); + let mut gens: Vec<G::PreprocessedGroupElement> = Vec::new(); let mut uniform_bytes = [0u8; 64]; for _ in 0..n { reader.read_exact(&mut uniform_bytes).unwrap(); gens.push(G::from_uniform_bytes(&uniform_bytes).unwrap()); } - CommitGens { gens } + CommitGens { + gens, + _p: PhantomData::default(), + } } }
M src/pasta.rs → src/pasta.rs

@@ -1,5 +1,6 @@

//! This module implements the Nova traits for pallas::Point, pallas::Scalar, vesta::Point, vesta::Scalar. use crate::traits::{ChallengeTrait, CompressedGroup, Group}; +use core::ops::Mul; use ff::Field; use merlin::Transcript; use pasta_curves::{

@@ -11,7 +12,6 @@ };

use rand::SeedableRng; use rand_chacha::ChaCha20Rng; use rug::Integer; -use std::{borrow::Borrow, ops::Mul}; //////////////////////////////////////Pallas///////////////////////////////////////////////

@@ -28,27 +28,21 @@ Self { repr }

} } -unsafe impl Send for PallasCompressedElementWrapper {} -unsafe impl Sync for PallasCompressedElementWrapper {} - impl Group for pallas::Point { type Base = pallas::Base; type Scalar = pallas::Scalar; type CompressedGroupElement = PallasCompressedElementWrapper; + type PreprocessedGroupElement = pallas::Affine; - fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self - where - I: IntoIterator, - I::Item: Borrow<Self::Scalar>, - J: IntoIterator, - J::Item: Borrow<Self>, - Self: Clone, - { + fn vartime_multiscalar_mul( + scalars: &[Self::Scalar], + bases: &[Self::PreprocessedGroupElement], + ) -> Self { // Unoptimized. scalars - .into_iter() - .zip(points) - .map(|(scalar, point)| (*point.borrow()).mul(*scalar.borrow())) + .iter() + .zip(bases) + .map(|(scalar, base)| base.mul(scalar)) .fold(Ep::group_zero(), |acc, x| acc + x) }

@@ -56,7 +50,7 @@ fn compress(&self) -> Self::CompressedGroupElement {

PallasCompressedElementWrapper::new(self.to_bytes()) } - fn from_uniform_bytes(bytes: &[u8]) -> Option<Self> { + fn from_uniform_bytes(bytes: &[u8]) -> Option<Self::PreprocessedGroupElement> { if bytes.len() != 64 { None } else {

@@ -64,7 +58,7 @@ let mut arr = [0; 32];

arr.copy_from_slice(&bytes[0..32]); let hash = Ep::hash_to_curve("from_uniform_bytes"); - Some(hash(&arr)) + Some(hash(&arr).to_affine()) } }

@@ -121,27 +115,21 @@ Self { repr }

} } -unsafe impl Send for VestaCompressedElementWrapper {} -unsafe impl Sync for VestaCompressedElementWrapper {} - impl Group for vesta::Point { type Base = vesta::Base; type Scalar = vesta::Scalar; type CompressedGroupElement = VestaCompressedElementWrapper; + type PreprocessedGroupElement = vesta::Affine; - fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self - where - I: IntoIterator, - I::Item: Borrow<Self::Scalar>, - J: IntoIterator, - J::Item: Borrow<Self>, - Self: Clone, - { + fn vartime_multiscalar_mul( + scalars: &[Self::Scalar], + bases: &[Self::PreprocessedGroupElement], + ) -> Self { // Unoptimized. scalars - .into_iter() - .zip(points) - .map(|(scalar, point)| (*point.borrow()).mul(*scalar.borrow())) + .iter() + .zip(bases) + .map(|(scalar, base)| base.mul(scalar)) .fold(Eq::group_zero(), |acc, x| acc + x) }

@@ -149,7 +137,7 @@ fn compress(&self) -> Self::CompressedGroupElement {

VestaCompressedElementWrapper::new(self.to_bytes()) } - fn from_uniform_bytes(bytes: &[u8]) -> Option<Self> { + fn from_uniform_bytes(bytes: &[u8]) -> Option<Self::PreprocessedGroupElement> { if bytes.len() != 64 { None } else {

@@ -157,7 +145,7 @@ let mut arr = [0; 32];

arr.copy_from_slice(&bytes[0..32]); let hash = Eq::hash_to_curve("from_uniform_bytes"); - Some(hash(&arr)) + Some(hash(&arr).to_affine()) } }
M src/r1cs.rs → src/r1cs.rs

@@ -10,7 +10,6 @@ use itertools::concat;

use rayon::prelude::*; /// Public parameters for a given R1CS -#[derive(Debug)] pub struct R1CSGens<G: Group> { pub(crate) gens_W: CommitGens<G>, // TODO: avoid pub(crate) pub(crate) gens_E: CommitGens<G>,
M src/traits.rs → src/traits.rs

@@ -1,7 +1,6 @@

//! This module defines various traits required by the users of the library to implement. use bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError}; use core::{ - borrow::Borrow, fmt::Debug, ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}, };

@@ -30,21 +29,21 @@

/// A type representing the compressed version of the group element type CompressedGroupElement: CompressedGroup<GroupElement = Self>; + /// A type representing preprocessed group element + type PreprocessedGroupElement; + /// A method to compute a multiexponentation - fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self - where - I: IntoIterator, - I::Item: Borrow<Self::Scalar>, - J: IntoIterator, - J::Item: Borrow<Self>, - Self: Clone; + fn vartime_multiscalar_mul( + scalars: &[Self::Scalar], + bases: &[Self::PreprocessedGroupElement], + ) -> Self; /// Compresses the group element fn compress(&self) -> Self::CompressedGroupElement; /// Attempts to create a group element from a sequence of bytes, /// failing with a `None` if the supplied bytes do not encode the group element - fn from_uniform_bytes(bytes: &[u8]) -> Option<Self>; + fn from_uniform_bytes(bytes: &[u8]) -> Option<Self::PreprocessedGroupElement>; /// Returns the affine coordinates (x, y, infinty) for the point fn to_coordinates(&self) -> (Self::Base, Self::Base, bool);