mirror of
https://github.com/arnaucube/Nova.git
synced 2026-01-10 16:11:29 +01:00
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
This commit is contained in:
@@ -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"] }
|
||||
|
||||
@@ -4,6 +4,7 @@ use super::{
|
||||
};
|
||||
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 @@ impl<G: Group> CommitGens<G> {
|
||||
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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
54
src/pasta.rs
54
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 pasta_curves::{
|
||||
use rand::SeedableRng;
|
||||
use rand_chacha::ChaCha20Rng;
|
||||
use rug::Integer;
|
||||
use std::{borrow::Borrow, ops::Mul};
|
||||
|
||||
//////////////////////////////////////Pallas///////////////////////////////////////////////
|
||||
|
||||
@@ -28,27 +28,21 @@ impl PallasCompressedElementWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ impl Group for pallas::Point {
|
||||
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 @@ impl Group for pallas::Point {
|
||||
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 @@ impl VestaCompressedElementWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ impl Group for vesta::Point {
|
||||
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 @@ impl Group for vesta::Point {
|
||||
arr.copy_from_slice(&bytes[0..32]);
|
||||
|
||||
let hash = Eq::hash_to_curve("from_uniform_bytes");
|
||||
Some(hash(&arr))
|
||||
Some(hash(&arr).to_affine())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>,
|
||||
|
||||
@@ -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 @@ pub trait Group:
|
||||
/// 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);
|
||||
|
||||
Reference in New Issue
Block a user