mirror of
https://github.com/arnaucube/Nova.git
synced 2026-01-12 09:01:28 +01:00
Support Pasta curves. (#4)
* Support pasta curves directly. * Upgrade rand. * Simplify. * Don't deny missing docs. Co-authored-by: porcuquine <porcuquine@users.noreply.github.com>
This commit is contained in:
@@ -12,13 +12,11 @@ keywords = ["zkSNARKs", "cryptography", "proofs"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
merlin = "2.0.0"
|
merlin = "2.0.0"
|
||||||
rand = "0.7.3"
|
rand = "0.8.4"
|
||||||
digest = "0.8.1"
|
digest = "0.8.1"
|
||||||
sha3 = "0.8.2"
|
sha3 = "0.8.2"
|
||||||
rayon = "1.3.0"
|
rayon = "1.3.0"
|
||||||
rand_core = { version = "0.5", default-features = false }
|
rand_core = { version = "0.5", default-features = false }
|
||||||
itertools = "0.9.0"
|
itertools = "0.9.0"
|
||||||
subtle = "2.4"
|
subtle = "2.4"
|
||||||
|
pasta_curves = "0.2.1"
|
||||||
[dev-dependencies]
|
|
||||||
curve25519-dalek = {version = "3.0.0", features = ["simd_backend"]}
|
|
||||||
|
|||||||
86
src/lib.rs
86
src/lib.rs
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
mod commitments;
|
mod commitments;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
pub mod pasta;
|
||||||
pub mod r1cs;
|
pub mod r1cs;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
|
|
||||||
@@ -125,88 +126,11 @@ impl<G: Group> FinalSNARK<G> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::traits::{CompressedGroup, Group, PrimeField};
|
use crate::traits::PrimeField;
|
||||||
use core::borrow::Borrow;
|
use rand::rngs::OsRng;
|
||||||
use curve25519_dalek::traits::MultiscalarMul;
|
|
||||||
use rand::{rngs::OsRng, CryptoRng, RngCore};
|
|
||||||
|
|
||||||
type S = curve25519_dalek::scalar::Scalar;
|
type S = pasta_curves::pallas::Scalar;
|
||||||
type G = curve25519_dalek::ristretto::RistrettoPoint;
|
type G = pasta_curves::pallas::Point;
|
||||||
type C = curve25519_dalek::ristretto::CompressedRistretto;
|
|
||||||
|
|
||||||
impl Group for G {
|
|
||||||
type Scalar = S;
|
|
||||||
type CompressedGroupElement = C;
|
|
||||||
|
|
||||||
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,
|
|
||||||
{
|
|
||||||
Self::multiscalar_mul(scalars, points)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compress(&self) -> Self::CompressedGroupElement {
|
|
||||||
self.compress()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_uniform_bytes(bytes: &[u8]) -> Option<Self> {
|
|
||||||
if bytes.len() != 64 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let mut arr = [0; 64];
|
|
||||||
arr.copy_from_slice(&bytes[0..64]);
|
|
||||||
Some(Self::from_uniform_bytes(&arr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PrimeField for S {
|
|
||||||
fn zero() -> Self {
|
|
||||||
S::zero()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn one() -> Self {
|
|
||||||
S::one()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_bytes_mod_order_wide(bytes: &[u8]) -> Option<Self> {
|
|
||||||
if bytes.len() != 64 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let mut arr = [0; 64];
|
|
||||||
arr.copy_from_slice(&bytes[0..64]);
|
|
||||||
Some(Self::from_bytes_mod_order_wide(&arr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn random(rng: &mut (impl RngCore + CryptoRng)) -> Self {
|
|
||||||
S::random(rng)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CompressedGroup for C {
|
|
||||||
type GroupElement = G;
|
|
||||||
|
|
||||||
fn decompress(&self) -> Option<Self::GroupElement> {
|
|
||||||
self.decompress()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_bytes(&self) -> &[u8] {
|
|
||||||
self.as_bytes()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ChallengeTrait for S {
|
|
||||||
fn challenge(label: &'static [u8], transcript: &mut Transcript) -> Self {
|
|
||||||
let mut buf = [0u8; 64];
|
|
||||||
transcript.challenge_bytes(label, &mut buf);
|
|
||||||
S::from_bytes_mod_order_wide(&buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_tiny_r1cs() {
|
fn test_tiny_r1cs() {
|
||||||
|
|||||||
86
src/pasta.rs
Normal file
86
src/pasta.rs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
//! This module implements the Nova traits for pallas::Point and pallas::Scalar.
|
||||||
|
use crate::traits::{ChallengeTrait, CompressedGroup, Group, PrimeField};
|
||||||
|
use merlin::Transcript;
|
||||||
|
use pasta_curves::arithmetic::{CurveExt, FieldExt, Group as Grp};
|
||||||
|
use pasta_curves::group::GroupEncoding;
|
||||||
|
use pasta_curves::{self, pallas, Ep, Fq};
|
||||||
|
use rand::{CryptoRng, RngCore};
|
||||||
|
use std::borrow::Borrow;
|
||||||
|
use std::ops::Mul;
|
||||||
|
|
||||||
|
impl Group for pallas::Point {
|
||||||
|
type Scalar = pallas::Scalar;
|
||||||
|
type CompressedGroupElement = <pallas::Point as GroupEncoding>::Repr;
|
||||||
|
|
||||||
|
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,
|
||||||
|
{
|
||||||
|
// Unoptimized.
|
||||||
|
scalars
|
||||||
|
.into_iter()
|
||||||
|
.zip(points)
|
||||||
|
.map(|(scalar, point)| (*point.borrow()).mul(*scalar.borrow()))
|
||||||
|
.fold(Ep::group_zero(), |acc, x| acc + x)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compress(&self) -> Self::CompressedGroupElement {
|
||||||
|
self.to_bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_uniform_bytes(bytes: &[u8]) -> Option<Self> {
|
||||||
|
if bytes.len() != 64 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let mut arr = [0; 32];
|
||||||
|
arr.copy_from_slice(&bytes[0..32]);
|
||||||
|
|
||||||
|
let hash = Ep::hash_to_curve("from_uniform_bytes");
|
||||||
|
Some(hash(&arr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrimeField for pallas::Scalar {
|
||||||
|
fn zero() -> Self {
|
||||||
|
Fq::zero()
|
||||||
|
}
|
||||||
|
fn one() -> Self {
|
||||||
|
Fq::one()
|
||||||
|
}
|
||||||
|
fn from_bytes_mod_order_wide(bytes: &[u8]) -> Option<Self> {
|
||||||
|
if bytes.len() != 64 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let mut arr = [0; 64];
|
||||||
|
arr.copy_from_slice(&bytes[0..64]);
|
||||||
|
Some(Fq::from_bytes_wide(&arr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn random(_rng: &mut (impl RngCore + CryptoRng)) -> Self {
|
||||||
|
Fq::rand()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChallengeTrait for pallas::Scalar {
|
||||||
|
fn challenge(label: &'static [u8], transcript: &mut Transcript) -> Self {
|
||||||
|
let mut buf = [0u8; 64];
|
||||||
|
transcript.challenge_bytes(label, &mut buf);
|
||||||
|
pallas::Scalar::from_bytes_mod_order_wide(&buf).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompressedGroup for <pallas::Point as GroupEncoding>::Repr {
|
||||||
|
type GroupElement = pallas::Point;
|
||||||
|
fn decompress(&self) -> Option<<Self as CompressedGroup>::GroupElement> {
|
||||||
|
Some(Ep::from_bytes(&self).unwrap())
|
||||||
|
}
|
||||||
|
fn as_bytes(&self) -> &[u8] {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user