Browse Source

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>
main
porcuquine 3 years ago
committed by GitHub
parent
commit
de5b8d6598
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 93 additions and 85 deletions
  1. +2
    -4
      Cargo.toml
  2. +5
    -81
      src/lib.rs
  3. +86
    -0
      src/pasta.rs

+ 2
- 4
Cargo.toml

@ -12,13 +12,11 @@ keywords = ["zkSNARKs", "cryptography", "proofs"]
[dependencies]
merlin = "2.0.0"
rand = "0.7.3"
rand = "0.8.4"
digest = "0.8.1"
sha3 = "0.8.2"
rayon = "1.3.0"
rand_core = { version = "0.5", default-features = false }
itertools = "0.9.0"
subtle = "2.4"
[dev-dependencies]
curve25519-dalek = {version = "3.0.0", features = ["simd_backend"]}
pasta_curves = "0.2.1"

+ 5
- 81
src/lib.rs

@ -6,6 +6,7 @@
mod commitments;
pub mod errors;
pub mod pasta;
pub mod r1cs;
pub mod traits;
@ -125,88 +126,11 @@ impl FinalSNARK {
#[cfg(test)]
mod tests {
use super::*;
use crate::traits::{CompressedGroup, Group, PrimeField};
use core::borrow::Borrow;
use curve25519_dalek::traits::MultiscalarMul;
use rand::{rngs::OsRng, CryptoRng, RngCore};
type S = curve25519_dalek::scalar::Scalar;
type G = curve25519_dalek::ristretto::RistrettoPoint;
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;
use crate::traits::PrimeField;
use rand::rngs::OsRng;
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)
}
}
type S = pasta_curves::pallas::Scalar;
type G = pasta_curves::pallas::Point;
#[test]
fn test_tiny_r1cs() {

+ 86
- 0
src/pasta.rs

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

Loading…
Cancel
Save