diff --git a/CHANGELOG.md b/CHANGELOG.md index 15c2dbd2..7edbe28c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ Entries are listed in reverse chronological order. +## 2.0.0 + +* Switch from `failure` to `std`-compatible errors via `thiserror`. +* Update `rand`, `curve25519-dalek`, `merlin` versions. +* Adds `no_std` support by @xoloki. + ## 1.0.4 * Change doc-include paths to allow compilation on the latest Rust nightly diff --git a/Cargo.toml b/Cargo.toml index 83b90e3a..2cc94403 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,11 @@ [package] name = "bulletproofs" -version = "1.0.4" +# Before doing a release: +# - update version field +# - update html_root_url +# - ensure yoloproofs was disabled in an atomic (revertable) commit +# - update CHANGELOG +version = "2.0.0" authors = ["Cathie Yun ", "Henry de Valence ", "Oleg Andreev "] @@ -10,33 +15,33 @@ repository = "https://github.com/dalek-cryptography/bulletproofs" categories = ["cryptography"] keywords = ["cryptography", "crypto", "ristretto", "zero-knowledge", "bulletproofs"] description = "A pure-Rust implementation of Bulletproofs using Ristretto" +edition = "2018" [dependencies] -curve25519-dalek = { version = "1.0.3", features = ["serde"] } -subtle = "2" -sha3 = "0.8" -digest = "0.8" -rand = "0.6" -byteorder = "1" -serde = "1" -serde_derive = "1" -failure = "0.1" -merlin = "1.1" -clear_on_drop = "0.2" +curve25519-dalek = { version = "2", default-features = false, features = ["u64_backend", "nightly", "serde", "alloc"] } +subtle = { version = "2", default-features = false } +sha3 = { version = "0.8", default-features = false } +digest = { version = "0.8", default-features = false } +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 } +thiserror = { version = "1", optional = true } +merlin = { version = "2", default-features = false } +clear_on_drop = { version = "0.2", default-features = false, features = ["nightly"] } [dev-dependencies] hex = "0.3" -criterion = "0.2" +criterion = "0.3" bincode = "1" -rand_chacha = "0.1" +rand_chacha = "0.2" [features] +default = ["std", "avx2_backend"] avx2_backend = ["curve25519-dalek/avx2_backend"] -# Disable the yoloproofs feature in the released crate. -# To test it, use a git dependency on the develop branch and enable the -# yoloproofs feature. Note that this means it's impossible to publish a crate -# depending on the unstable R1CS API. -#yoloproofs = [] +# yoloproofs = [] +std = ["rand", "rand/std", "thiserror"] [[test]] name = "range_proof" diff --git a/benches/generators.rs b/benches/generators.rs index 47af5b5a..0b2bbfdb 100644 --- a/benches/generators.rs +++ b/benches/generators.rs @@ -1,4 +1,3 @@ -extern crate bulletproofs; use bulletproofs::{BulletproofGens, PedersenGens}; #[macro_use] diff --git a/benches/r1cs.rs b/benches/r1cs.rs index c4dade19..356a6527 100644 --- a/benches/r1cs.rs +++ b/benches/r1cs.rs @@ -23,7 +23,8 @@ use bulletproofs::{BulletproofGens, PedersenGens}; use curve25519_dalek::ristretto::CompressedRistretto; use curve25519_dalek::scalar::Scalar; use merlin::Transcript; -use rand::{thread_rng, Rng}; +use rand::seq::SliceRandom; +use rand::Rng; // Shuffle gadget (documented in markdown file) @@ -177,7 +178,7 @@ fn bench_kshuffle_prove(c: &mut Criterion) { .map(|_| Scalar::from(rng.gen_range(min, max))) .collect(); let mut output = input.clone(); - rand::thread_rng().shuffle(&mut output); + output.shuffle(&mut rand::thread_rng()); // Make kshuffle proof b.iter(|| { @@ -219,7 +220,7 @@ fn bench_kshuffle_verify(c: &mut Criterion) { .map(|_| Scalar::from(rng.gen_range(min, max))) .collect(); let mut output = input.clone(); - rand::thread_rng().shuffle(&mut output); + output.shuffle(&mut rand::thread_rng()); let mut prover_transcript = Transcript::new(b"ShuffleBenchmark"); diff --git a/benches/range_proof.rs b/benches/range_proof.rs index fe3f82c0..5ab246ec 100644 --- a/benches/range_proof.rs +++ b/benches/range_proof.rs @@ -3,16 +3,13 @@ extern crate criterion; use criterion::Criterion; -extern crate rand; +use rand; use rand::Rng; -extern crate curve25519_dalek; use curve25519_dalek::scalar::Scalar; -extern crate merlin; use merlin::Transcript; -extern crate bulletproofs; use bulletproofs::RangeProof; use bulletproofs::{BulletproofGens, PedersenGens}; diff --git a/docs/notes-r1cs.md b/docs/notes-r1cs.md index db48b539..767a0961 100644 --- a/docs/notes-r1cs.md +++ b/docs/notes-r1cs.md @@ -254,8 +254,7 @@ the proof would still work if \\({\mathbf{a}}\_{O}\\) was rearranged on the righ If we reorder terms, we get: \\[ -w\_c + \langle \mathbf{w}\_V, \mathbf{v} \rangle -= +w\_c + \langle \mathbf{w}\_V, \mathbf{v} \rangle = \langle \mathbf{a}\_L \circ \mathbf{a}\_R, \mathbf{y}^n \rangle - \langle \mathbf{a}\_O, \mathbf{y}^n \rangle + \langle \mathbf{w}\_L, \mathbf{a}\_L \rangle + @@ -266,8 +265,7 @@ w\_c + \langle \mathbf{w}\_V, \mathbf{v} \rangle Merge the statements containing \\(\mathbf{a}\_O \\): \\[ -w\_c + \langle \mathbf{w}\_V, \mathbf{v} \rangle -= +w\_c + \langle \mathbf{w}\_V, \mathbf{v} \rangle = \langle \mathbf{a}\_L \circ \mathbf{a}\_R, \mathbf{y}^n \rangle + \langle \mathbf{a}\_L, \mathbf{w}\_L \rangle + \langle \mathbf{a}\_O, -\mathbf{y}^n + \mathbf{w}\_O \rangle + @@ -278,8 +276,7 @@ Rearrange \\(\langle \mathbf{a}\_L \circ \mathbf{a}\_R, \mathbf{y}^n \rangle\\) \\(\langle \mathbf{a}\_L, \mathbf{y}^n \circ \mathbf{a}\_R \rangle\\): \\[ -w\_c + \langle \mathbf{w}\_V, \mathbf{v} \rangle -= +w\_c + \langle \mathbf{w}\_V, \mathbf{v} \rangle = \langle \mathbf{a}\_L, \mathbf{y}^n \circ \mathbf{a}\_R \rangle + \langle \mathbf{a}\_L, \mathbf{w}\_L \rangle + \langle \mathbf{a}\_O, -\mathbf{y}^n + \mathbf{w}\_O \rangle + @@ -290,8 +287,7 @@ Multiply the \\( \langle \mathbf{a}\_R, \mathbf{w}\_R \rangle \\) term by \\(\mathbf{y}^n\\) one one side of the inner product and by \\(\mathbf{y}^{-n}\\) on the other side: \\[ -w\_c + \langle \mathbf{w}\_V, \mathbf{v} \rangle -= +w\_c + \langle \mathbf{w}\_V, \mathbf{v} \rangle = \langle \mathbf{a}\_L, \mathbf{y}^n \circ \mathbf{a}\_R \rangle + \langle \mathbf{a}\_L, \mathbf{w}\_L \rangle + \langle \mathbf{a}\_O, -\mathbf{y}^n + \mathbf{w}\_O \rangle + @@ -301,8 +297,7 @@ w\_c + \langle \mathbf{w}\_V, \mathbf{v} \rangle Merge the statements containing \\(\mathbf{y}^n \circ \mathbf{a}\_R\\): \\[ -w\_c + \langle \mathbf{w}\_V, \mathbf{v} \rangle -= +w\_c + \langle \mathbf{w}\_V, \mathbf{v} \rangle = \langle \mathbf{a}\_L + \mathbf{y}^{-n} \circ \mathbf{w}\_R, \mathbf{y}^n \circ \mathbf{a}\_R \rangle + \langle \mathbf{a}\_L, \mathbf{w}\_L \rangle + \langle \mathbf{a}\_O, -\mathbf{y}^n + \mathbf{w}\_O \rangle diff --git a/src/errors.rs b/src/errors.rs index ca70e31e..776915d1 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,28 +1,41 @@ //! Errors related to proving and verifying proofs. +extern crate alloc; +use alloc::vec::Vec; + +#[cfg(feature = "std")] +use thiserror::Error; + /// Represents an error in proof creation, verification, or parsing. -#[derive(Fail, Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "std", derive(Error))] pub enum ProofError { /// This error occurs when a proof failed to verify. - #[fail(display = "Proof verification failed.")] + #[cfg_attr(feature = "std", error("Proof verification failed."))] VerificationError, /// This error occurs when the proof encoding is malformed. - #[fail(display = "Proof data could not be parsed.")] + #[cfg_attr(feature = "std", error("Proof data could not be parsed."))] FormatError, /// This error occurs during proving if the number of blinding /// factors does not match the number of values. - #[fail(display = "Wrong number of blinding factors supplied.")] + #[cfg_attr(feature = "std", error("Wrong number of blinding factors supplied."))] WrongNumBlindingFactors, /// This error occurs when attempting to create a proof with /// bitsize other than \\(8\\), \\(16\\), \\(32\\), or \\(64\\). - #[fail(display = "Invalid bitsize, must have n = 8,16,32,64.")] + #[cfg_attr(feature = "std", error("Invalid bitsize, must have n = 8,16,32,64."))] InvalidBitsize, /// This error occurs when attempting to create an aggregated /// proof with non-power-of-two aggregation size. - #[fail(display = "Invalid aggregation size, m must be a power of 2.")] + #[cfg_attr( + feature = "std", + error("Invalid aggregation size, m must be a power of 2.") + )] InvalidAggregation, /// This error occurs when there are insufficient generators for the proof. - #[fail(display = "Invalid generators size, too few generators for proof")] + #[cfg_attr( + feature = "std", + error("Invalid generators size, too few generators for proof") + )] InvalidGeneratorsLength, /// This error results from an internal error during proving. /// @@ -30,7 +43,7 @@ pub enum ProofError { /// multiparty computation with ourselves. However, because the /// MPC protocol is not exposed by the single-party API, we /// consider its errors to be internal errors. - #[fail(display = "Internal error during proof creation: {}", _0)] + #[cfg_attr(feature = "std", error("Internal error during proof creation: {0}"))] ProvingError(MPCError), } @@ -52,38 +65,48 @@ impl From for ProofError { /// API: although the MPC protocol is used internally for single-party /// proving, its API should not expose the complexity of the MPC /// protocol. -#[derive(Fail, Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "std", derive(Error))] pub enum MPCError { /// This error occurs when the dealer gives a zero challenge, /// which would annihilate the blinding factors. - #[fail(display = "Dealer gave a malicious challenge value.")] + #[cfg_attr(feature = "std", error("Dealer gave a malicious challenge value."))] MaliciousDealer, /// This error occurs when attempting to create a proof with /// bitsize other than \\(8\\), \\(16\\), \\(32\\), or \\(64\\). - #[fail(display = "Invalid bitsize, must have n = 8,16,32,64")] + #[cfg_attr(feature = "std", error("Invalid bitsize, must have n = 8,16,32,64"))] InvalidBitsize, /// This error occurs when attempting to create an aggregated /// proof with non-power-of-two aggregation size. - #[fail(display = "Invalid aggregation size, m must be a power of 2")] + #[cfg_attr( + feature = "std", + error("Invalid aggregation size, m must be a power of 2") + )] InvalidAggregation, /// This error occurs when there are insufficient generators for the proof. - #[fail(display = "Invalid generators size, too few generators for proof")] + #[cfg_attr( + feature = "std", + error("Invalid generators size, too few generators for proof") + )] InvalidGeneratorsLength, /// This error occurs when the dealer is given the wrong number of /// value commitments. - #[fail(display = "Wrong number of value commitments")] + #[cfg_attr(feature = "std", error("Wrong number of value commitments"))] WrongNumBitCommitments, /// This error occurs when the dealer is given the wrong number of /// polynomial commitments. - #[fail(display = "Wrong number of value commitments")] + #[cfg_attr(feature = "std", error("Wrong number of value commitments"))] WrongNumPolyCommitments, /// This error occurs when the dealer is given the wrong number of /// proof shares. - #[fail(display = "Wrong number of proof shares")] + #[cfg_attr(feature = "std", error("Wrong number of proof shares"))] WrongNumProofShares, /// This error occurs when one or more parties submit malformed /// proof shares. - #[fail(display = "Malformed proof shares from parties {:?}", bad_shares)] + #[cfg_attr( + feature = "std", + error("Malformed proof shares from parties {bad_shares:?}") + )] MalformedProofShares { /// A vector with the indexes of the parties whose shares were malformed. bad_shares: Vec, @@ -94,27 +117,31 @@ pub enum MPCError { /// /// XXX: should this be separate from a `ProofError`? #[cfg(feature = "yoloproofs")] -#[derive(Fail, Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "std", derive(Error))] pub enum R1CSError { /// Occurs when there are insufficient generators for the proof. - #[fail(display = "Invalid generators size, too few generators for proof")] + #[cfg_attr( + feature = "std", + error("Invalid generators size, too few generators for proof") + )] InvalidGeneratorsLength, /// This error occurs when the proof encoding is malformed. - #[fail(display = "Proof data could not be parsed.")] + #[cfg_attr(feature = "std", error("Proof data could not be parsed."))] FormatError, /// Occurs when verification of an /// [`R1CSProof`](::r1cs::R1CSProof) fails. - #[fail(display = "R1CSProof did not verify correctly.")] + #[cfg_attr(feature = "std", error("R1CSProof did not verify correctly."))] VerificationError, /// Occurs when trying to use a missing variable assignment. /// Used by gadgets that build the constraint system to signal that /// a variable assignment is not provided when the prover needs it. - #[fail(display = "Variable does not have a value assignment.")] + #[cfg_attr(feature = "std", error("Variable does not have a value assignment."))] MissingAssignment, /// Occurs when a gadget receives an inconsistent input. - #[fail(display = "Gadget error: {:?}", description)] + #[cfg_attr(feature = "std", error("Gadget error: {description:?}"))] GadgetError { /// The description of the reasons for the error. description: String, diff --git a/src/generators.rs b/src/generators.rs index 10937917..6e936562 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -4,12 +4,14 @@ #![allow(non_snake_case)] #![deny(missing_docs)] +extern crate alloc; + +use alloc::vec::Vec; use curve25519_dalek::constants::RISTRETTO_BASEPOINT_COMPRESSED; use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT; use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; use curve25519_dalek::traits::MultiscalarMul; - use digest::{ExtendableOutput, Input, XofReader}; use sha3::{Sha3XofReader, Sha3_512, Shake256}; @@ -165,7 +167,7 @@ impl BulletproofGens { /// Returns j-th share of generators, with an appropriate /// slice of vectors G and H for the j-th range proof. - pub fn share(&self, j: usize) -> BulletproofGensShare { + pub fn share(&self, j: usize) -> BulletproofGensShare<'_> { BulletproofGensShare { gens: &self, share: j, @@ -251,7 +253,7 @@ impl<'a> Iterator for AggregatedGensIter<'a> { } fn size_hint(&self) -> (usize, Option) { - let size = self.n * self.m; + let size = self.n * (self.m - self.party_idx) - self.gen_idx; (size, Some(size)) } } diff --git a/src/inner_product_proof.rs b/src/inner_product_proof.rs index e42ee6ce..5d1eb594 100644 --- a/src/inner_product_proof.rs +++ b/src/inner_product_proof.rs @@ -1,16 +1,19 @@ #![allow(non_snake_case)] #![doc(include = "../docs/inner-product-protocol.md")] -use std::borrow::Borrow; -use std::iter; +extern crate alloc; +use alloc::borrow::Borrow; +use alloc::vec::Vec; + +use core::iter; use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint}; use curve25519_dalek::scalar::Scalar; use curve25519_dalek::traits::VartimeMultiscalarMul; use merlin::Transcript; -use errors::ProofError; -use transcript::TranscriptProtocol; +use crate::errors::ProofError; +use crate::transcript::TranscriptProtocol; #[derive(Clone, Debug)] pub struct InnerProductProof { @@ -346,6 +349,21 @@ impl InnerProductProof { buf } + /// Converts the proof into a byte iterator over serialized view of the proof. + /// The layout of the inner product proof is: + /// * \\(n\\) pairs of compressed Ristretto points \\(L_0, R_0 \dots, L_{n-1}, R_{n-1}\\), + /// * two scalars \\(a, b\\). + #[inline] + pub(crate) fn to_bytes_iter(&self) -> impl Iterator + '_ { + self.L_vec + .iter() + .zip(self.R_vec.iter()) + .flat_map(|(l, r)| l.as_bytes().iter().chain(r.as_bytes())) + .chain(self.a.as_bytes()) + .chain(self.b.as_bytes()) + .copied() + } + /// Deserializes the proof from a byte slice. /// Returns an error in the following cases: /// * the slice does not have \\(2n+2\\) 32-byte elements, @@ -369,7 +387,7 @@ impl InnerProductProof { return Err(ProofError::FormatError); } - use util::read32; + use crate::util::read32; let mut L_vec: Vec = Vec::with_capacity(lg_n); let mut R_vec: Vec = Vec::with_capacity(lg_n); @@ -409,13 +427,13 @@ pub fn inner_product(a: &[Scalar], b: &[Scalar]) -> Scalar { mod tests { use super::*; + use crate::util; use sha3::Sha3_512; - use util; fn test_helper_create(n: usize) { let mut rng = rand::thread_rng(); - use generators::BulletproofGens; + use crate::generators::BulletproofGens; let bp_gens = BulletproofGens::new(n, 1); let G: Vec = bp_gens.share(0).G(n).cloned().collect(); let H: Vec = bp_gens.share(0).H(n).cloned().collect(); diff --git a/src/lib.rs b/src/lib.rs index 82d760d6..41b1edd0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,29 +1,16 @@ +#![cfg_attr(not(feature = "std"), no_std)] #![feature(nll)] #![feature(external_doc)] #![feature(try_trait)] #![deny(missing_docs)] #![doc(include = "../README.md")] #![doc(html_logo_url = "https://doc.dalek.rs/assets/dalek-logo-clear.png")] +#![doc(html_root_url = "https://docs.rs/bulletproofs/2.0.0")] -extern crate byteorder; -extern crate core; -extern crate digest; -extern crate rand; -extern crate sha3; +extern crate alloc; -extern crate clear_on_drop; -extern crate curve25519_dalek; -extern crate merlin; -extern crate subtle; #[macro_use] extern crate serde_derive; -extern crate serde; - -#[macro_use] -extern crate failure; - -#[cfg(test)] -extern crate bincode; mod util; @@ -43,17 +30,18 @@ mod inner_product_proof; mod range_proof; mod transcript; -pub use errors::ProofError; -pub use generators::{BulletproofGens, BulletproofGensShare, PedersenGens}; -pub use range_proof::RangeProof; +pub use crate::errors::ProofError; +pub use crate::generators::{BulletproofGens, BulletproofGensShare, PedersenGens}; +pub use crate::range_proof::RangeProof; #[doc(include = "../docs/aggregation-api.md")] pub mod range_proof_mpc { - pub use errors::MPCError; - pub use range_proof::dealer; - pub use range_proof::messages; - pub use range_proof::party; + pub use crate::errors::MPCError; + pub use crate::range_proof::dealer; + pub use crate::range_proof::messages; + pub use crate::range_proof::party; } #[cfg(feature = "yoloproofs")] +#[cfg(feature = "std")] pub mod r1cs; diff --git a/src/r1cs/constraint_system.rs b/src/r1cs/constraint_system.rs index 276bdbdf..cf327f26 100644 --- a/src/r1cs/constraint_system.rs +++ b/src/r1cs/constraint_system.rs @@ -66,6 +66,9 @@ pub trait ConstraintSystem { input_assignments: Option<(Scalar, Scalar)>, ) -> Result<(Variable, Variable, Variable), R1CSError>; + /// Counts the amount of allocated multipliers. + fn multipliers_len(&self) -> usize; + /// Enforce the explicit constraint that /// ```text /// lc = 0 diff --git a/src/r1cs/mod.rs b/src/r1cs/mod.rs index 72f88606..cb140e09 100644 --- a/src/r1cs/mod.rs +++ b/src/r1cs/mod.rs @@ -17,4 +17,4 @@ pub use self::proof::R1CSProof; pub use self::prover::Prover; pub use self::verifier::Verifier; -pub use errors::R1CSError; +pub use crate::errors::R1CSError; diff --git a/src/r1cs/proof.rs b/src/r1cs/proof.rs index dd24de69..6bf0817c 100644 --- a/src/r1cs/proof.rs +++ b/src/r1cs/proof.rs @@ -5,9 +5,9 @@ use curve25519_dalek::ristretto::CompressedRistretto; use curve25519_dalek::scalar::Scalar; use curve25519_dalek::traits::{Identity, IsIdentity}; -use errors::R1CSError; -use inner_product_proof::InnerProductProof; -use util; +use crate::errors::R1CSError; +use crate::inner_product_proof::InnerProductProof; +use crate::util; use serde::de::Visitor; use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; @@ -104,8 +104,7 @@ impl R1CSProof { buf.extend_from_slice(self.t_x.as_bytes()); buf.extend_from_slice(self.t_x_blinding.as_bytes()); buf.extend_from_slice(self.e_blinding.as_bytes()); - // XXX this costs an extra alloc - buf.extend_from_slice(self.ipp_proof.to_bytes().as_slice()); + buf.extend(self.ipp_proof.to_bytes_iter()); buf } @@ -232,7 +231,14 @@ impl<'de> Deserialize<'de> for R1CSProof { where E: serde::de::Error, { - R1CSProof::from_bytes(v).map_err(serde::de::Error::custom) + // 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")); } } diff --git a/src/r1cs/prover.rs b/src/r1cs/prover.rs index 9acd3a1d..bee4a945 100644 --- a/src/r1cs/prover.rs +++ b/src/r1cs/prover.rs @@ -12,10 +12,10 @@ use super::{ RandomizedConstraintSystem, Variable, }; -use errors::R1CSError; -use generators::{BulletproofGens, PedersenGens}; -use inner_product_proof::InnerProductProof; -use transcript::TranscriptProtocol; +use crate::errors::R1CSError; +use crate::generators::{BulletproofGens, PedersenGens}; +use crate::inner_product_proof::InnerProductProof; +use crate::transcript::TranscriptProtocol; /// A [`ConstraintSystem`] implementation for use by the prover. /// @@ -44,7 +44,7 @@ pub struct Prover<'t, 'g> { /// This list holds closures that will be called in the second phase of the protocol, /// when non-randomized variables are committed. - deferred_constraints: Vec) -> Result<(), R1CSError>>>, + deferred_constraints: Vec) -> Result<(), R1CSError>>>, /// Index of a pending multiplier that's not fully assigned yet. pending_multiplier: Option, @@ -158,6 +158,10 @@ impl<'t, 'g> ConstraintSystem for Prover<'t, 'g> { Ok((l_var, r_var, o_var)) } + fn multipliers_len(&self) -> usize { + self.a_L.len() + } + 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). @@ -201,6 +205,10 @@ impl<'t, 'g> ConstraintSystem for RandomizingProver<'t, 'g> { self.prover.allocate_multiplier(input_assignments) } + fn multipliers_len(&self) -> usize { + self.prover.multipliers_len() + } + fn constrain(&mut self, lc: LinearCombination) { self.prover.constrain(lc) } @@ -370,8 +378,8 @@ impl<'t, 'g> Prover<'t, 'g> { /// Consume this `ConstraintSystem` to produce a proof. pub fn prove(mut self, bp_gens: &BulletproofGens) -> Result { + use crate::util; use std::iter; - use util; // 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, diff --git a/src/r1cs/verifier.rs b/src/r1cs/verifier.rs index af17f55e..9e4aa411 100644 --- a/src/r1cs/verifier.rs +++ b/src/r1cs/verifier.rs @@ -11,9 +11,9 @@ use super::{ RandomizedConstraintSystem, Variable, }; -use errors::R1CSError; -use generators::{BulletproofGens, PedersenGens}; -use transcript::TranscriptProtocol; +use crate::errors::R1CSError; +use crate::generators::{BulletproofGens, PedersenGens}; +use crate::transcript::TranscriptProtocol; /// A [`ConstraintSystem`] implementation for use by the verifier. /// @@ -42,7 +42,7 @@ pub struct Verifier<'t> { /// when non-randomized variables are committed. /// After that, the option will flip to None and additional calls to `randomize_constraints` /// will invoke closures immediately. - deferred_constraints: Vec) -> Result<(), R1CSError>>>, + deferred_constraints: Vec) -> Result<(), R1CSError>>>, /// Index of a pending multiplier that's not fully assigned yet. pending_multiplier: Option, @@ -116,6 +116,10 @@ impl<'t> ConstraintSystem for Verifier<'t> { Ok((l_var, r_var, o_var)) } + fn multipliers_len(&self) -> usize { + self.num_vars + } + fn constrain(&mut self, lc: LinearCombination) { // TODO: check that the linear combinations are valid // (e.g. that variables are valid, that the linear combination @@ -160,6 +164,10 @@ impl<'t> ConstraintSystem for RandomizingVerifier<'t> { self.verifier.allocate_multiplier(input_assignments) } + fn multipliers_len(&self) -> usize { + self.verifier.multipliers_len() + } + fn constrain(&mut self, lc: LinearCombination) { self.verifier.constrain(lc) } @@ -347,9 +355,9 @@ impl<'t> Verifier<'t> { let padded_n = self.num_vars.next_power_of_two(); let pad = padded_n - n; - use inner_product_proof::inner_product; + use crate::inner_product_proof::inner_product; + use crate::util; use std::iter; - use util; if bp_gens.gens_capacity < padded_n { return Err(R1CSError::InvalidGeneratorsLength); diff --git a/src/range_proof/dealer.rs b/src/range_proof/dealer.rs index 6023db70..00c6691e 100644 --- a/src/range_proof/dealer.rs +++ b/src/range_proof/dealer.rs @@ -5,17 +5,27 @@ //! [the API for the aggregated multiparty computation protocol](../aggregation/index.html#api-for-the-aggregated-multiparty-computation-protocol). use core::iter; + +extern crate alloc; + +use alloc::vec::Vec; + use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; use merlin::Transcript; -use errors::MPCError; -use generators::{BulletproofGens, PedersenGens}; -use inner_product_proof; -use range_proof::RangeProof; -use transcript::TranscriptProtocol; +use crate::errors::MPCError; +use crate::generators::{BulletproofGens, PedersenGens}; +use crate::inner_product_proof; +use crate::range_proof::RangeProof; +use crate::transcript::TranscriptProtocol; + +use rand_core::{CryptoRng, RngCore}; + +use crate::util; -use util; +#[cfg(feature = "std")] +use rand::thread_rng; use super::messages::*; @@ -218,6 +228,20 @@ impl<'a, 'b> DealerAwaitingProofShares<'a, 'b> { return Err(MPCError::WrongNumProofShares); } + // Validate lengths for each share + let mut bad_shares = Vec::::new(); // no allocations until we append + for (j, share) in proof_shares.iter().enumerate() { + share + .check_size(self.n, &self.bp_gens, j) + .unwrap_or_else(|_| { + bad_shares.push(j); + }); + } + + if bad_shares.len() > 0 { + return Err(MPCError::MalformedProofShares { bad_shares }); + } + let t_x: Scalar = proof_shares.iter().map(|ps| ps.t_x).sum(); let t_x_blinding: Scalar = proof_shares.iter().map(|ps| ps.t_x_blinding).sum(); let e_blinding: Scalar = proof_shares.iter().map(|ps| ps.e_blinding).sum(); @@ -268,6 +292,17 @@ impl<'a, 'b> DealerAwaitingProofShares<'a, 'b> { }) } + /// Assemble the final aggregated [`RangeProof`] from the given + /// `proof_shares`, then validate the proof to ensure that all + /// `ProofShare`s were well-formed. + /// + /// This is a convenience wrapper around receive_shares_with_rng + /// + #[cfg(feature = "std")] + pub fn receive_shares(self, proof_shares: &[ProofShare]) -> Result { + self.receive_shares_with_rng(proof_shares, &mut thread_rng()) + } + /// Assemble the final aggregated [`RangeProof`] from the given /// `proof_shares`, then validate the proof to ensure that all /// `ProofShare`s were well-formed. @@ -281,7 +316,11 @@ impl<'a, 'b> DealerAwaitingProofShares<'a, 'b> { /// performing local aggregation, /// [`receive_trusted_shares`](DealerAwaitingProofShares::receive_trusted_shares) /// saves time by skipping verification of the aggregated proof. - pub fn receive_shares(mut self, proof_shares: &[ProofShare]) -> Result { + pub fn receive_shares_with_rng( + mut self, + proof_shares: &[ProofShare], + rng: &mut T, + ) -> Result { let proof = self.assemble_shares(proof_shares)?; let Vs: Vec<_> = self.bit_commitments.iter().map(|vc| vc.V_j).collect(); @@ -289,7 +328,7 @@ impl<'a, 'b> DealerAwaitingProofShares<'a, 'b> { // See comment in `Dealer::new` for why we use `initial_transcript` let transcript = &mut self.initial_transcript; if proof - .verify_multiple(self.bp_gens, self.pc_gens, transcript, &Vs, self.n) + .verify_multiple_with_rng(self.bp_gens, self.pc_gens, transcript, &Vs, self.n, rng) .is_ok() { Ok(proof) diff --git a/src/range_proof/messages.rs b/src/range_proof/messages.rs index 775ff0e8..8a563fb0 100644 --- a/src/range_proof/messages.rs +++ b/src/range_proof/messages.rs @@ -4,10 +4,14 @@ //! For more explanation of how the `dealer`, `party`, and `messages` modules orchestrate the protocol execution, see //! [the API for the aggregated multiparty computation protocol](../aggregation/index.html#api-for-the-aggregated-multiparty-computation-protocol). +extern crate alloc; + +use alloc::vec::Vec; +use core::iter; use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint}; use curve25519_dalek::scalar::Scalar; -use generators::{BulletproofGens, PedersenGens}; +use crate::generators::{BulletproofGens, PedersenGens}; /// A commitment to the bits of a party's value. #[derive(Serialize, Deserialize, Copy, Clone, Debug)] @@ -49,6 +53,32 @@ pub struct ProofShare { } impl ProofShare { + /// Checks consistency of all sizes in the proof share and returns the size of the l/r vector. + pub(super) fn check_size( + &self, + expected_n: usize, + bp_gens: &BulletproofGens, + j: usize, + ) -> Result<(), ()> { + if self.l_vec.len() != expected_n { + return Err(()); + } + + if self.r_vec.len() != expected_n { + return Err(()); + } + + if expected_n > bp_gens.gens_capacity { + return Err(()); + } + + if j >= bp_gens.party_capacity { + return Err(()); + } + + Ok(()) + } + /// Audit an individual proof share to determine whether it is /// malformed. pub(super) fn audit_share( @@ -61,14 +91,15 @@ impl ProofShare { poly_commitment: &PolyCommitment, poly_challenge: &PolyChallenge, ) -> Result<(), ()> { - use std::iter; - use curve25519_dalek::traits::{IsIdentity, VartimeMultiscalarMul}; - use inner_product_proof::inner_product; - use util; + use crate::inner_product_proof::inner_product; + use crate::util; let n = self.l_vec.len(); + + self.check_size(n, bp_gens, j)?; + let (y, z) = (&bit_challenge.y, &bit_challenge.z); let x = &poly_challenge.x; diff --git a/src/range_proof/mod.rs b/src/range_proof/mod.rs index c680ae78..6eee8d31 100644 --- a/src/range_proof/mod.rs +++ b/src/range_proof/mod.rs @@ -1,21 +1,28 @@ #![allow(non_snake_case)] #![doc(include = "../../docs/range-proof-protocol.md")] -use rand; +extern crate alloc; +#[cfg(feature = "std")] +extern crate rand; -use std::iter; +#[cfg(feature = "std")] +use self::rand::thread_rng; +use alloc::vec::Vec; + +use core::iter; use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint}; use curve25519_dalek::scalar::Scalar; use curve25519_dalek::traits::{IsIdentity, VartimeMultiscalarMul}; use merlin::Transcript; -use errors::ProofError; -use generators::{BulletproofGens, PedersenGens}; -use inner_product_proof::InnerProductProof; -use transcript::TranscriptProtocol; -use util; +use crate::errors::ProofError; +use crate::generators::{BulletproofGens, PedersenGens}; +use crate::inner_product_proof::InnerProductProof; +use crate::transcript::TranscriptProtocol; +use crate::util; +use rand_core::{CryptoRng, RngCore}; use serde::de::Visitor; use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; @@ -125,19 +132,51 @@ impl RangeProof { /// ); /// # } /// ``` - pub fn prove_single( + pub fn prove_single_with_rng( bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, v: u64, v_blinding: &Scalar, n: usize, + rng: &mut T, ) -> Result<(RangeProof, CompressedRistretto), ProofError> { - let (p, Vs) = - RangeProof::prove_multiple(bp_gens, pc_gens, transcript, &[v], &[*v_blinding], n)?; + let (p, Vs) = RangeProof::prove_multiple_with_rng( + bp_gens, + pc_gens, + transcript, + &[v], + &[*v_blinding], + n, + rng, + )?; Ok((p, Vs[0])) } + /// Create a rangeproof for a given pair of value `v` and + /// blinding scalar `v_blinding`. + /// This is a convenience wrapper around [`RangeProof::prove_single_with_rng`], + /// passing in a threadsafe RNG. + #[cfg(feature = "std")] + pub fn prove_single( + bp_gens: &BulletproofGens, + pc_gens: &PedersenGens, + transcript: &mut Transcript, + v: u64, + v_blinding: &Scalar, + n: usize, + ) -> Result<(RangeProof, CompressedRistretto), ProofError> { + RangeProof::prove_single_with_rng( + bp_gens, + pc_gens, + transcript, + v, + v_blinding, + n, + &mut thread_rng(), + ) + } + /// Create a rangeproof for a set of values. /// /// # Example @@ -192,13 +231,14 @@ impl RangeProof { /// ); /// # } /// ``` - pub fn prove_multiple( + pub fn prove_multiple_with_rng( bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, values: &[u64], blindings: &[Scalar], n: usize, + rng: &mut T, ) -> Result<(RangeProof, Vec), ProofError> { use self::dealer::*; use self::party::*; @@ -220,7 +260,7 @@ impl RangeProof { .into_iter() .enumerate() .map(|(j, p)| { - p.assign_position(j) + p.assign_position_with_rng(j, rng) .expect("We already checked the parameters, so this should never happen") }) .unzip(); @@ -231,7 +271,7 @@ impl RangeProof { let (parties, poly_commitments): (Vec<_>, Vec<_>) = parties .into_iter() - .map(|p| p.apply_challenge(&bit_challenge)) + .map(|p| p.apply_challenge_with_rng(&bit_challenge, rng)) .unzip(); let (dealer, poly_challenge) = dealer.receive_poly_commitments(poly_commitments)?; @@ -247,9 +287,49 @@ impl RangeProof { Ok((proof, value_commitments)) } + /// Create a rangeproof for a set of values. + /// This is a convenience wrapper around [`RangeProof::prove_multiple_with_rng`], + /// passing in a threadsafe RNG. + #[cfg(feature = "std")] + pub fn prove_multiple( + bp_gens: &BulletproofGens, + pc_gens: &PedersenGens, + transcript: &mut Transcript, + values: &[u64], + blindings: &[Scalar], + n: usize, + ) -> Result<(RangeProof, Vec), ProofError> { + RangeProof::prove_multiple_with_rng( + bp_gens, + pc_gens, + transcript, + values, + blindings, + n, + &mut thread_rng(), + ) + } + /// Verifies a rangeproof for a given value commitment \\(V\\). /// /// This is a convenience wrapper around `verify_multiple` for the `m=1` case. + pub fn verify_single_with_rng( + &self, + bp_gens: &BulletproofGens, + pc_gens: &PedersenGens, + transcript: &mut Transcript, + V: &CompressedRistretto, + n: usize, + rng: &mut T, + ) -> Result<(), ProofError> { + self.verify_multiple_with_rng(bp_gens, pc_gens, transcript, &[*V], n, rng) + } + + /// Verifies a rangeproof for a given value commitment \\(V\\). + /// + /// This is a convenience wrapper around [`RangeProof::verify_single_with_rng`], + /// passing in a threadsafe RNG. + #[cfg(feature = "std")] pub fn verify_single( &self, bp_gens: &BulletproofGens, @@ -258,17 +338,18 @@ impl RangeProof { V: &CompressedRistretto, n: usize, ) -> Result<(), ProofError> { - self.verify_multiple(bp_gens, pc_gens, transcript, &[*V], n) + self.verify_single_with_rng(bp_gens, pc_gens, transcript, V, n, &mut thread_rng()) } /// Verifies an aggregated rangeproof for the given value commitments. - pub fn verify_multiple( + pub fn verify_multiple_with_rng( &self, bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, value_commitments: &[CompressedRistretto], n: usize, + rng: &mut T, ) -> Result<(), ProofError> { let m = value_commitments.len(); @@ -311,10 +392,8 @@ impl RangeProof { let w = transcript.challenge_scalar(b"w"); - let mut rng = transcript.build_rng().finalize(&mut rand::thread_rng()); - // Challenge value for batching statements to be verified - let c = Scalar::random(&mut rng); + let c = Scalar::random(rng); let (x_sq, x_inv_sq, s) = self.ipp_proof.verification_scalars(n * m, transcript)?; let s_inv = s.iter().rev(); @@ -372,6 +451,28 @@ impl RangeProof { } } + /// Verifies an aggregated rangeproof for the given value commitments. + /// This is a convenience wrapper around [`RangeProof::verify_multiple_with_rng`], + /// passing in a threadsafe RNG. + #[cfg(feature = "std")] + pub fn verify_multiple( + &self, + bp_gens: &BulletproofGens, + pc_gens: &PedersenGens, + transcript: &mut Transcript, + value_commitments: &[CompressedRistretto], + n: usize, + ) -> Result<(), ProofError> { + self.verify_multiple_with_rng( + bp_gens, + pc_gens, + transcript, + value_commitments, + n, + &mut thread_rng(), + ) + } + /// Serializes the proof into a byte array of \\(2 \lg n + 9\\) /// 32-byte elements, where \\(n\\) is the number of secret bits. /// @@ -393,8 +494,7 @@ impl RangeProof { buf.extend_from_slice(self.t_x.as_bytes()); buf.extend_from_slice(self.t_x_blinding.as_bytes()); buf.extend_from_slice(self.e_blinding.as_bytes()); - // XXX this costs an extra alloc - buf.extend_from_slice(self.ipp_proof.to_bytes().as_slice()); + buf.extend(self.ipp_proof.to_bytes_iter()); buf } @@ -409,7 +509,7 @@ impl RangeProof { return Err(ProofError::FormatError); } - use util::read32; + use crate::util::read32; let A = CompressedRistretto(read32(&slice[0 * 32..])); let S = CompressedRistretto(read32(&slice[1 * 32..])); @@ -457,7 +557,7 @@ impl<'de> Deserialize<'de> for RangeProof { impl<'de> Visitor<'de> for RangeProofVisitor { type Value = RangeProof; - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { formatter.write_str("a valid RangeProof") } @@ -465,7 +565,14 @@ impl<'de> Deserialize<'de> for RangeProof { where E: serde::de::Error, { - RangeProof::from_bytes(v).map_err(serde::de::Error::custom) + // Using Error::custom requires T: Display, which our error + // type only implements when it implements std::error::Error. + #[cfg(feature = "std")] + return RangeProof::from_bytes(v).map_err(serde::de::Error::custom); + // In no-std contexts, drop the error message. + #[cfg(not(feature = "std"))] + return RangeProof::from_bytes(v) + .map_err(|_| serde::de::Error::custom("deserialization error")); } } @@ -489,7 +596,7 @@ fn delta(n: usize, m: usize, y: &Scalar, z: &Scalar) -> Scalar { mod tests { use super::*; - use generators::PedersenGens; + use crate::generators::PedersenGens; #[test] fn test_delta() { @@ -528,7 +635,7 @@ mod tests { // data is shared between the prover and the verifier. // Use bincode for serialization - use bincode; + //use bincode; // already present in lib.rs // Both prover and verifier have access to the generators and the proof let max_bitsize = 64; @@ -538,7 +645,7 @@ mod tests { // Prover's scope let (proof_bytes, value_commitments) = { - use rand::Rng; + use self::rand::Rng; let mut rng = rand::thread_rng(); // 0. Create witness data @@ -621,7 +728,7 @@ mod tests { use self::dealer::*; use self::party::*; - use errors::MPCError; + use crate::errors::MPCError; // Simulate four parties, two of which will be dishonest and use a 64-bit value. let m = 4; @@ -630,7 +737,7 @@ mod tests { let pc_gens = PedersenGens::default(); let bp_gens = BulletproofGens::new(n, m); - use rand::Rng; + use self::rand::Rng; let mut rng = rand::thread_rng(); let mut transcript = Transcript::new(b"AggregatedRangeProofTest"); @@ -694,7 +801,7 @@ mod tests { fn detect_dishonest_dealer_during_aggregation() { use self::dealer::*; use self::party::*; - use errors::MPCError; + use crate::errors::MPCError; // Simulate one party let m = 1; @@ -703,7 +810,7 @@ mod tests { let pc_gens = PedersenGens::default(); let bp_gens = BulletproofGens::new(n, m); - use rand::Rng; + use self::rand::Rng; let mut rng = rand::thread_rng(); let mut transcript = Transcript::new(b"AggregatedRangeProofTest"); diff --git a/src/range_proof/party.rs b/src/range_proof/party.rs index 017ff17e..ebb232cc 100644 --- a/src/range_proof/party.rs +++ b/src/range_proof/party.rs @@ -10,16 +10,22 @@ //! modules orchestrate the protocol execution, see the documentation //! in the [`aggregation`](::range_proof_mpc) module. +extern crate alloc; + +use alloc::vec::Vec; +use clear_on_drop::clear::Clear; +use core::iter; use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint}; use curve25519_dalek::scalar::Scalar; use curve25519_dalek::traits::MultiscalarMul; +use rand_core::{CryptoRng, RngCore}; -use clear_on_drop::clear::Clear; -use errors::MPCError; -use generators::{BulletproofGens, PedersenGens}; -use rand; -use std::iter; -use util; +use crate::errors::MPCError; +use crate::generators::{BulletproofGens, PedersenGens}; +use crate::util; + +#[cfg(feature = "std")] +use rand::thread_rng; use super::messages::*; @@ -68,20 +74,28 @@ pub struct PartyAwaitingPosition<'a> { impl<'a> PartyAwaitingPosition<'a> { /// Assigns a position in the aggregated proof to this party, /// allowing the party to commit to the bits of their value. + #[cfg(feature = "std")] pub fn assign_position( self, j: usize, ) -> Result<(PartyAwaitingBitChallenge<'a>, BitCommitment), MPCError> { - // XXX use transcript RNG - let mut rng = rand::thread_rng(); + self.assign_position_with_rng(j, &mut thread_rng()) + } + /// Assigns a position in the aggregated proof to this party, + /// allowing the party to commit to the bits of their value. + pub fn assign_position_with_rng( + self, + j: usize, + rng: &mut T, + ) -> Result<(PartyAwaitingBitChallenge<'a>, BitCommitment), MPCError> { if self.bp_gens.party_capacity <= j { return Err(MPCError::InvalidGeneratorsLength); } let bp_share = self.bp_gens.share(j); - let a_blinding = Scalar::random(&mut rng); + let a_blinding = Scalar::random(rng); // Compute A = + + a_blinding * B_blinding let mut A = self.pc_gens.B_blinding * a_blinding; @@ -97,9 +111,9 @@ impl<'a> PartyAwaitingPosition<'a> { i += 1; } - let s_blinding = Scalar::random(&mut rng); - let s_L: Vec = (0..self.n).map(|_| Scalar::random(&mut rng)).collect(); - let s_R: Vec = (0..self.n).map(|_| Scalar::random(&mut rng)).collect(); + let s_blinding = Scalar::random(rng); + let s_L: Vec = (0..self.n).map(|_| Scalar::random(rng)).collect(); + let s_R: Vec = (0..self.n).map(|_| Scalar::random(rng)).collect(); // Compute S = + + s_blinding * B_blinding let S = RistrettoPoint::multiscalar_mul( @@ -155,12 +169,21 @@ pub struct PartyAwaitingBitChallenge<'a> { impl<'a> PartyAwaitingBitChallenge<'a> { /// Receive a [`BitChallenge`] from the dealer and use it to /// compute commitments to the party's polynomial coefficients. + #[cfg(feature = "std")] pub fn apply_challenge( self, vc: &BitChallenge, ) -> (PartyAwaitingPolyChallenge, PolyCommitment) { - let mut rng = rand::thread_rng(); + self.apply_challenge_with_rng(vc, &mut thread_rng()) + } + /// Receive a [`BitChallenge`] from the dealer and use it to + /// compute commitments to the party's polynomial coefficients. + pub fn apply_challenge_with_rng( + self, + vc: &BitChallenge, + rng: &mut T, + ) -> (PartyAwaitingPolyChallenge, PolyCommitment) { let n = self.n; let offset_y = util::scalar_exp_vartime(&vc.y, (self.j * n) as u64); let offset_z = util::scalar_exp_vartime(&vc.z, self.j as u64); @@ -169,7 +192,7 @@ impl<'a> PartyAwaitingBitChallenge<'a> { let mut l_poly = util::VecPoly1::zero(n); let mut r_poly = util::VecPoly1::zero(n); - let zz = vc.z * vc.z; + let offset_zz = vc.z * vc.z * offset_z; let mut exp_y = offset_y; // start at y^j let mut exp_2 = Scalar::one(); // start at 2^0 = 1 for i in 0..n { @@ -178,7 +201,7 @@ impl<'a> PartyAwaitingBitChallenge<'a> { l_poly.0[i] = a_L_i - vc.z; l_poly.1[i] = self.s_L[i]; - r_poly.0[i] = exp_y * (a_R_i + vc.z) + zz * offset_z * exp_2; + r_poly.0[i] = exp_y * (a_R_i + vc.z) + offset_zz * exp_2; r_poly.1[i] = exp_y * self.s_R[i]; exp_y *= vc.y; // y^i -> y^(i+1) @@ -188,8 +211,8 @@ impl<'a> PartyAwaitingBitChallenge<'a> { let t_poly = l_poly.inner_product(&r_poly); // Generate x by committing to T_1, T_2 (line 49-54) - let t_1_blinding = Scalar::random(&mut rng); - let t_2_blinding = Scalar::random(&mut rng); + let t_1_blinding = Scalar::random(rng); + let t_2_blinding = Scalar::random(rng); let T_1 = self.pc_gens.commit(t_poly.1, t_1_blinding); let T_2 = self.pc_gens.commit(t_poly.2, t_2_blinding); @@ -202,8 +225,7 @@ impl<'a> PartyAwaitingBitChallenge<'a> { v_blinding: self.v_blinding, a_blinding: self.a_blinding, s_blinding: self.s_blinding, - z: vc.z, - offset_z, + offset_zz, l_poly, r_poly, t_poly, @@ -240,8 +262,7 @@ impl<'a> Drop for PartyAwaitingBitChallenge<'a> { /// A party which has committed to their polynomial coefficents /// and is waiting for the polynomial challenge from the dealer. pub struct PartyAwaitingPolyChallenge { - z: Scalar, - offset_z: Scalar, + offset_zz: Scalar, l_poly: util::VecPoly1, r_poly: util::VecPoly1, t_poly: util::Poly2, @@ -263,7 +284,7 @@ impl PartyAwaitingPolyChallenge { } let t_blinding_poly = util::Poly2( - self.z * self.z * self.offset_z * self.v_blinding, + self.offset_zz * self.v_blinding, self.t_1_blinding, self.t_2_blinding, ); diff --git a/src/transcript.rs b/src/transcript.rs index 7b3d5447..639c7cf1 100644 --- a/src/transcript.rs +++ b/src/transcript.rs @@ -4,7 +4,7 @@ use curve25519_dalek::ristretto::CompressedRistretto; use curve25519_dalek::scalar::Scalar; use merlin::Transcript; -use errors::ProofError; +use crate::errors::ProofError; pub trait TranscriptProtocol { /// Append a domain separator for an `n`-bit, `m`-party range proof. diff --git a/src/util.rs b/src/util.rs index 7c65735b..dd7ce2fe 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,9 +1,14 @@ #![deny(missing_docs)] #![allow(non_snake_case)] +extern crate alloc; + +use alloc::vec; +use alloc::vec::Vec; use clear_on_drop::clear::Clear; use curve25519_dalek::scalar::Scalar; -use inner_product_proof::inner_product; + +use crate::inner_product_proof::inner_product; /// Represents a degree-1 vector polynomial \\(\mathbf{a} + \mathbf{b} \cdot x\\). pub struct VecPoly1(pub Vec, pub Vec); @@ -64,7 +69,7 @@ pub fn exp_iter(x: Scalar) -> ScalarExp { pub fn add_vec(a: &[Scalar], b: &[Scalar]) -> Vec { if a.len() != b.len() { // throw some error - println!("lengths of vectors don't match for vector addition"); + //println!("lengths of vectors don't match for vector addition"); } let mut out = vec![Scalar::zero(); b.len()]; for i in 0..a.len() { diff --git a/tests/r1cs.rs b/tests/r1cs.rs index 0e3680cb..93daefbe 100644 --- a/tests/r1cs.rs +++ b/tests/r1cs.rs @@ -10,6 +10,7 @@ use bulletproofs::{BulletproofGens, PedersenGens}; use curve25519_dalek::ristretto::CompressedRistretto; use curve25519_dalek::scalar::Scalar; use merlin::Transcript; +use rand::seq::SliceRandom; use rand::thread_rng; // Shuffle gadget (documented in markdown file) @@ -157,7 +158,7 @@ fn kshuffle_helper(k: usize) { .map(|_| Scalar::from(rng.gen_range(min, max))) .collect(); let mut output = input.clone(); - rand::thread_rng().shuffle(&mut output); + output.shuffle(&mut rand::thread_rng()); let mut prover_transcript = Transcript::new(b"ShuffleProofTest"); ShuffleProof::prove(&pc_gens, &bp_gens, &mut prover_transcript, &input, &output).unwrap() @@ -401,10 +402,10 @@ pub fn range_proof( #[test] fn range_proof_gadget() { - use rand::rngs::OsRng; + use rand::thread_rng; use rand::Rng; - let mut rng = OsRng::new().unwrap(); + let mut rng = thread_rng(); let m = 3; // number of values to test per `n` for n in [2, 10, 32, 63].iter() { diff --git a/tests/range_proof.rs b/tests/range_proof.rs index 339440f3..57b0f653 100644 --- a/tests/range_proof.rs +++ b/tests/range_proof.rs @@ -1,20 +1,15 @@ -extern crate rand; -use rand::SeedableRng; +use rand_core::SeedableRng; -extern crate rand_chacha; use rand_chacha::ChaChaRng; -extern crate curve25519_dalek; use curve25519_dalek::ristretto::CompressedRistretto; use curve25519_dalek::scalar::Scalar; -extern crate merlin; use merlin::Transcript; -extern crate bulletproofs; use bulletproofs::{BulletproofGens, PedersenGens, RangeProof}; -extern crate hex; +use hex; // Tests that proofs generated with v1.0.0 continue to verify in later versions. #[test]