Browse Source

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
main
Srinath Setty 2 years ago
committed by GitHub
parent
commit
bcbdec2982
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 47 deletions
  1. +1
    -1
      Cargo.toml
  2. +8
    -3
      src/commitments.rs
  3. +21
    -33
      src/pasta.rs
  4. +0
    -1
      src/r1cs.rs
  5. +8
    -9
      src/traits.rs

+ 1
- 1
Cargo.toml

@ -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"] }

+ 8
- 3
src/commitments.rs

@ -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 CommitGens {
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(),
}
} }
} }

+ 21
- 33
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
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. // Unoptimized.
scalars 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) .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
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. // Unoptimized.
scalars 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) .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())
} }
} }

+ 0
- 1
src/r1cs.rs

@ -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>,

+ 8
- 9
src/traits.rs

@ -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
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 /// 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);

Loading…
Cancel
Save