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"
|
rand_chacha = "0.3"
|
||||||
itertools = "0.9.0"
|
itertools = "0.9.0"
|
||||||
subtle = "2.4"
|
subtle = "2.4"
|
||||||
pasta_curves = "0.3.0"
|
pasta_curves = "0.3.1"
|
||||||
neptune = "6.1"
|
neptune = "6.1"
|
||||||
generic-array = "0.14.4"
|
generic-array = "0.14.4"
|
||||||
bellperson-nonnative = { version = "0.2.1", default-features = false, features = ["wasm"] }
|
bellperson-nonnative = { version = "0.2.1", default-features = false, features = ["wasm"] }
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use super::{
|
|||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
|
marker::PhantomData,
|
||||||
ops::{Add, AddAssign, Mul, MulAssign},
|
ops::{Add, AddAssign, Mul, MulAssign},
|
||||||
};
|
};
|
||||||
use digest::{ExtendableOutput, Input};
|
use digest::{ExtendableOutput, Input};
|
||||||
@@ -13,7 +14,8 @@ use std::io::Read;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CommitGens<G: Group> {
|
pub struct CommitGens<G: Group> {
|
||||||
gens: Vec<G>,
|
gens: Vec<G::PreprocessedGroupElement>,
|
||||||
|
_p: PhantomData<G>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
@@ -31,14 +33,17 @@ impl<G: Group> CommitGens<G> {
|
|||||||
let mut shake = Shake256::default();
|
let mut shake = Shake256::default();
|
||||||
shake.input(label);
|
shake.input(label);
|
||||||
let mut reader = shake.xof_result();
|
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];
|
let mut uniform_bytes = [0u8; 64];
|
||||||
for _ in 0..n {
|
for _ in 0..n {
|
||||||
reader.read_exact(&mut uniform_bytes).unwrap();
|
reader.read_exact(&mut uniform_bytes).unwrap();
|
||||||
gens.push(G::from_uniform_bytes(&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.
|
//! This module implements the Nova traits for pallas::Point, pallas::Scalar, vesta::Point, vesta::Scalar.
|
||||||
use crate::traits::{ChallengeTrait, CompressedGroup, Group};
|
use crate::traits::{ChallengeTrait, CompressedGroup, Group};
|
||||||
|
use core::ops::Mul;
|
||||||
use ff::Field;
|
use ff::Field;
|
||||||
use merlin::Transcript;
|
use merlin::Transcript;
|
||||||
use pasta_curves::{
|
use pasta_curves::{
|
||||||
@@ -11,7 +12,6 @@ use pasta_curves::{
|
|||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
use rand_chacha::ChaCha20Rng;
|
use rand_chacha::ChaCha20Rng;
|
||||||
use rug::Integer;
|
use rug::Integer;
|
||||||
use std::{borrow::Borrow, ops::Mul};
|
|
||||||
|
|
||||||
//////////////////////////////////////Pallas///////////////////////////////////////////////
|
//////////////////////////////////////Pallas///////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -28,27 +28,21 @@ impl PallasCompressedElementWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for PallasCompressedElementWrapper {}
|
|
||||||
unsafe impl Sync for PallasCompressedElementWrapper {}
|
|
||||||
|
|
||||||
impl Group for pallas::Point {
|
impl Group for pallas::Point {
|
||||||
type Base = pallas::Base;
|
type Base = pallas::Base;
|
||||||
type Scalar = pallas::Scalar;
|
type Scalar = pallas::Scalar;
|
||||||
type CompressedGroupElement = PallasCompressedElementWrapper;
|
type CompressedGroupElement = PallasCompressedElementWrapper;
|
||||||
|
type PreprocessedGroupElement = pallas::Affine;
|
||||||
|
|
||||||
fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self
|
fn vartime_multiscalar_mul(
|
||||||
where
|
scalars: &[Self::Scalar],
|
||||||
I: IntoIterator,
|
bases: &[Self::PreprocessedGroupElement],
|
||||||
I::Item: Borrow<Self::Scalar>,
|
) -> Self {
|
||||||
J: IntoIterator,
|
|
||||||
J::Item: Borrow<Self>,
|
|
||||||
Self: Clone,
|
|
||||||
{
|
|
||||||
// Unoptimized.
|
// Unoptimized.
|
||||||
scalars
|
scalars
|
||||||
.into_iter()
|
.iter()
|
||||||
.zip(points)
|
.zip(bases)
|
||||||
.map(|(scalar, point)| (*point.borrow()).mul(*scalar.borrow()))
|
.map(|(scalar, base)| base.mul(scalar))
|
||||||
.fold(Ep::group_zero(), |acc, x| acc + x)
|
.fold(Ep::group_zero(), |acc, x| acc + x)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +50,7 @@ impl Group for pallas::Point {
|
|||||||
PallasCompressedElementWrapper::new(self.to_bytes())
|
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 {
|
if bytes.len() != 64 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@@ -64,7 +58,7 @@ impl Group for pallas::Point {
|
|||||||
arr.copy_from_slice(&bytes[0..32]);
|
arr.copy_from_slice(&bytes[0..32]);
|
||||||
|
|
||||||
let hash = Ep::hash_to_curve("from_uniform_bytes");
|
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 {
|
impl Group for vesta::Point {
|
||||||
type Base = vesta::Base;
|
type Base = vesta::Base;
|
||||||
type Scalar = vesta::Scalar;
|
type Scalar = vesta::Scalar;
|
||||||
type CompressedGroupElement = VestaCompressedElementWrapper;
|
type CompressedGroupElement = VestaCompressedElementWrapper;
|
||||||
|
type PreprocessedGroupElement = vesta::Affine;
|
||||||
|
|
||||||
fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self
|
fn vartime_multiscalar_mul(
|
||||||
where
|
scalars: &[Self::Scalar],
|
||||||
I: IntoIterator,
|
bases: &[Self::PreprocessedGroupElement],
|
||||||
I::Item: Borrow<Self::Scalar>,
|
) -> Self {
|
||||||
J: IntoIterator,
|
|
||||||
J::Item: Borrow<Self>,
|
|
||||||
Self: Clone,
|
|
||||||
{
|
|
||||||
// Unoptimized.
|
// Unoptimized.
|
||||||
scalars
|
scalars
|
||||||
.into_iter()
|
.iter()
|
||||||
.zip(points)
|
.zip(bases)
|
||||||
.map(|(scalar, point)| (*point.borrow()).mul(*scalar.borrow()))
|
.map(|(scalar, base)| base.mul(scalar))
|
||||||
.fold(Eq::group_zero(), |acc, x| acc + x)
|
.fold(Eq::group_zero(), |acc, x| acc + x)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +137,7 @@ impl Group for vesta::Point {
|
|||||||
VestaCompressedElementWrapper::new(self.to_bytes())
|
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 {
|
if bytes.len() != 64 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@@ -157,7 +145,7 @@ impl Group for vesta::Point {
|
|||||||
arr.copy_from_slice(&bytes[0..32]);
|
arr.copy_from_slice(&bytes[0..32]);
|
||||||
|
|
||||||
let hash = Eq::hash_to_curve("from_uniform_bytes");
|
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::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
/// Public parameters for a given R1CS
|
/// Public parameters for a given R1CS
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct R1CSGens<G: Group> {
|
pub struct R1CSGens<G: Group> {
|
||||||
pub(crate) gens_W: CommitGens<G>, // TODO: avoid pub(crate)
|
pub(crate) gens_W: CommitGens<G>, // TODO: avoid pub(crate)
|
||||||
pub(crate) gens_E: CommitGens<G>,
|
pub(crate) gens_E: CommitGens<G>,
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
//! This module defines various traits required by the users of the library to implement.
|
//! This module defines various traits required by the users of the library to implement.
|
||||||
use bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError};
|
use bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError};
|
||||||
use core::{
|
use core::{
|
||||||
borrow::Borrow,
|
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
|
ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
|
||||||
};
|
};
|
||||||
@@ -30,21 +29,21 @@ pub trait Group:
|
|||||||
/// A type representing the compressed version of the group element
|
/// A type representing the compressed version of the group element
|
||||||
type CompressedGroupElement: CompressedGroup<GroupElement = Self>;
|
type CompressedGroupElement: CompressedGroup<GroupElement = Self>;
|
||||||
|
|
||||||
|
/// A type representing preprocessed group element
|
||||||
|
type PreprocessedGroupElement;
|
||||||
|
|
||||||
/// A method to compute a multiexponentation
|
/// A method to compute a multiexponentation
|
||||||
fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self
|
fn vartime_multiscalar_mul(
|
||||||
where
|
scalars: &[Self::Scalar],
|
||||||
I: IntoIterator,
|
bases: &[Self::PreprocessedGroupElement],
|
||||||
I::Item: Borrow<Self::Scalar>,
|
) -> Self;
|
||||||
J: IntoIterator,
|
|
||||||
J::Item: Borrow<Self>,
|
|
||||||
Self: Clone;
|
|
||||||
|
|
||||||
/// Compresses the group element
|
/// Compresses the group element
|
||||||
fn compress(&self) -> Self::CompressedGroupElement;
|
fn compress(&self) -> Self::CompressedGroupElement;
|
||||||
|
|
||||||
/// Attempts to create a group element from a sequence of bytes,
|
/// 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
|
/// 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
|
/// Returns the affine coordinates (x, y, infinty) for the point
|
||||||
fn to_coordinates(&self) -> (Self::Base, Self::Base, bool);
|
fn to_coordinates(&self) -> (Self::Base, Self::Base, bool);
|
||||||
|
|||||||
Reference in New Issue
Block a user