Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiling to no_std #3

Merged
merged 8 commits into from
Nov 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ description = "A pure-Rust implementation of Bulletproofs using Ristretto"
edition = "2018"

[dependencies]
curve25519-dalek = { version = "3.0.0", default-features = false, features = ["u64_backend", "nightly", "serde", "alloc"] }
curve25519-dalek = { version = "3.0.0", default-features = false, features = ["u64_backend", "nightly", "alloc"] }
subtle = { version = "2", default-features = false }
sha3 = { version = "0.9.1", default-features = false }
digest = { version = "0.9.0", default-features = false }
digest = { version = "0.9.0", default-features = false, features = ["alloc"] }
rand_core = { version = "0.5", default-features = false, features = ["alloc"] }
rand = { version = "0.7", default-features = false, optional = true }
byteorder = { version = "1", default-features = false }
serde = { version = "1", default-features = false, features = ["alloc"] }
serde_derive = { version = "1", default-features = false }
# serde = { version = "1", default-features = false, features = ["alloc"] }
# serde_derive = { version = "1", default-features = false }
thiserror = { version = "1", optional = true }
merlin = { version = "2", default-features = false }
clear_on_drop = { version = "0.2", default-features = false, features = ["nightly"] }
Expand All @@ -38,7 +38,7 @@ bincode = "1"
rand_chacha = "0.2"

[features]
default = ["std", "yoloproofs"]
default = ["std"]
avx2_backend = ["curve25519-dalek/avx2_backend"]
yoloproofs = []
std = ["rand", "rand/std", "thiserror"]
Expand Down
13 changes: 6 additions & 7 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,12 @@ pub enum R1CSError {
/// a variable assignment is not provided when the prover needs it.
#[cfg_attr(feature = "std", error("Variable does not have a value assignment."))]
MissingAssignment,

/// Occurs when a gadget receives an inconsistent input.
#[cfg_attr(feature = "std", error("Gadget error: {description:?}"))]
GadgetError {
/// The description of the reasons for the error.
description: String,
},
// Occurs when a gadget receives an inconsistent input.
// #[cfg_attr(feature = "std", error("Gadget error: {description:?}"))]
// GadgetError {
// /// The description of the reasons for the error.
// description: String,
// },
}

#[cfg(feature = "yoloproofs")]
Expand Down
2 changes: 1 addition & 1 deletion src/generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::MultiscalarMul;
use digest::{XofReader, ExtendableOutputDirty, Update};
use digest::{ExtendableOutputDirty, Update, XofReader};
use sha3::{Sha3XofReader, Sha3_512, Shake256};

/// Represents a pair of base points for Pedersen commitments.
Expand Down
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
#![doc(html_logo_url = "https://doc.dalek.rs/assets/dalek-logo-clear.png")]
#![doc(html_root_url = "https://docs.rs/bulletproofs/2.0.0")]

#[macro_use]
extern crate alloc;

#[macro_use]
extern crate serde_derive;
// #[macro_use]
// extern crate serde_derive;

mod util;

Expand Down
5 changes: 4 additions & 1 deletion src/r1cs/constraint_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ pub trait ConstraintSystem {
/// Allocate a single variable using a closure, similar to `allocate`.
/// When allocating left variable, return left variable and None.
/// When allocating right variable, return right variable and output variable.
fn allocate_single(&mut self, assignment: Option<Scalar>) -> Result<(Variable, Option<Variable>), R1CSError>;
fn allocate_single(
&mut self,
assignment: Option<Scalar>,
) -> Result<(Variable, Option<Variable>), R1CSError>;
}

/// An extension to the constraint system trait that permits randomized constraints.
Expand Down
29 changes: 3 additions & 26 deletions src/r1cs/linear_combination.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
//! Definition of linear combinations.

use alloc::vec::Vec;
use core::iter::FromIterator;
use core::ops::{Add, Mul, Neg, Sub};
use curve25519_dalek::scalar::Scalar;
#[cfg(feature = "std")]
use std::collections::HashMap;
#[cfg(feature = "std")]
use std::iter::FromIterator;
#[cfg(feature = "std")]
use std::ops::{Add, Mul, Neg, Sub};

/// Represents a variable in a constraint system.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -119,26 +116,6 @@ impl LinearCombination {
pub fn get_terms(self) -> Vec<(Variable, Scalar)> {
self.terms
}

/// Simplify linear combination by taking Variables common across terms and adding their corresponding scalars.
/// Useful when linear combinations become large. Takes ownership of linear combination as this function is useful
/// when memory is limited and the obvious action after this function call will be to free the memory held by the old linear combination
#[cfg(feature = "std")]
pub fn simplify(self) -> Self {
// Build hashmap to hold unique variables with their values.
let mut vars: HashMap<Variable, Scalar> = HashMap::new();

let terms = self.get_terms();
for (var, val) in terms {
*vars.entry(var).or_insert(Scalar::zero()) += val;
}

let mut new_lc_terms = vec![];
for (var, val) in vars {
new_lc_terms.push((var, val));
}
new_lc_terms.iter().collect()
}
}

impl Default for LinearCombination {
Expand Down
87 changes: 44 additions & 43 deletions src/r1cs/proof.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![allow(non_snake_case)]
//! Definition of the proof struct.

use alloc::vec::Vec;
use curve25519_dalek::ristretto::CompressedRistretto;
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::{Identity, IsIdentity};
Expand All @@ -9,8 +10,8 @@ use crate::errors::R1CSError;
use crate::inner_product_proof::InnerProductProof;
use crate::util;

use serde::de::Visitor;
use serde::{self, Deserialize, Deserializer, Serialize, Serializer};
// use serde::de::Visitor;
// use serde::{self, Deserialize, Deserializer, Serialize, Serializer};

const ONE_PHASE_COMMITMENTS: u8 = 0;
const TWO_PHASE_COMMITMENTS: u8 = 1;
Expand Down Expand Up @@ -204,44 +205,44 @@ impl R1CSProof {
}
}

impl Serialize for R1CSProof {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(&self.to_bytes()[..])
}
}

impl<'de> Deserialize<'de> for R1CSProof {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct R1CSProofVisitor;

impl<'de> Visitor<'de> for R1CSProofVisitor {
type Value = R1CSProof;

fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
formatter.write_str("a valid R1CSProof")
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<R1CSProof, E>
where
E: serde::de::Error,
{
// Using Error::custom requires T: Display, which our error
// type only implements when it implements std::error::Error.
#[cfg(feature = "std")]
return R1CSProof::from_bytes(v).map_err(serde::de::Error::custom);
// In no-std contexts, drop the error message.
#[cfg(not(feature = "std"))]
return R1CSProof::from_bytes(v)
.map_err(|_| serde::de::Error::custom("deserialization error"));
}
}

deserializer.deserialize_bytes(R1CSProofVisitor)
}
}
// impl Serialize for R1CSProof {
// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
// where
// S: Serializer,
// {
// serializer.serialize_bytes(&self.to_bytes()[..])
// }
// }

// impl<'de> Deserialize<'de> for R1CSProof {
// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
// where
// D: Deserializer<'de>,
// {
// struct R1CSProofVisitor;

// impl<'de> Visitor<'de> for R1CSProofVisitor {
// type Value = R1CSProof;

// fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
// formatter.write_str("a valid R1CSProof")
// }

// fn visit_bytes<E>(self, v: &[u8]) -> Result<R1CSProof, E>
// where
// E: serde::de::Error,
// {
// // Using Error::custom requires T: Display, which our error
// // type only implements when it implements std::error::Error.
// #[cfg(feature = "std")]
// return R1CSProof::from_bytes(v).map_err(serde::de::Error::custom);
// // In no-std contexts, drop the error message.
// #[cfg(not(feature = "std"))]
// return R1CSProof::from_bytes(v)
// .map_err(|_| serde::de::Error::custom("deserialization error"));
// }
// }

// deserializer.deserialize_bytes(R1CSProofVisitor)
// }
// }
21 changes: 18 additions & 3 deletions src/r1cs/prover.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#![allow(non_snake_case)]

use alloc::boxed::Box;
use alloc::vec::Vec;
use clear_on_drop::clear::Clear;
use core::mem;
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::{Identity, MultiscalarMul};
use merlin::Transcript;
use rand_core::{CryptoRng, RngCore};

use super::{
ConstraintSystem, LinearCombination, R1CSProof, RandomizableConstraintSystem,
Expand All @@ -17,6 +20,9 @@ use crate::generators::{BulletproofGens, PedersenGens};
use crate::inner_product_proof::InnerProductProof;
use crate::transcript::TranscriptProtocol;

#[cfg(feature = "std")]
use rand::thread_rng;

/// A [`ConstraintSystem`] implementation for use by the prover.
///
/// The prover commits high-level variables and their blinding factors `(v, v_blinding)`,
Expand Down Expand Up @@ -407,9 +413,19 @@ impl<'t, 'g> Prover<'t, 'g> {
}

/// Consume this `ConstraintSystem` to produce a proof.
#[cfg(feature = "std")]
pub fn prove(mut self, bp_gens: &BulletproofGens) -> Result<R1CSProof, R1CSError> {
self.prove_with_rng(&bp_gens, &mut thread_rng())
}

/// Consume this `ConstraintSystem` to produce a proof.
pub fn prove_with_rng<T: RngCore + CryptoRng>(
mut self,
bp_gens: &BulletproofGens,
prng: &mut T,
) -> Result<R1CSProof, R1CSError> {
use crate::util;
use std::iter;
use core::iter;

// Commit a length _suffix_ for the number of high-level variables.
// We cannot do this in advance because user can commit variables one-by-one,
Expand Down Expand Up @@ -438,8 +454,7 @@ impl<'t, 'g> Prover<'t, 'g> {
builder = builder.rekey_with_witness_bytes(b"v_blinding", v_b.as_bytes());
}

use rand::thread_rng;
builder.finalize(&mut thread_rng())
builder.finalize(prng)
};

// Commit to the first-phase low-level witness variables.
Expand Down
27 changes: 23 additions & 4 deletions src/r1cs/verifier.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#![allow(non_snake_case)]

use alloc::boxed::Box;
use alloc::vec::Vec;
use core::mem;
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::VartimeMultiscalarMul;
use merlin::Transcript;
use rand_core::{CryptoRng, RngCore};

#[cfg(feature = "std")]
use rand::thread_rng;

use super::{
ConstraintSystem, LinearCombination, R1CSProof, RandomizableConstraintSystem,
Expand Down Expand Up @@ -121,6 +127,9 @@ impl<'t> ConstraintSystem for Verifier<'t> {
}

fn constrain(&mut self, lc: LinearCombination) {
// TODO: check that the linear combinations are valid
// (e.g. that variables are valid, that the linear combination
// evals to 0 for prover, etc).
self.constraints.push(lc);
}

Expand Down Expand Up @@ -347,17 +356,28 @@ impl<'t> Verifier<'t> {
}
}

#[cfg(feature = "std")]
pub fn verify(
mut self,
proof: &R1CSProof,
pc_gens: &PedersenGens,
bp_gens: &BulletproofGens,
) -> Result<(), R1CSError> {
self.verify_with_rng(proof, pc_gens, bp_gens, &mut thread_rng())
}

/// Consume this `VerifierCS` and attempt to verify the supplied `proof`.
/// The `pc_gens` and `bp_gens` are generators for Pedersen commitments and
/// Bulletproofs vector commitments, respectively. The
/// [`BulletproofGens`] should have `gens_capacity` greater than
/// the number of multiplication constraints that will eventually
/// be added into the constraint system.
pub fn verify(
pub fn verify_with_rng<T: RngCore + CryptoRng>(
mut self,
proof: &R1CSProof,
pc_gens: &PedersenGens,
bp_gens: &BulletproofGens,
prng: &mut T,
) -> Result<(), R1CSError> {
// Commit a length _suffix_ for the number of high-level variables.
// We cannot do this in advance because user can commit variables one-by-one,
Expand All @@ -384,7 +404,7 @@ impl<'t> Verifier<'t> {

use crate::inner_product_proof::inner_product;
use crate::util;
use std::iter;
use core::iter;

if bp_gens.gens_capacity < padded_n {
return Err(R1CSError::InvalidGeneratorsLength);
Expand Down Expand Up @@ -471,8 +491,7 @@ impl<'t> Verifier<'t> {
// Create a `TranscriptRng` from the transcript. The verifier
// has no witness data to commit, so this just mixes external
// randomness into the existing transcript.
use rand::thread_rng;
let mut rng = self.transcript.build_rng().finalize(&mut thread_rng());
let mut rng = self.transcript.build_rng().finalize(prng);
let r = Scalar::random(&mut rng);

let xx = x * x;
Expand Down
Loading