From 9a00ce71285e2e45d6450819e7b61ec0089e2f15 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Wed, 22 Jun 2022 18:57:07 -0400 Subject: [PATCH 01/17] feat: setup trusted-setup crate --- Cargo.toml | 1 + manta-trusted-setup/Cargo.toml | 31 +++++++++++++++++++++++++++++++ manta-trusted-setup/LICENSE | 1 + manta-trusted-setup/README.md | 1 + manta-trusted-setup/src/lib.rs | 22 ++++++++++++++++++++++ 5 files changed, 56 insertions(+) create mode 100644 manta-trusted-setup/Cargo.toml create mode 120000 manta-trusted-setup/LICENSE create mode 100644 manta-trusted-setup/README.md create mode 100644 manta-trusted-setup/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 218983c2c..e3641ef6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,5 +6,6 @@ members = [ "manta-crypto", "manta-parameters", "manta-pay", + "manta-trusted-setup", "manta-util", ] diff --git a/manta-trusted-setup/Cargo.toml b/manta-trusted-setup/Cargo.toml new file mode 100644 index 000000000..fcc12c29e --- /dev/null +++ b/manta-trusted-setup/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "manta-trusted-setup" +version = "0.5.1" +edition = "2021" +authors = ["Manta Network "] +readme = "README.md" +license-file = "LICENSE" +repository = "https://github.com/Manta-Network/manta-rs" +homepage = "https://github.com/Manta-Network" +documentation = "https://github.com/Manta-Network/manta-rs" +categories = [""] +keywords = [""] +description = "MPC Ceremonies for Trusted Setup SRS Generation" +publish = false + +[package.metadata.docs.rs] +# To build locally: +# RUSTDOCFLAGS="--cfg doc_cfg" cargo +nightly doc --all-features --open +all-features = true +rustdoc-args = ["--cfg", "doc_cfg"] + +[badges] +is-it-maintained-issue-resolution = { repository = "Manta-Network/manta-rs" } +is-it-maintained-open-issues = { repository = "Manta-Network/manta-rs" } +maintenance = { status = "actively-developed" } + +[features] +# Standard Library +std = [] + +[dependencies] diff --git a/manta-trusted-setup/LICENSE b/manta-trusted-setup/LICENSE new file mode 120000 index 000000000..ea5b60640 --- /dev/null +++ b/manta-trusted-setup/LICENSE @@ -0,0 +1 @@ +../LICENSE \ No newline at end of file diff --git a/manta-trusted-setup/README.md b/manta-trusted-setup/README.md new file mode 100644 index 000000000..71d974f16 --- /dev/null +++ b/manta-trusted-setup/README.md @@ -0,0 +1 @@ +# manta-trusted-setup diff --git a/manta-trusted-setup/src/lib.rs b/manta-trusted-setup/src/lib.rs new file mode 100644 index 000000000..c3369c650 --- /dev/null +++ b/manta-trusted-setup/src/lib.rs @@ -0,0 +1,22 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! Trusted Setup + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![forbid(rustdoc::broken_intra_doc_links)] +#![forbid(missing_docs)] From 8a30ca394003923880463ceae84e8bd9b7df0533 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Wed, 22 Jun 2022 21:12:08 -0400 Subject: [PATCH 02/17] wip: start adding KZG structures --- manta-trusted-setup/Cargo.toml | 11 + manta-trusted-setup/src/groth16.rs | 17 ++ manta-trusted-setup/src/kzg.rs | 456 +++++++++++++++++++++++++++++ manta-trusted-setup/src/lib.rs | 5 + manta-trusted-setup/src/mpc.rs | 110 +++++++ manta-trusted-setup/src/util.rs | 213 ++++++++++++++ 6 files changed, 812 insertions(+) create mode 100644 manta-trusted-setup/src/groth16.rs create mode 100644 manta-trusted-setup/src/kzg.rs create mode 100644 manta-trusted-setup/src/mpc.rs create mode 100644 manta-trusted-setup/src/util.rs diff --git a/manta-trusted-setup/Cargo.toml b/manta-trusted-setup/Cargo.toml index fcc12c29e..dc20077f7 100644 --- a/manta-trusted-setup/Cargo.toml +++ b/manta-trusted-setup/Cargo.toml @@ -29,3 +29,14 @@ maintenance = { status = "actively-developed" } std = [] [dependencies] +ark-ec = { version = "0.3.0", default-features = false } +ark-ff = { version = "0.3.0", default-features = false } +ark-groth16 = { version = "0.3.0", default-features = false } +ark-r1cs-std = { version = "0.3.1", default-features = false } +ark-relations = { version = "0.3.0", default-features = false } +ark-serialize = { version = "0.3.0", default-features = false, features = ["derive"] } +ark-snark = { version = "0.3.0", default-features = false } +ark-std = { version = "0.3.0", default-features = false } +derivative = { version = "2.2.0", default-features = false, features = ["use_core"] } +manta-crypto = { path = "../manta-crypto", default-features = false } +manta-util = { path = "../manta-util", default-features = false, features = ["alloc"] } diff --git a/manta-trusted-setup/src/groth16.rs b/manta-trusted-setup/src/groth16.rs new file mode 100644 index 000000000..23a926e1f --- /dev/null +++ b/manta-trusted-setup/src/groth16.rs @@ -0,0 +1,17 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! Groth16 Trusted Setup diff --git a/manta-trusted-setup/src/kzg.rs b/manta-trusted-setup/src/kzg.rs new file mode 100644 index 000000000..af0efde47 --- /dev/null +++ b/manta-trusted-setup/src/kzg.rs @@ -0,0 +1,456 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! KZG Trusted Setup + +use crate::util::{ + CanonicalDeserialize, CanonicalSerialize, Deserializer, HasDistribution, NonZero, Read, Sample, + SerializationError, Serializer, Write, Zero, +}; +use ark_ec::{AffineCurve, PairingEngine}; + +/// KZG Trusted Setup Size +pub trait Size { + /// Number of G1 Powers to Produce + const G1_POWERS: usize; + + /// Number of G2 Powers to Produce + const G2_POWERS: usize; +} + +/// +pub trait Pairing: HasDistribution { + /// + type Scalar; + + /// First Group of the Pairing + type G1: AffineCurve + Sample + Zero; + + /// Second Group of the Pairing + type G2: AffineCurve + Sample + Zero; + + /// Pairing Engine Type + type Engine: PairingEngine; + + /// + fn g1_prime_subgroup_generator() -> Self::G1; + + /// + fn g2_prime_subgroup_generator() -> Self::G2; +} + +/// Verification Error +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub enum VerificationError { + /// Invalid Proof of Knowledge for τ + TauKnowledgeProof, + + /// Invalid Proof of Knowledge for α + AlphaKnowledgeProof, + + /// Invalid Proof of Knowledge for β + BetaKnowledgeProof, + + /// Element Differs from Prime Subgroup Generator in G1 + PrimeSubgroupGeneratorG1, + + /// Element Differs from Prime Subgroup Generator in G2 + PrimeSubgroupGeneratorG2, + + /// Invalid Multiplication of τ + TauMultiplication, + + /// Invalid Multiplication of α + AlphaMultiplication, + + /// Invalid Multiplication of β + BetaMultiplication, + + /// Invalid Computation of Powers of τ + PowersOfTau, +} + +/// Contribution Public Key +#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)] +pub struct PublicKey +where + C: Pairing, +{ + /// + pub tau_g1_ratio: (C::G1, C::G1), + + /// + pub alpha_g1_ratio: (C::G1, C::G1), + + /// + pub beta_g1_ratio: (C::G1, C::G1), + + /// + pub tau_g2: C::G2, + + /// + pub alpha_g2: C::G2, + + /// + pub beta_g2: C::G2, +} + +impl CanonicalSerialize for PublicKey +where + C: Pairing + Serializer + Serializer, +{ + #[inline] + fn serialize(&self, mut writer: W) -> Result<(), SerializationError> + where + W: Write, + { + C::serialize_compressed(&self.tau_g1_ratio.0, &mut writer)?; + C::serialize_compressed(&self.tau_g1_ratio.1, &mut writer)?; + C::serialize_compressed(&self.alpha_g1_ratio.0, &mut writer)?; + C::serialize_compressed(&self.alpha_g1_ratio.1, &mut writer)?; + C::serialize_compressed(&self.beta_g1_ratio.0, &mut writer)?; + C::serialize_compressed(&self.beta_g1_ratio.1, &mut writer)?; + C::serialize_compressed(&self.tau_g2, &mut writer)?; + C::serialize_compressed(&self.alpha_g2, &mut writer)?; + C::serialize_compressed(&self.beta_g2, &mut writer)?; + Ok(()) + } + + #[inline] + fn serialized_size(&self) -> usize { + /* TODO: + // Compressed G1 is 48 bytes + // Compressed G2 is 96 bytes + 48 * 2 * 3 + 96 * 3 + */ + todo!() + } + + #[inline] + fn serialize_uncompressed(&self, mut writer: W) -> Result<(), SerializationError> + where + W: Write, + { + C::serialize_uncompressed(&self.tau_g1_ratio.0, &mut writer)?; + C::serialize_uncompressed(&self.tau_g1_ratio.1, &mut writer)?; + C::serialize_uncompressed(&self.alpha_g1_ratio.0, &mut writer)?; + C::serialize_uncompressed(&self.alpha_g1_ratio.1, &mut writer)?; + C::serialize_uncompressed(&self.beta_g1_ratio.0, &mut writer)?; + C::serialize_uncompressed(&self.beta_g1_ratio.1, &mut writer)?; + C::serialize_uncompressed(&self.tau_g2, &mut writer)?; + C::serialize_uncompressed(&self.alpha_g2, &mut writer)?; + C::serialize_uncompressed(&self.beta_g2, &mut writer)?; + Ok(()) + } + + #[inline] + fn uncompressed_size(&self) -> usize { + /* TODO: + // Compressed G1 is 96 bytes + // Compressed G2 is 192 bytes + 96 * 2 * 3 + 192 * 3 + */ + todo!() + } +} + +impl CanonicalDeserialize for PublicKey +where + C: Deserializer + Deserializer + Pairing, +{ + #[inline] + fn deserialize(mut reader: R) -> Result + where + R: Read, + { + Ok(Self { + tau_g1_ratio: ( + NonZero::::deserialize_compressed(&mut reader)?, + NonZero::::deserialize_compressed(&mut reader)?, + ), + alpha_g1_ratio: ( + NonZero::::deserialize_compressed(&mut reader)?, + NonZero::::deserialize_compressed(&mut reader)?, + ), + beta_g1_ratio: ( + NonZero::::deserialize_compressed(&mut reader)?, + NonZero::::deserialize_compressed(&mut reader)?, + ), + tau_g2: NonZero::::deserialize_compressed(&mut reader)?, + alpha_g2: NonZero::::deserialize_compressed(&mut reader)?, + beta_g2: NonZero::::deserialize_compressed(&mut reader)?, + }) + } + + #[inline] + fn deserialize_uncompressed(mut reader: R) -> Result + where + R: Read, + { + Ok(Self { + tau_g1_ratio: ( + NonZero::::deserialize_uncompressed(&mut reader)?, + NonZero::::deserialize_uncompressed(&mut reader)?, + ), + alpha_g1_ratio: ( + NonZero::::deserialize_uncompressed(&mut reader)?, + NonZero::::deserialize_uncompressed(&mut reader)?, + ), + beta_g1_ratio: ( + NonZero::::deserialize_uncompressed(&mut reader)?, + NonZero::::deserialize_uncompressed(&mut reader)?, + ), + tau_g2: NonZero::::deserialize_uncompressed(&mut reader)?, + alpha_g2: NonZero::::deserialize_uncompressed(&mut reader)?, + beta_g2: NonZero::::deserialize_uncompressed(&mut reader)?, + }) + } +} + +/// Contribution Accumulator +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct Accumulator +where + C: Pairing + Size, +{ + /// + tau_powers_g1: Vec, + + /// + tau_powers_g2: Vec, + + /// + alpha_tau_powers_g1: Vec, + + /// + beta_tau_powers_g1: Vec, + + /// + beta_g2: C::G2, +} + +impl CanonicalSerialize for Accumulator +where + C: Pairing + Size + Serializer + Serializer, +{ + #[inline] + fn serialize(&self, mut writer: W) -> Result<(), SerializationError> + where + W: Write, + { + for elem in &self.tau_powers_g1 { + C::serialize_compressed(elem, &mut writer)?; + } + for elem in &self.tau_powers_g2 { + C::serialize_compressed(elem, &mut writer)?; + } + for elem in &self.alpha_tau_powers_g1 { + C::serialize_compressed(elem, &mut writer)?; + } + for elem in &self.beta_tau_powers_g1 { + C::serialize_compressed(elem, &mut writer)?; + } + C::serialize_compressed(&self.beta_g2, &mut writer)?; + Ok(()) + } + + #[inline] + fn serialized_size(&self) -> usize { + /* TODO: + // A compressed G1 element is 48 bytes + // A compressed G2 element is 96 bytes + C::G1_POWERS * 48 + C::G2_POWERS * 96 + C::G1_POWERS * 48 * 2 + 96 + */ + todo!() + } + + #[inline] + fn serialize_uncompressed(&self, mut writer: W) -> Result<(), SerializationError> + where + W: Write, + { + for elem in &self.tau_powers_g1 { + C::serialize_uncompressed(elem, &mut writer)?; + } + for elem in &self.tau_powers_g2 { + C::serialize_uncompressed(elem, &mut writer)?; + } + for elem in &self.alpha_tau_powers_g1 { + C::serialize_uncompressed(elem, &mut writer)?; + } + for elem in &self.beta_tau_powers_g1 { + C::serialize_uncompressed(elem, &mut writer)?; + } + C::serialize_uncompressed(&self.beta_g2, &mut writer)?; + Ok(()) + } + + #[inline] + fn uncompressed_size(&self) -> usize { + /* TODO: + // An uncompressed G1 element is 96 bytes + // An uncompressed G2 element is 192 bytes + C::G1_POWERS * 96 + C::G2_POWERS * 192 + C::G1_POWERS * 96 * 2 + 192 + */ + todo!() + } +} + +impl CanonicalDeserialize for Accumulator +where + C: Deserializer + Deserializer + Pairing + Size, +{ + #[inline] + fn deserialize(mut reader: R) -> Result + where + R: Read, + { + /* + let mut tau_powers_g1 = Vec::with_capacity(C::G1_POWERS); + for _ in 0..C::G1_POWERS { + tau_powers_g1.push( + C::deserialize_g1_compressed(&mut reader) + .map_err(C::convert_serialization_error)?, + ); + } + let mut tau_powers_g2 = Vec::with_capacity(C::G2_POWERS); + for _ in 0..C::G2_POWERS { + tau_powers_g2.push( + C::deserialize_g2_compressed(&mut reader) + .map_err(C::convert_serialization_error)?, + ); + } + let mut alpha_tau_powers_g1 = Vec::with_capacity(C::G2_POWERS); + for _ in 0..C::G2_POWERS { + alpha_tau_powers_g1.push( + C::deserialize_g1_compressed(&mut reader) + .map_err(C::convert_serialization_error)?, + ); + } + let mut beta_tau_powers_g1 = Vec::with_capacity(C::G2_POWERS); + for _ in 0..C::G2_POWERS { + beta_tau_powers_g1.push( + C::deserialize_g1_compressed(&mut reader) + .map_err(C::convert_serialization_error)?, + ); + } + Ok(Self { + tau_powers_g1, + tau_powers_g2, + alpha_tau_powers_g1, + beta_tau_powers_g1, + beta_g2: C::deserialize_g2_compressed(&mut reader) + .map_err(C::convert_serialization_error)?, + }) + */ + todo!() + } + + #[inline] + fn deserialize_uncompressed(reader: R) -> Result + where + R: Read, + { + /* TODO: + let unchecked = Self::deserialize_unchecked(reader)?; + let counter = std::sync::atomic::AtomicU64::new(0); + cfg_try_for_each!(cfg_iter!(&unchecked.tau_powers_g1), |point| { + counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst); + if counter.load(std::sync::atomic::Ordering::SeqCst) % 1000000 == 0 { + println!("Checked this many elements: {:?}", counter); + } + C::curve_point_checks_g1(point) + }) + .map_err(C::convert_serialization_error)?; + cfg_try_for_each!( + cfg_iter!(&unchecked.tau_powers_g2), + C::curve_point_checks_g2 + ) + .map_err(C::convert_serialization_error)?; + cfg_try_for_each!( + cfg_iter!(&unchecked.alpha_tau_powers_g1), + C::curve_point_checks_g1 + ) + .map_err(C::convert_serialization_error)?; + cfg_try_for_each!( + cfg_iter!(&unchecked.beta_tau_powers_g1), + C::curve_point_checks_g1 + ) + .map_err(C::convert_serialization_error)?; + C::curve_point_checks_g2(&unchecked.beta_g2).map_err(C::convert_serialization_error)?; + Ok(unchecked) + */ + todo!() + } + + #[inline] + fn deserialize_unchecked(mut reader: R) -> Result + where + R: Read, + { + /* TODO: + let mut tau_powers_g1 = Vec::with_capacity(C::G1_POWERS); + for i in 0..C::G1_POWERS { + tau_powers_g1.push( + C::deserialize_g1_unchecked(&mut reader).map_err(C::convert_serialization_error)?, + ); + } + let mut tau_powers_g2 = Vec::with_capacity(C::G2_POWERS); + for i in 0..C::G2_POWERS { + tau_powers_g2.push( + C::deserialize_g2_unchecked(&mut reader).map_err(C::convert_serialization_error)?, + ); + } + let mut alpha_tau_powers_g1 = Vec::with_capacity(C::G2_POWERS); + for i in 0..C::G2_POWERS { + alpha_tau_powers_g1.push( + C::deserialize_g1_unchecked(&mut reader).map_err(C::convert_serialization_error)?, + ); + } + let mut beta_tau_powers_g1 = Vec::with_capacity(C::G2_POWERS); + for i in 0..C::G2_POWERS { + beta_tau_powers_g1.push( + C::deserialize_g1_unchecked(&mut reader).map_err(C::convert_serialization_error)?, + ); + } + Ok(Self { + tau_powers_g1, + tau_powers_g2, + alpha_tau_powers_g1, + beta_tau_powers_g1, + beta_g2: C::deserialize_g2_unchecked(&mut reader) + .map_err(C::convert_serialization_error)?, + }) + */ + todo!() + } +} + +impl Default for Accumulator +where + C: Pairing + Size, +{ + #[inline] + fn default() -> Self { + Self { + tau_powers_g1: vec![C::g1_prime_subgroup_generator(); C::G1_POWERS], + tau_powers_g2: vec![C::g2_prime_subgroup_generator(); C::G2_POWERS], + alpha_tau_powers_g1: vec![C::g1_prime_subgroup_generator(); C::G2_POWERS], + beta_tau_powers_g1: vec![C::g1_prime_subgroup_generator(); C::G2_POWERS], + beta_g2: C::g2_prime_subgroup_generator(), + } + } +} diff --git a/manta-trusted-setup/src/lib.rs b/manta-trusted-setup/src/lib.rs index c3369c650..02fb3478b 100644 --- a/manta-trusted-setup/src/lib.rs +++ b/manta-trusted-setup/src/lib.rs @@ -20,3 +20,8 @@ #![cfg_attr(doc_cfg, feature(doc_cfg))] #![forbid(rustdoc::broken_intra_doc_links)] #![forbid(missing_docs)] + +pub mod groth16; +pub mod kzg; +pub mod mpc; +pub mod util; diff --git a/manta-trusted-setup/src/mpc.rs b/manta-trusted-setup/src/mpc.rs new file mode 100644 index 000000000..ddd5bbc02 --- /dev/null +++ b/manta-trusted-setup/src/mpc.rs @@ -0,0 +1,110 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! MPC Primitives + +/// +pub trait Contribute { + /// + type Accumulator; + + /// + type Contribution; + + /// + type PublicKey; + + /// + type Challenge; + + /// + type Response; + + /// + fn contribute( + &self, + accumulator: &Self::Accumulator, + challenge: &Self::Challenge, + contribution: &Self::Contribution, + ) -> (Self::Response, Self::PublicKey, Self::Accumulator); +} + +/// +pub trait Verify { + /// Accumulator + type Accumulator; + + /// Contribution Public Key + type PublicKey; + + /// Challenge + type Challenge; + + /// Response + type Response; + + /// Error + type Error; + + /// Computes the challenge associated to `last` and `last_response` for the next player. + fn challenge( + &self, + last: &Self::Accumulator, + last_response: &Self::Response, + ) -> Self::Challenge; + + /// Computes the response from `next` and `next_key` to the `challenge` presented by the + /// previous state. + fn response( + &self, + next: &Self::Accumulator, + next_key: &Self::PublicKey, + challenge: Self::Challenge, + ) -> Self::Response; + + /// Verifies the transformation from `last` to `next` using the `next_key` and `next_response` + /// as evidence for the correct update of the state. This method returns the `next` accumulator + /// and `next_response`. + fn verify( + &self, + last: Self::Accumulator, + next: Self::Accumulator, + next_key: Self::PublicKey, + next_response: Self::Challenge, + ) -> Result<(Self::Accumulator, Self::Response), Self::Error>; + + /// Verifies all accumulator contributions in `iter` chaining from `last` and `last_response` + /// returning the newest [`Accumulator`](Self::Accumulator) and [`Response`](Self::Response) if + /// all the contributions in the chain had valid transitions. + #[inline] + fn verify_all( + &self, + mut last: Self::Accumulator, + mut last_response: Self::Response, + iter: I, + ) -> Result<(Self::Accumulator, Self::Response), Self::Error> + where + E: Into, + I: IntoIterator>, + { + for item in iter { + let (next, next_key) = item.map_err(Into::into)?; + let next_challenge = self.challenge(&next, &last_response); + (last, last_response) = self.verify(last, next, next_key, next_challenge)?; + } + Ok((last, last_response)) + } +} diff --git a/manta-trusted-setup/src/util.rs b/manta-trusted-setup/src/util.rs new file mode 100644 index 000000000..9d0225076 --- /dev/null +++ b/manta-trusted-setup/src/util.rs @@ -0,0 +1,213 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! Utilities + +use ark_std::io; +use core::marker::PhantomData; + +pub use ark_ff::{One, Zero}; +pub use ark_serialize::{ + CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write, +}; +pub use manta_crypto::rand::Sample; + +/// Distribution Type Extension +pub trait HasDistribution { + /// Distribution Type + type Distribution; +} + +/// Custom Serialization Adapter +/// +/// In the majority of cases we can just use [`CanonicalSerialize`] and [`CanonicalDeserialize`] to +/// make data types compatible with the `arkworks` serialization system. However, in some cases we +/// need to provide a "non-canonical" serialization for an existing type. This `trait` provides an +/// interface for building a serialization over the type `T`. For deserialization see the +/// [`Deserializer`] `trait`. +/// +/// [`CanonicalSerialize`]: ark_serialize::CanonicalSerialize +/// [`CanonicalDeserialize`]: ark_serialize::CanonicalDeserialize +pub trait Serializer { + /// Serializes `item` in uncompressed form to the `writer` without performing any + /// well-formedness checks. + fn serialize_unchecked(item: &T, writer: &mut W) -> Result<(), io::Error> + where + W: Write; + + /// Serializes `item` in uncompressed form to the `writer`, performing all well-formedness + /// checks. + fn serialize_uncompressed(item: &T, writer: &mut W) -> Result<(), io::Error> + where + W: Write; + + /// Serializes `item` in compressed form to the `writer`, performing all well-formedness checks. + fn serialize_compressed(item: &T, writer: &mut W) -> Result<(), io::Error> + where + W: Write; +} + +/// Custom Deserialization Adapter +/// +/// In the majority of cases we can just use [`CanonicalSerialize`] and [`CanonicalDeserialize`] to +/// make data types compatible with the `arkworks` serialization system. However, in some cases we +/// need to provide a "non-canonical" deserialization for an existing type. This `trait` provides an +/// interface for building a deserialization over the type `T`. For serialization see the +/// [`Serializer`] `trait`. +/// +/// [`CanonicalSerialize`]: ark_serialize::CanonicalSerialize +/// [`CanonicalDeserialize`]: ark_serialize::CanonicalDeserialize +pub trait Deserializer { + /// Deserialization Error Type + type Error: Into; + + /// Checks that `item` is a valid element of type `T`. + /// + /// # Implementation Note + /// + /// Implementing this method is optional and by default it does nothing since callers should + /// always rely on the `deserialize_*` methods directly. However, the + /// [`deserialize_uncompressed`] method calls this method, so if the difference between + /// [`deserialize_unchecked`] and [`deserialize_uncompressed`] is just a simple check on the + /// type `T`, then this function should be implemented. Otherwise, [`deserialize_uncompressed`] + /// should be implemented manually. + /// + /// [`deserialize_uncompressed`]: Self::deserialize_uncompressed + /// [`deserialize_unchecked`]: Self::deserialize_unchecked + #[inline] + fn check(item: &T) -> Result<(), Self::Error> { + let _ = item; + Ok(()) + } + + /// Deserializes a single uncompressed item of type `T` from the `reader` with the minimal + /// amount of checks required to form the type. + fn deserialize_unchecked(reader: &mut R) -> Result + where + R: Read; + + /// Deserializes a single uncompressed item of type `T` from the `reader` with all validity + /// checks enabled. + /// + /// # Implementation Note + /// + /// Implementing this method is optional whenever there exists a non-default implementation of + /// [`check`](Self::check). See its documentation for more. + #[inline] + fn deserialize_uncompressed(reader: &mut R) -> Result + where + R: Read, + { + let item = Self::deserialize_unchecked(reader)?; + Self::check(&item)?; + Ok(item) + } + + /// Deserializes a single compressed item of type `T` from the `reader` with all validity checks + /// enabled. + fn deserialize_compressed(reader: &mut R) -> Result + where + R: Read; +} + +/// Deserialization Error for [`NonZero`] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub enum NonZeroError { + /// Element was Zero when Deserialized + IsZero, + + /// Other Deserialization Error + Error(E), +} + +impl From> for SerializationError +where + E: Into, +{ + #[inline] + fn from(err: NonZeroError) -> Self { + match err { + NonZeroError::IsZero => SerializationError::IoError(io::Error::new( + io::ErrorKind::Other, + "Value was expected to be non-zero but instead had value zero.", + )), + NonZeroError::Error(err) => err.into(), + } + } +} + +/// Non-Zero Checking Deserializer +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct NonZero(PhantomData); + +impl NonZero { + /// Checks if `item` is zero, returning [`NonZeroError::IsZero`] if so. + #[inline] + fn is_zero(item: &T) -> Result<(), NonZeroError> + where + D: Deserializer, + T: Zero, + { + if item.is_zero() { + return Err(NonZeroError::IsZero); + } + Ok(()) + } +} + +impl Deserializer for NonZero +where + D: Deserializer, + T: Zero, +{ + type Error = NonZeroError; + + #[inline] + fn check(item: &T) -> Result<(), Self::Error> { + Self::is_zero(item)?; + D::check(item).map_err(Self::Error::Error) + } + + #[inline] + fn deserialize_unchecked(reader: &mut R) -> Result + where + R: Read, + { + let item = D::deserialize_unchecked(reader).map_err(Self::Error::Error)?; + Self::is_zero(&item)?; + Ok(item) + } + + #[inline] + fn deserialize_uncompressed(reader: &mut R) -> Result + where + R: Read, + { + let item = D::deserialize_uncompressed(reader).map_err(Self::Error::Error)?; + Self::is_zero(&item)?; + Ok(item) + } + + #[inline] + fn deserialize_compressed(reader: &mut R) -> Result + where + R: Read, + { + let item = D::deserialize_compressed(reader).map_err(Self::Error::Error)?; + Self::is_zero(&item)?; + Ok(item) + } +} From c1b1f748ba4ebe90fdd583d85d21420f577b67f9 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Wed, 22 Jun 2022 23:13:20 -0400 Subject: [PATCH 03/17] wip: build initial setup code Signed-off-by: Brandon H. Gomes --- manta-trusted-setup/src/kzg.rs | 200 +++++++++++++------------------- manta-trusted-setup/src/mpc.rs | 89 ++++++-------- manta-trusted-setup/src/util.rs | 6 + manta-util/src/lib.rs | 15 +-- manta-util/src/macros.rs | 175 ++++++++++++++++++++++++++++ manta-util/src/vec.rs | 10 ++ 6 files changed, 311 insertions(+), 184 deletions(-) create mode 100644 manta-util/src/macros.rs diff --git a/manta-trusted-setup/src/kzg.rs b/manta-trusted-setup/src/kzg.rs index af0efde47..353a264fa 100644 --- a/manta-trusted-setup/src/kzg.rs +++ b/manta-trusted-setup/src/kzg.rs @@ -21,6 +21,7 @@ use crate::util::{ SerializationError, Serializer, Write, Zero, }; use ark_ec::{AffineCurve, PairingEngine}; +use manta_util::{iter, sum, try_for_each, vec::VecExt}; /// KZG Trusted Setup Size pub trait Size { @@ -89,22 +90,22 @@ pub struct PublicKey where C: Pairing, { - /// + /// Tau G1 Ratio pub tau_g1_ratio: (C::G1, C::G1), - /// + /// Alpha G1 Ratio pub alpha_g1_ratio: (C::G1, C::G1), - /// + /// Beta G1 Ratio pub beta_g1_ratio: (C::G1, C::G1), - /// + /// Tau in G2 pub tau_g2: C::G2, - /// + /// Alpha in G2 pub alpha_g2: C::G2, - /// + /// Beta in G2 pub beta_g2: C::G2, } @@ -131,12 +132,15 @@ where #[inline] fn serialized_size(&self) -> usize { - /* TODO: - // Compressed G1 is 48 bytes - // Compressed G2 is 96 bytes - 48 * 2 * 3 + 96 * 3 - */ - todo!() + C::compressed_size(&self.tau_g1_ratio.0) + + C::compressed_size(&self.tau_g1_ratio.1) + + C::compressed_size(&self.alpha_g1_ratio.0) + + C::compressed_size(&self.alpha_g1_ratio.1) + + C::compressed_size(&self.beta_g1_ratio.0) + + C::compressed_size(&self.beta_g1_ratio.1) + + C::compressed_size(&self.tau_g2) + + C::compressed_size(&self.alpha_g2) + + C::compressed_size(&self.beta_g2) } #[inline] @@ -158,12 +162,15 @@ where #[inline] fn uncompressed_size(&self) -> usize { - /* TODO: - // Compressed G1 is 96 bytes - // Compressed G2 is 192 bytes - 96 * 2 * 3 + 192 * 3 - */ - todo!() + C::uncompressed_size(&self.tau_g1_ratio.0) + + C::uncompressed_size(&self.tau_g1_ratio.1) + + C::uncompressed_size(&self.alpha_g1_ratio.0) + + C::uncompressed_size(&self.alpha_g1_ratio.1) + + C::uncompressed_size(&self.beta_g1_ratio.0) + + C::uncompressed_size(&self.beta_g1_ratio.1) + + C::uncompressed_size(&self.tau_g2) + + C::uncompressed_size(&self.alpha_g2) + + C::uncompressed_size(&self.beta_g2) } } @@ -226,19 +233,19 @@ pub struct Accumulator where C: Pairing + Size, { - /// + /// Vector of Tau Powers in G1 of size [`G1_POWERS`] tau_powers_g1: Vec, - /// + /// Vector of Tau Powers in G2 of size [`G2_POWERS`] tau_powers_g2: Vec, - /// + /// Vector of Alpha Multiplied by Tau Powers in G1 of size [`G2_POWERS`] alpha_tau_powers_g1: Vec, - /// + /// Vector of Beta Multiplied by Tau Powers in G1 of size [`G2_POWERS`] beta_tau_powers_g1: Vec, - /// + /// Beta in G2 beta_g2: C::G2, } @@ -269,12 +276,17 @@ where #[inline] fn serialized_size(&self) -> usize { - /* TODO: - // A compressed G1 element is 48 bytes - // A compressed G2 element is 96 bytes - C::G1_POWERS * 48 + C::G2_POWERS * 96 + C::G1_POWERS * 48 * 2 + 96 - */ - todo!() + sum!(iter!(self.tau_powers_g1).map(C::compressed_size), usize) + + sum!(iter!(self.tau_powers_g2).map(C::compressed_size), usize) + + sum!( + iter!(self.alpha_tau_powers_g1).map(C::compressed_size), + usize + ) + + sum!( + iter!(self.beta_tau_powers_g1).map(C::compressed_size), + usize + ) + + C::compressed_size(&self.beta_g2) } #[inline] @@ -300,12 +312,17 @@ where #[inline] fn uncompressed_size(&self) -> usize { - /* TODO: - // An uncompressed G1 element is 96 bytes - // An uncompressed G2 element is 192 bytes - C::G1_POWERS * 96 + C::G2_POWERS * 192 + C::G1_POWERS * 96 * 2 + 192 - */ - todo!() + sum!(iter!(self.tau_powers_g1).map(C::uncompressed_size), usize) + + sum!(iter!(self.tau_powers_g2).map(C::uncompressed_size), usize) + + sum!( + iter!(self.alpha_tau_powers_g1).map(C::uncompressed_size), + usize + ) + + sum!( + iter!(self.beta_tau_powers_g1).map(C::uncompressed_size), + usize + ) + + C::uncompressed_size(&self.beta_g2) } } @@ -318,45 +335,29 @@ where where R: Read, { - /* let mut tau_powers_g1 = Vec::with_capacity(C::G1_POWERS); for _ in 0..C::G1_POWERS { - tau_powers_g1.push( - C::deserialize_g1_compressed(&mut reader) - .map_err(C::convert_serialization_error)?, - ); + tau_powers_g1.push(C::deserialize_compressed(&mut reader).map_err(Into::into)?); } let mut tau_powers_g2 = Vec::with_capacity(C::G2_POWERS); for _ in 0..C::G2_POWERS { - tau_powers_g2.push( - C::deserialize_g2_compressed(&mut reader) - .map_err(C::convert_serialization_error)?, - ); + tau_powers_g2.push(C::deserialize_compressed(&mut reader).map_err(Into::into)?); } let mut alpha_tau_powers_g1 = Vec::with_capacity(C::G2_POWERS); for _ in 0..C::G2_POWERS { - alpha_tau_powers_g1.push( - C::deserialize_g1_compressed(&mut reader) - .map_err(C::convert_serialization_error)?, - ); + alpha_tau_powers_g1.push(C::deserialize_compressed(&mut reader).map_err(Into::into)?); } let mut beta_tau_powers_g1 = Vec::with_capacity(C::G2_POWERS); for _ in 0..C::G2_POWERS { - beta_tau_powers_g1.push( - C::deserialize_g1_compressed(&mut reader) - .map_err(C::convert_serialization_error)?, - ); + beta_tau_powers_g1.push(C::deserialize_compressed(&mut reader).map_err(Into::into)?); } Ok(Self { tau_powers_g1, tau_powers_g2, alpha_tau_powers_g1, beta_tau_powers_g1, - beta_g2: C::deserialize_g2_compressed(&mut reader) - .map_err(C::convert_serialization_error)?, + beta_g2: C::deserialize_compressed(&mut reader).map_err(Into::into)?, }) - */ - todo!() } #[inline] @@ -364,36 +365,13 @@ where where R: Read, { - /* TODO: - let unchecked = Self::deserialize_unchecked(reader)?; - let counter = std::sync::atomic::AtomicU64::new(0); - cfg_try_for_each!(cfg_iter!(&unchecked.tau_powers_g1), |point| { - counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst); - if counter.load(std::sync::atomic::Ordering::SeqCst) % 1000000 == 0 { - println!("Checked this many elements: {:?}", counter); - } - C::curve_point_checks_g1(point) - }) - .map_err(C::convert_serialization_error)?; - cfg_try_for_each!( - cfg_iter!(&unchecked.tau_powers_g2), - C::curve_point_checks_g2 - ) - .map_err(C::convert_serialization_error)?; - cfg_try_for_each!( - cfg_iter!(&unchecked.alpha_tau_powers_g1), - C::curve_point_checks_g1 - ) - .map_err(C::convert_serialization_error)?; - cfg_try_for_each!( - cfg_iter!(&unchecked.beta_tau_powers_g1), - C::curve_point_checks_g1 - ) - .map_err(C::convert_serialization_error)?; - C::curve_point_checks_g2(&unchecked.beta_g2).map_err(C::convert_serialization_error)?; - Ok(unchecked) - */ - todo!() + let accumulator = Self::deserialize_unchecked(reader)?; + try_for_each!(iter!(&accumulator.tau_powers_g1), C::check).map_err(Into::into)?; + try_for_each!(iter!(&accumulator.tau_powers_g2), C::check).map_err(Into::into)?; + try_for_each!(iter!(&accumulator.alpha_tau_powers_g1), C::check).map_err(Into::into)?; + try_for_each!(iter!(&accumulator.beta_tau_powers_g1), C::check).map_err(Into::into)?; + C::check(&accumulator.beta_g2).map_err(Into::into)?; + Ok(accumulator) } #[inline] @@ -401,41 +379,25 @@ where where R: Read, { - /* TODO: - let mut tau_powers_g1 = Vec::with_capacity(C::G1_POWERS); - for i in 0..C::G1_POWERS { - tau_powers_g1.push( - C::deserialize_g1_unchecked(&mut reader).map_err(C::convert_serialization_error)?, - ); - } - let mut tau_powers_g2 = Vec::with_capacity(C::G2_POWERS); - for i in 0..C::G2_POWERS { - tau_powers_g2.push( - C::deserialize_g2_unchecked(&mut reader).map_err(C::convert_serialization_error)?, - ); - } - let mut alpha_tau_powers_g1 = Vec::with_capacity(C::G2_POWERS); - for i in 0..C::G2_POWERS { - alpha_tau_powers_g1.push( - C::deserialize_g1_unchecked(&mut reader).map_err(C::convert_serialization_error)?, - ); - } - let mut beta_tau_powers_g1 = Vec::with_capacity(C::G2_POWERS); - for i in 0..C::G2_POWERS { - beta_tau_powers_g1.push( - C::deserialize_g1_unchecked(&mut reader).map_err(C::convert_serialization_error)?, - ); - } Ok(Self { - tau_powers_g1, - tau_powers_g2, - alpha_tau_powers_g1, - beta_tau_powers_g1, - beta_g2: C::deserialize_g2_unchecked(&mut reader) - .map_err(C::convert_serialization_error)?, + tau_powers_g1: Vec::try_allocate_with(C::G1_POWERS, |_| { + C::deserialize_unchecked(&mut reader) + }) + .map_err(Into::into)?, + tau_powers_g2: Vec::try_allocate_with(C::G2_POWERS, |_| { + C::deserialize_unchecked(&mut reader) + }) + .map_err(Into::into)?, + alpha_tau_powers_g1: Vec::try_allocate_with(C::G2_POWERS, |_| { + C::deserialize_unchecked(&mut reader) + }) + .map_err(Into::into)?, + beta_tau_powers_g1: Vec::try_allocate_with(C::G2_POWERS, |_| { + C::deserialize_unchecked(&mut reader) + }) + .map_err(Into::into)?, + beta_g2: C::deserialize_unchecked(&mut reader).map_err(Into::into)?, }) - */ - todo!() } } diff --git a/manta-trusted-setup/src/mpc.rs b/manta-trusted-setup/src/mpc.rs index ddd5bbc02..351e8a0cf 100644 --- a/manta-trusted-setup/src/mpc.rs +++ b/manta-trusted-setup/src/mpc.rs @@ -14,96 +14,83 @@ // You should have received a copy of the GNU General Public License // along with manta-rs. If not, see . -//! MPC Primitives +//! Secure Multi-Party Computation Primitives -/// -pub trait Contribute { - /// - type Accumulator; +/// Secure Multi-Party Computation Types +pub trait Types { + /// State Type + type State; - /// - type Contribution; - - /// - type PublicKey; + /// Contribution Proof Type + type Proof; - /// + /// Challenge Type type Challenge; - /// + /// Response Type type Response; +} - /// +/// Contribution +pub trait Contribute: Types { + /// Private Contribution Data + type Contribution; + + /// Comptues the next state from `state`, `challenge`, and `contribution`. fn contribute( &self, - accumulator: &Self::Accumulator, + state: &Self::State, challenge: &Self::Challenge, contribution: &Self::Contribution, - ) -> (Self::Response, Self::PublicKey, Self::Accumulator); + ) -> (Self::State, Self::Response, Self::Proof); } -/// -pub trait Verify { - /// Accumulator - type Accumulator; - - /// Contribution Public Key - type PublicKey; - - /// Challenge - type Challenge; - - /// Response - type Response; - +/// Verification +pub trait Verify: Types { /// Error type Error; /// Computes the challenge associated to `last` and `last_response` for the next player. - fn challenge( - &self, - last: &Self::Accumulator, - last_response: &Self::Response, - ) -> Self::Challenge; + fn challenge(&self, last: &Self::State, last_response: &Self::Response) -> Self::Challenge; - /// Computes the response from `next` and `next_key` to the `challenge` presented by the + /// Computes the response from `next` and `next_proof` to the `challenge` presented by the /// previous state. fn response( &self, - next: &Self::Accumulator, - next_key: &Self::PublicKey, + next: &Self::State, + next_proof: &Self::Proof, challenge: Self::Challenge, ) -> Self::Response; - /// Verifies the transformation from `last` to `next` using the `next_key` and `next_response` - /// as evidence for the correct update of the state. This method returns the `next` accumulator + /// Verifies the transformation from `last` to `next` using the `next_proof` and `next_response` + /// as evidence for the correct update of the state. This method returns the `next` state /// and `next_response`. fn verify( &self, - last: Self::Accumulator, - next: Self::Accumulator, - next_key: Self::PublicKey, + last: Self::State, + next: Self::State, + next_proof: Self::Proof, next_response: Self::Challenge, - ) -> Result<(Self::Accumulator, Self::Response), Self::Error>; + ) -> Result<(Self::State, Self::Response), Self::Error>; - /// Verifies all accumulator contributions in `iter` chaining from `last` and `last_response` - /// returning the newest [`Accumulator`](Self::Accumulator) and [`Response`](Self::Response) if - /// all the contributions in the chain had valid transitions. + /// Verifies all contributions in `iter` chaining from `last` and `last_response` returning the + /// newest [`State`](Self::State) and [`Response`](Self::Response) if all the contributions in + /// the chain had valid transitions. #[inline] fn verify_all( &self, - mut last: Self::Accumulator, + mut last: Self::State, mut last_response: Self::Response, iter: I, - ) -> Result<(Self::Accumulator, Self::Response), Self::Error> + ) -> Result<(Self::State, Self::Response), Self::Error> where E: Into, - I: IntoIterator>, + I: IntoIterator>, { for item in iter { - let (next, next_key) = item.map_err(Into::into)?; + let (next, next_proof) = item.map_err(Into::into)?; let next_challenge = self.challenge(&next, &last_response); - (last, last_response) = self.verify(last, next, next_key, next_challenge)?; + (last, last_response) = self.verify(last, next, next_proof, next_challenge)?; } Ok((last, last_response)) } diff --git a/manta-trusted-setup/src/util.rs b/manta-trusted-setup/src/util.rs index 9d0225076..e5d0b0d97 100644 --- a/manta-trusted-setup/src/util.rs +++ b/manta-trusted-setup/src/util.rs @@ -54,10 +54,16 @@ pub trait Serializer { where W: Write; + /// Returns the size in bytes of the uncompressed form of `item`. + fn uncompressed_size(item: &T) -> usize; + /// Serializes `item` in compressed form to the `writer`, performing all well-formedness checks. fn serialize_compressed(item: &T, writer: &mut W) -> Result<(), io::Error> where W: Write; + + /// Returns the size in bytes of the compressed form of `item`. + fn compressed_size(item: &T) -> usize; } /// Custom Deserialization Adapter diff --git a/manta-util/src/lib.rs b/manta-util/src/lib.rs index d932eb31e..9b9e56dcd 100644 --- a/manta-util/src/lib.rs +++ b/manta-util/src/lib.rs @@ -26,6 +26,7 @@ extern crate alloc; mod array; mod bytes; +mod macros; mod sealed; pub mod codec; @@ -54,17 +55,3 @@ pub use serde; #[cfg_attr(doc_cfg, doc(cfg(feature = "serde_with")))] #[doc(inline)] pub use serde_with; - -/// Implements [`From`]`<$from>` for an enum `$to`, choosing the `$kind` variant. -// TODO: add `where` clauses -#[macro_export] -macro_rules! from_variant_impl { - ($to:ty, $kind:ident, $from:ty) => { - impl From<$from> for $to { - #[inline] - fn from(t: $from) -> Self { - Self::$kind(t) - } - } - }; -} diff --git a/manta-util/src/macros.rs b/manta-util/src/macros.rs new file mode 100644 index 000000000..362374202 --- /dev/null +++ b/manta-util/src/macros.rs @@ -0,0 +1,175 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! Utility Macros + +/// Implements [`From`]`<$from>` for an enum `$to`, choosing the `$kind` variant. +#[macro_export] +macro_rules! from_variant_impl { + ($to:ty, $kind:ident, $from:ty) => { + impl From<$from> for $to { + #[inline] + fn from(t: $from) -> Self { + Self::$kind(t) + } + } + }; +} + +/// Calls the `into_iter` method on `$e` or the `into_par_iter` Rayon method if the `rayon` feature +/// is enabled. +#[macro_export] +macro_rules! into_iter { + ($e:expr) => {{ + #[cfg(feature = "rayon")] + let result = ::rayon::iter::IntoParallelIterator::into_par_iter($e); + #[cfg(not(feature = "rayon"))] + let result = $e.into_iter(); + result + }}; +} + +/// Calls the `iter` method on `$e` or the `par_iter` Rayon method if the `rayon` feature is +/// enabled. +#[macro_export] +macro_rules! iter { + ($e:expr) => {{ + #[cfg(feature = "rayon")] + let result = ::rayon::iter::IntoParallelRefIterator::par_iter($e); + #[cfg(not(feature = "rayon"))] + let result = $e.iter(); + result + }}; +} + +/// Calls the `iter_mut` method on `$e` or the `par_iter_mut` Rayon method if the `rayon` feature is +/// enabled. +#[macro_export] +macro_rules! iter_mut { + ($e:expr) => {{ + #[cfg(feature = "rayon")] + let result = ::rayon::iter::IntoParallelRefMutIterator::par_iter_mut($e); + #[cfg(not(feature = "rayon"))] + let result = $e.iter_mut(); + result + }}; +} + +/// Calls the `chunks` method on `$e` or the `par_chunks` Rayon method if the `rayon` feature is +/// enabled. +#[macro_export] +macro_rules! chunks { + ($e:expr, $size:expr) => {{ + #[cfg(feature = "rayon")] + let result = ::rayon::slice::ParallelSlice::par_chunks($e, $size); + #[cfg(not(feature = "rayon"))] + let result = $e.chunks($size); + result + }}; +} + +/// Calls the `chunks_mut` method on `$e` or the `par_chunks_mut` Rayon method if the `rayon` +/// feature is enabled. +#[macro_export] +macro_rules! chunks_mut { + ($e:expr, $size:expr) => {{ + #[cfg(feature = "rayon")] + let result = ::rayon::slice::ParallelSliceMut::par_chunks_mut($e, $size); + #[cfg(not(feature = "rayon"))] + let result = $e.chunks_mut($size); + result + }}; +} + +/// Calls the `fold` method on `$e` or the `reduce` Rayon method if the `rayon` feature is enabled. +#[macro_export] +macro_rules! reduce { + ($e:expr, $default:expr, $op:expr) => {{ + #[cfg(feature = "rayon")] + let result = ::rayon::iter::ParallelIterator::reduce($e, $default, $op); + #[cfg(not(feature = "rayon"))] + let result = $e.fold($default(), $op); + result + }}; +} + +/// Calls the `sum` method on `$e` or the `sum` Rayon method if the `rayon` feature is enabled. +#[macro_export] +macro_rules! sum { + ($e:expr) => {{ + $crate::sum!($e, _) + }}; + ($e:expr, $T:ty) => {{ + #[cfg(feature = "rayon")] + let result = ::rayon::iter::ParallelIterator::sum::<$T>($e); + #[cfg(not(feature = "rayon"))] + let result = $e.sum::<$T>(); + result + }}; +} + +/// Calls the `product` method on `$e` or the `product` Rayon method if the `rayon` feature is +/// enabled. +#[macro_export] +macro_rules! product { + ($e:expr) => {{ + $crate::product!($e, _) + }}; + ($e:expr, $T:ty) => {{ + #[cfg(feature = "rayon")] + let result = ::rayon::iter::ParallelIterator::product::<$T>($e); + #[cfg(not(feature = "rayon"))] + let result = $e.product::<$T>(); + result + }}; +} + +/// Calls the `min` method on `$e` or the `min` Rayon method if the `rayon` feature is enabled. +#[macro_export] +macro_rules! min { + ($e:expr) => {{ + #[cfg(feature = "rayon")] + let result = ::rayon::iter::ParallelIterator::min($e); + #[cfg(not(feature = "rayon"))] + let result = $e.min(); + result + }}; +} + +/// Calls the `max` method on `$e` or the `max` Rayon method if the `rayon` feature is enabled. +#[macro_export] +macro_rules! max { + ($e:expr) => {{ + #[cfg(feature = "rayon")] + let result = ::rayon::iter::ParallelIterator::max($e); + #[cfg(not(feature = "rayon"))] + let result = $e.max(); + result + }}; +} + +/// Calls the `try_for_each` method on `$e` or the `try_for_each` Rayon method if the `rayon` +/// feature is enabled. +#[macro_export] +macro_rules! try_for_each { + ($e:expr, $op:expr) => {{ + #[cfg(feature = "rayon")] + let result = ::rayon::iter::ParallelIterator::try_for_each($e, $op); + #[cfg(not(feature = "rayon"))] + let result = $e.try_for_each($op); + result + }}; +} diff --git a/manta-util/src/vec.rs b/manta-util/src/vec.rs index f4848a525..14cbe9865 100644 --- a/manta-util/src/vec.rs +++ b/manta-util/src/vec.rs @@ -51,6 +51,16 @@ pub trait VecExt: From> + Into> + sealed::Sealed + Sized { vec.resize_with(n, f); vec.into() } + + /// Allocates a vector of length `n` and tries to initialize it with `f`, returning an error if + /// `f` ever fails. + #[inline] + fn try_allocate_with(n: usize, f: F) -> Result + where + F: FnMut(usize) -> Result, + { + (0..n).map(f).collect::, _>>().map(Into::into) + } } impl VecExt for Vec {} From 168d6eaa0be3ea789de00bb3faeac47246f0c64e Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Thu, 23 Jun 2022 02:34:20 -0400 Subject: [PATCH 04/17] feat: add phase1 abstract framework --- manta-trusted-setup/Cargo.toml | 6 +- manta-trusted-setup/src/kzg.rs | 626 +++++++++++++++++++++++++------- manta-trusted-setup/src/mpc.rs | 18 +- manta-trusted-setup/src/util.rs | 176 ++++++++- manta-util/src/macros.rs | 157 ++++---- 5 files changed, 749 insertions(+), 234 deletions(-) diff --git a/manta-trusted-setup/Cargo.toml b/manta-trusted-setup/Cargo.toml index dc20077f7..413a858bd 100644 --- a/manta-trusted-setup/Cargo.toml +++ b/manta-trusted-setup/Cargo.toml @@ -25,6 +25,9 @@ is-it-maintained-open-issues = { repository = "Manta-Network/manta-rs" } maintenance = { status = "actively-developed" } [features] +# Rayon Parallelization +rayon = ["dep:rayon", "manta-util/rayon"] + # Standard Library std = [] @@ -38,5 +41,6 @@ ark-serialize = { version = "0.3.0", default-features = false, features = ["deri ark-snark = { version = "0.3.0", default-features = false } ark-std = { version = "0.3.0", default-features = false } derivative = { version = "2.2.0", default-features = false, features = ["use_core"] } -manta-crypto = { path = "../manta-crypto", default-features = false } +manta-crypto = { path = "../manta-crypto", default-features = false, features = ["getrandom"] } manta-util = { path = "../manta-util", default-features = false, features = ["alloc"] } +rayon = { version = "1.5.3", optional = true, default-features = false } diff --git a/manta-trusted-setup/src/kzg.rs b/manta-trusted-setup/src/kzg.rs index 353a264fa..7b06b10c3 100644 --- a/manta-trusted-setup/src/kzg.rs +++ b/manta-trusted-setup/src/kzg.rs @@ -17,11 +17,18 @@ //! KZG Trusted Setup use crate::util::{ - CanonicalDeserialize, CanonicalSerialize, Deserializer, HasDistribution, NonZero, Read, Sample, - SerializationError, Serializer, Write, Zero, + power_pairs, scalar_mul, CanonicalDeserialize, CanonicalSerialize, Deserializer, + HasDistribution, NonZero, One, PairingEngineExt, Read, Sample, SerializationError, Serializer, + Write, Zero, }; -use ark_ec::{AffineCurve, PairingEngine}; -use manta_util::{iter, sum, try_for_each, vec::VecExt}; +use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ff::{PrimeField, UniformRand}; +use core::{iter, ops::Mul}; +use manta_crypto::rand::{CryptoRng, Rand, RngCore}; +use manta_util::{cfg_iter, cfg_iter_mut, from_variant, vec::VecExt}; + +#[cfg(feature = "rayon")] +use rayon::iter::{IndexedParallelIterator, ParallelIterator}; /// KZG Trusted Setup Size pub trait Size { @@ -32,30 +39,82 @@ pub trait Size { const G2_POWERS: usize; } -/// +/// Pairing Configuration pub trait Pairing: HasDistribution { - /// - type Scalar; + /// Underlying Scalar Field + type Scalar: PrimeField + One; /// First Group of the Pairing - type G1: AffineCurve + Sample + Zero; + type G1: AffineCurve + + Into + + Sample + + Zero; + + /// First Group Pairing-Prepared Point + type G1Prepared; /// Second Group of the Pairing - type G2: AffineCurve + Sample + Zero; + type G2: AffineCurve + + Into + + Sample + + Zero; - /// Pairing Engine Type - type Engine: PairingEngine; + /// Second Group Pairing-Prepared Point + type G2Prepared; - /// + /// Pairing Engine Type + type Pairing: PairingEngine< + G1Affine = Self::G1, + G2Affine = Self::G2, + G1Prepared = Self::G1Prepared, + G2Prepared = Self::G2Prepared, + >; + + /// Returns the base G1 generator for this configuration. fn g1_prime_subgroup_generator() -> Self::G1; - /// + /// Returns the base G2 generator for this configuration. fn g2_prime_subgroup_generator() -> Self::G2; } -/// Verification Error +/// Trusted Setup Configuration +pub trait Configuration: Pairing + Size { + /// Domain Tag + type DomainTag; + + /// Challenge Type + type Challenge; + + /// Response Type + type Response; + + /// Tau Domain Tag for [`hash_to_g2`](Self::hash_to_g2) + const TAU_DOMAIN_TAG: Self::DomainTag; + + /// Alpha Domain Tag for [`hash_to_g2`](Self::hash_to_g2) + const ALPHA_DOMAIN_TAG: Self::DomainTag; + + /// Beta Domain Tag for [`hash_to_g2`](Self::hash_to_g2) + const BETA_DOMAIN_TAG: Self::DomainTag; + + /// Computes the challenge G2 point from `domain_tag`, `challenge`, and `ratio`. + fn hash_to_g2( + domain_tag: Self::DomainTag, + challenge: &Self::Challenge, + ratio: (&Self::G1, &Self::G1), + ) -> Self::G2; + + /// Computes the challenge response from `state`, `challenge`, and `proof`. + fn response( + state: &Accumulator, + challenge: &Self::Challenge, + proof: &Proof, + ) -> Self::Response; +} + +/// Knowledge Proof Error #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum VerificationError { +pub enum KnowledgeError { /// Invalid Proof of Knowledge for τ TauKnowledgeProof, @@ -64,13 +123,20 @@ pub enum VerificationError { /// Invalid Proof of Knowledge for β BetaKnowledgeProof, +} +/// Verification Error +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub enum VerificationError { /// Element Differs from Prime Subgroup Generator in G1 PrimeSubgroupGeneratorG1, /// Element Differs from Prime Subgroup Generator in G2 PrimeSubgroupGeneratorG2, + /// Knowledge Proof Error + Knowledge(KnowledgeError), + /// Invalid Multiplication of τ TauMultiplication, @@ -80,36 +146,217 @@ pub enum VerificationError { /// Invalid Multiplication of β BetaMultiplication, - /// Invalid Computation of Powers of τ - PowersOfTau, + /// Invalid Computation of Powers of τ in G1 + TauG1Powers, + + /// Invalid Computation of Powers of τ in G2 + TauG2Powers, + + /// Invalid Computation of Powers of α in G1 + AlphaG1Powers, + + /// Invalid Computation of Powers of β in G1 + BetaG1Powers, } -/// Contribution Public Key -#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)] -pub struct PublicKey +from_variant!(VerificationError, Knowledge, KnowledgeError); + +/// Contribution +pub struct Contribution where C: Pairing, { - /// Tau G1 Ratio - pub tau_g1_ratio: (C::G1, C::G1), + /// Tau Scalar + tau: C::Scalar, - /// Alpha G1 Ratio - pub alpha_g1_ratio: (C::G1, C::G1), + /// Alpha Scalar + alpha: C::Scalar, - /// Beta G1 Ratio - pub beta_g1_ratio: (C::G1, C::G1), + /// Beta Scalar + beta: C::Scalar, +} - /// Tau in G2 - pub tau_g2: C::G2, +impl Contribution +where + C: Configuration, +{ + /// Generates a proof of knowledge for `self`. + #[inline] + pub fn proof(&self, challenge: &C::Challenge, rng: &mut R) -> Option> + where + R: CryptoRng + RngCore + ?Sized, + { + Some(Proof { + tau: RatioProof::build(C::TAU_DOMAIN_TAG, challenge, &self.tau, rng)?, + alpha: RatioProof::build(C::ALPHA_DOMAIN_TAG, challenge, &self.alpha, rng)?, + beta: RatioProof::build(C::BETA_DOMAIN_TAG, challenge, &self.beta, rng)?, + }) + } +} + +impl Sample for Contribution +where + C: Pairing, +{ + #[inline] + fn sample(_: (), rng: &mut R) -> Self + where + R: CryptoRng + RngCore + ?Sized, + { + Self { + tau: C::Scalar::rand(rng), + alpha: C::Scalar::rand(rng), + beta: C::Scalar::rand(rng), + } + } +} - /// Alpha in G2 - pub alpha_g2: C::G2, +/// Pairing Ratio Proof of Knowledge +#[derive(derivative::Derivative)] +#[derivative(Clone, Debug, Default, Eq, Hash, PartialEq)] +pub struct RatioProof +where + C: Pairing + ?Sized, +{ + /// Ratio in G1 + pub ratio: (C::G1, C::G1), - /// Beta in G2 - pub beta_g2: C::G2, + /// Matching Point in G2 + pub matching_point: C::G2, } -impl CanonicalSerialize for PublicKey +impl RatioProof +where + C: Pairing, +{ + /// Builds a [`RatioProof`] for `scalar` against `challenge`. + #[inline] + pub fn build( + domain_tag: C::DomainTag, + challenge: &C::Challenge, + scalar: &C::Scalar, + rng: &mut R, + ) -> Option + where + C: Configuration, + R: CryptoRng + RngCore + ?Sized, + { + let g1_point = rng.gen::<_, C::G1>(); + if g1_point.is_zero() { + return None; + } + let scaled_g1_point = g1_point.mul(*scalar).into_affine(); + if scaled_g1_point.is_zero() { + return None; + } + let ratio = (g1_point, scaled_g1_point); + let g2_point = C::hash_to_g2(domain_tag, challenge, (&ratio.0, &ratio.1)); + if g2_point.is_zero() { + return None; + } + let scaled_g2_point = g2_point.mul(*scalar).into_affine(); + if scaled_g2_point.is_zero() { + return None; + } + Some(Self { + ratio, + matching_point: scaled_g2_point, + }) + } + + /// Computes the challenge point that corresponds with the given `challenge`. + #[inline] + pub fn challenge_point(&self, domain_tag: C::DomainTag, challenge: &C::Challenge) -> C::G2 + where + C: Configuration, + { + C::hash_to_g2(domain_tag, challenge, (&self.ratio.0, &self.ratio.1)) + } + + /// Verifies that `self` is a valid ratio proof-of-knowledge, returning the G2 ratio of the + /// underlying scalar. + #[inline] + pub fn verify( + self, + domain_tag: C::DomainTag, + challenge: &C::Challenge, + ) -> Option<(C::G2Prepared, C::G2Prepared)> + where + C: Configuration, + { + let challenge_point = self.challenge_point(domain_tag, challenge); + let ((_, matching_point), (_, challenge_point)) = C::Pairing::same( + (self.ratio.0, self.matching_point), + (self.ratio.1, challenge_point), + )?; + Some((matching_point, challenge_point)) + } +} + +/// Knowledge Proof Certificate +pub struct KnowledgeProofCeritificate +where + C: Pairing, +{ + /// Tau Ratio in G2 + pub tau: (C::G2Prepared, C::G2Prepared), + + /// Alpha Ratio in G2 + pub alpha: (C::G2Prepared, C::G2Prepared), + + /// Beta Ratio in G2 + pub beta: (C::G2Prepared, C::G2Prepared), +} + +/// Contribution Proof +#[derive(derivative::Derivative)] +#[derivative(Clone, Debug, Default, Eq, Hash, PartialEq)] +pub struct Proof +where + C: Pairing + ?Sized, +{ + /// Tau Ratio Proof + pub tau: RatioProof, + + /// Alpha Ratio Proof + pub alpha: RatioProof, + + /// Beta Ratio Proof + pub beta: RatioProof, +} + +impl Proof +where + C: Pairing, +{ + /// Verifies that all [`RatioProof`]s in `self` are valid, returning all of their G2 ratios. See + /// [`RatioProof::verify`] for more. + #[inline] + pub fn verify( + self, + challenge: &C::Challenge, + ) -> Result, KnowledgeError> + where + C: Configuration, + { + Ok(KnowledgeProofCeritificate { + tau: self + .tau + .verify(C::TAU_DOMAIN_TAG, challenge) + .ok_or(KnowledgeError::TauKnowledgeProof)?, + alpha: self + .alpha + .verify(C::ALPHA_DOMAIN_TAG, challenge) + .ok_or(KnowledgeError::AlphaKnowledgeProof)?, + beta: self + .beta + .verify(C::BETA_DOMAIN_TAG, challenge) + .ok_or(KnowledgeError::BetaKnowledgeProof)?, + }) + } +} + +impl CanonicalSerialize for Proof where C: Pairing + Serializer + Serializer, { @@ -118,29 +365,29 @@ where where W: Write, { - C::serialize_compressed(&self.tau_g1_ratio.0, &mut writer)?; - C::serialize_compressed(&self.tau_g1_ratio.1, &mut writer)?; - C::serialize_compressed(&self.alpha_g1_ratio.0, &mut writer)?; - C::serialize_compressed(&self.alpha_g1_ratio.1, &mut writer)?; - C::serialize_compressed(&self.beta_g1_ratio.0, &mut writer)?; - C::serialize_compressed(&self.beta_g1_ratio.1, &mut writer)?; - C::serialize_compressed(&self.tau_g2, &mut writer)?; - C::serialize_compressed(&self.alpha_g2, &mut writer)?; - C::serialize_compressed(&self.beta_g2, &mut writer)?; + C::serialize_compressed(&self.tau.ratio.0, &mut writer)?; + C::serialize_compressed(&self.tau.ratio.1, &mut writer)?; + C::serialize_compressed(&self.alpha.ratio.0, &mut writer)?; + C::serialize_compressed(&self.alpha.ratio.1, &mut writer)?; + C::serialize_compressed(&self.beta.ratio.0, &mut writer)?; + C::serialize_compressed(&self.beta.ratio.1, &mut writer)?; + C::serialize_compressed(&self.tau.matching_point, &mut writer)?; + C::serialize_compressed(&self.alpha.matching_point, &mut writer)?; + C::serialize_compressed(&self.beta.matching_point, &mut writer)?; Ok(()) } #[inline] fn serialized_size(&self) -> usize { - C::compressed_size(&self.tau_g1_ratio.0) - + C::compressed_size(&self.tau_g1_ratio.1) - + C::compressed_size(&self.alpha_g1_ratio.0) - + C::compressed_size(&self.alpha_g1_ratio.1) - + C::compressed_size(&self.beta_g1_ratio.0) - + C::compressed_size(&self.beta_g1_ratio.1) - + C::compressed_size(&self.tau_g2) - + C::compressed_size(&self.alpha_g2) - + C::compressed_size(&self.beta_g2) + C::compressed_size(&self.tau.ratio.0) + + C::compressed_size(&self.tau.ratio.1) + + C::compressed_size(&self.alpha.ratio.0) + + C::compressed_size(&self.alpha.ratio.1) + + C::compressed_size(&self.beta.ratio.0) + + C::compressed_size(&self.beta.ratio.1) + + C::compressed_size(&self.tau.matching_point) + + C::compressed_size(&self.alpha.matching_point) + + C::compressed_size(&self.beta.matching_point) } #[inline] @@ -148,33 +395,33 @@ where where W: Write, { - C::serialize_uncompressed(&self.tau_g1_ratio.0, &mut writer)?; - C::serialize_uncompressed(&self.tau_g1_ratio.1, &mut writer)?; - C::serialize_uncompressed(&self.alpha_g1_ratio.0, &mut writer)?; - C::serialize_uncompressed(&self.alpha_g1_ratio.1, &mut writer)?; - C::serialize_uncompressed(&self.beta_g1_ratio.0, &mut writer)?; - C::serialize_uncompressed(&self.beta_g1_ratio.1, &mut writer)?; - C::serialize_uncompressed(&self.tau_g2, &mut writer)?; - C::serialize_uncompressed(&self.alpha_g2, &mut writer)?; - C::serialize_uncompressed(&self.beta_g2, &mut writer)?; + C::serialize_uncompressed(&self.tau.ratio.0, &mut writer)?; + C::serialize_uncompressed(&self.tau.ratio.1, &mut writer)?; + C::serialize_uncompressed(&self.alpha.ratio.0, &mut writer)?; + C::serialize_uncompressed(&self.alpha.ratio.1, &mut writer)?; + C::serialize_uncompressed(&self.beta.ratio.0, &mut writer)?; + C::serialize_uncompressed(&self.beta.ratio.1, &mut writer)?; + C::serialize_uncompressed(&self.tau.matching_point, &mut writer)?; + C::serialize_uncompressed(&self.alpha.matching_point, &mut writer)?; + C::serialize_uncompressed(&self.beta.matching_point, &mut writer)?; Ok(()) } #[inline] fn uncompressed_size(&self) -> usize { - C::uncompressed_size(&self.tau_g1_ratio.0) - + C::uncompressed_size(&self.tau_g1_ratio.1) - + C::uncompressed_size(&self.alpha_g1_ratio.0) - + C::uncompressed_size(&self.alpha_g1_ratio.1) - + C::uncompressed_size(&self.beta_g1_ratio.0) - + C::uncompressed_size(&self.beta_g1_ratio.1) - + C::uncompressed_size(&self.tau_g2) - + C::uncompressed_size(&self.alpha_g2) - + C::uncompressed_size(&self.beta_g2) + C::uncompressed_size(&self.tau.ratio.0) + + C::uncompressed_size(&self.tau.ratio.1) + + C::uncompressed_size(&self.alpha.ratio.0) + + C::uncompressed_size(&self.alpha.ratio.1) + + C::uncompressed_size(&self.beta.ratio.0) + + C::uncompressed_size(&self.beta.ratio.1) + + C::uncompressed_size(&self.tau.matching_point) + + C::uncompressed_size(&self.alpha.matching_point) + + C::uncompressed_size(&self.beta.matching_point) } } -impl CanonicalDeserialize for PublicKey +impl CanonicalDeserialize for Proof where C: Deserializer + Deserializer + Pairing, { @@ -183,22 +430,31 @@ where where R: Read, { + let tau_ratio = ( + NonZero::::deserialize_compressed(&mut reader)?, + NonZero::::deserialize_compressed(&mut reader)?, + ); + let alpha_ratio = ( + NonZero::::deserialize_compressed(&mut reader)?, + NonZero::::deserialize_compressed(&mut reader)?, + ); + let beta_ratio = ( + NonZero::::deserialize_compressed(&mut reader)?, + NonZero::::deserialize_compressed(&mut reader)?, + ); Ok(Self { - tau_g1_ratio: ( - NonZero::::deserialize_compressed(&mut reader)?, - NonZero::::deserialize_compressed(&mut reader)?, - ), - alpha_g1_ratio: ( - NonZero::::deserialize_compressed(&mut reader)?, - NonZero::::deserialize_compressed(&mut reader)?, - ), - beta_g1_ratio: ( - NonZero::::deserialize_compressed(&mut reader)?, - NonZero::::deserialize_compressed(&mut reader)?, - ), - tau_g2: NonZero::::deserialize_compressed(&mut reader)?, - alpha_g2: NonZero::::deserialize_compressed(&mut reader)?, - beta_g2: NonZero::::deserialize_compressed(&mut reader)?, + tau: RatioProof { + ratio: tau_ratio, + matching_point: NonZero::::deserialize_compressed(&mut reader)?, + }, + alpha: RatioProof { + ratio: alpha_ratio, + matching_point: NonZero::::deserialize_compressed(&mut reader)?, + }, + beta: RatioProof { + ratio: beta_ratio, + matching_point: NonZero::::deserialize_compressed(&mut reader)?, + }, }) } @@ -207,22 +463,31 @@ where where R: Read, { + let tau_ratio = ( + NonZero::::deserialize_uncompressed(&mut reader)?, + NonZero::::deserialize_uncompressed(&mut reader)?, + ); + let alpha_ratio = ( + NonZero::::deserialize_uncompressed(&mut reader)?, + NonZero::::deserialize_uncompressed(&mut reader)?, + ); + let beta_ratio = ( + NonZero::::deserialize_uncompressed(&mut reader)?, + NonZero::::deserialize_uncompressed(&mut reader)?, + ); Ok(Self { - tau_g1_ratio: ( - NonZero::::deserialize_uncompressed(&mut reader)?, - NonZero::::deserialize_uncompressed(&mut reader)?, - ), - alpha_g1_ratio: ( - NonZero::::deserialize_uncompressed(&mut reader)?, - NonZero::::deserialize_uncompressed(&mut reader)?, - ), - beta_g1_ratio: ( - NonZero::::deserialize_uncompressed(&mut reader)?, - NonZero::::deserialize_uncompressed(&mut reader)?, - ), - tau_g2: NonZero::::deserialize_uncompressed(&mut reader)?, - alpha_g2: NonZero::::deserialize_uncompressed(&mut reader)?, - beta_g2: NonZero::::deserialize_uncompressed(&mut reader)?, + tau: RatioProof { + ratio: tau_ratio, + matching_point: NonZero::::deserialize_uncompressed(&mut reader)?, + }, + alpha: RatioProof { + ratio: alpha_ratio, + matching_point: NonZero::::deserialize_uncompressed(&mut reader)?, + }, + beta: RatioProof { + ratio: beta_ratio, + matching_point: NonZero::::deserialize_uncompressed(&mut reader)?, + }, }) } } @@ -231,24 +496,113 @@ where #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct Accumulator where - C: Pairing + Size, + C: Pairing + Size + ?Sized, { - /// Vector of Tau Powers in G1 of size [`G1_POWERS`] + /// Vector of Tau Powers in G1 of size [`G1_POWERS`](Size::G1_POWERS) tau_powers_g1: Vec, - /// Vector of Tau Powers in G2 of size [`G2_POWERS`] + /// Vector of Tau Powers in G2 of size [`G2_POWERS`](Size::G2_POWERS) tau_powers_g2: Vec, - /// Vector of Alpha Multiplied by Tau Powers in G1 of size [`G2_POWERS`] + /// Vector of Alpha Multiplied by Tau Powers in G1 of size [`G2_POWERS`](Size::G2_POWERS) alpha_tau_powers_g1: Vec, - /// Vector of Beta Multiplied by Tau Powers in G1 of size [`G2_POWERS`] + /// Vector of Beta Multiplied by Tau Powers in G1 of size [`G2_POWERS`](Size::G2_POWERS) beta_tau_powers_g1: Vec, /// Beta in G2 beta_g2: C::G2, } +impl Accumulator +where + C: Pairing + Size, +{ + /// Updates `self` by multiplying each element of the accumulator by the powers of its + /// respective element in the `contribution`. + #[inline] + pub fn update(&mut self, contribution: &Contribution) { + let mut tau_powers = + iter::successors(Some(C::Scalar::one()), |x| Some(x.mul(contribution.tau))) + .collect::>(); + let remaining_tau_powers = tau_powers.split_off(C::G2_POWERS); + cfg_iter_mut!(self.tau_powers_g1) + .zip(cfg_iter_mut!(self.tau_powers_g2)) + .zip(cfg_iter_mut!(self.alpha_tau_powers_g1)) + .zip(cfg_iter_mut!(self.beta_tau_powers_g1)) + .zip(tau_powers) + .for_each( + |((((tau_g1, tau_g2), alpha_tau_g1), beta_tau_g1), tau_power)| { + scalar_mul(tau_g1, tau_power); + scalar_mul(tau_g2, tau_power); + scalar_mul(alpha_tau_g1, tau_power.mul(contribution.alpha)); + scalar_mul(beta_tau_g1, tau_power.mul(contribution.beta)); + }, + ); + cfg_iter_mut!(self.tau_powers_g1) + .skip(C::G2_POWERS) + .zip(remaining_tau_powers) + .for_each(|(tau_g1, tau_power)| scalar_mul(tau_g1, tau_power)); + scalar_mul(&mut self.beta_g2, contribution.beta); + } + + /// Verifies that `next` was computed properly from `last` with `proof` of the contribution. + #[inline] + pub fn verify( + last: Self, + next: Self, + challenge: C::Challenge, + proof: Proof, + ) -> Result<(Self, C::Response), VerificationError> + where + C: Configuration, + { + if next.tau_powers_g1[0] != C::g1_prime_subgroup_generator() { + return Err(VerificationError::PrimeSubgroupGeneratorG1); + } + if next.tau_powers_g2[0] != C::g2_prime_subgroup_generator() { + return Err(VerificationError::PrimeSubgroupGeneratorG2); + } + let response = C::response(&next, &challenge, &proof); + let KnowledgeProofCeritificate { tau, alpha, beta } = proof.verify(&challenge)?; + C::Pairing::same( + (last.tau_powers_g1[1], tau.0), + (next.tau_powers_g1[1], tau.1), + ) + .ok_or(VerificationError::TauMultiplication)?; + C::Pairing::same( + (last.alpha_tau_powers_g1[0], alpha.0), + (next.alpha_tau_powers_g1[0], alpha.1), + ) + .ok_or(VerificationError::AlphaMultiplication)?; + let ((last_beta_tau_powers_g1_0, _), (next_beta_tau_powers_g1_0, _)) = C::Pairing::same( + (last.beta_tau_powers_g1[0], beta.0), + (next.beta_tau_powers_g1[0], beta.1), + ) + .ok_or(VerificationError::BetaMultiplication)?; + C::Pairing::same( + (last_beta_tau_powers_g1_0, next.beta_g2), + (next_beta_tau_powers_g1_0, last.beta_g2), + ) + .ok_or(VerificationError::BetaMultiplication)?; + let (lhs, rhs) = power_pairs(&next.tau_powers_g2); + C::Pairing::same((next.tau_powers_g1[0], rhs), (next.tau_powers_g1[1], lhs)) + .ok_or(VerificationError::TauG1Powers)?; + let (lhs, rhs) = power_pairs(&next.tau_powers_g1); + let ((_, next_tau_powers_g2_1), (_, next_tau_powers_g2_0)) = + C::Pairing::same((lhs, next.tau_powers_g2[1]), (rhs, next.tau_powers_g2[0])) + .ok_or(VerificationError::TauG2Powers)?; + let (lhs, rhs) = power_pairs(&next.alpha_tau_powers_g1); + let ((_, next_tau_powers_g2_1), (_, next_tau_powers_g2_0)) = + C::Pairing::same((lhs, next_tau_powers_g2_1), (rhs, next_tau_powers_g2_0)) + .ok_or(VerificationError::AlphaG1Powers)?; + let (lhs, rhs) = power_pairs(&next.beta_tau_powers_g1); + C::Pairing::same((lhs, next_tau_powers_g2_1), (rhs, next_tau_powers_g2_0)) + .ok_or(VerificationError::BetaG1Powers)?; + Ok((next, response)) + } +} + impl CanonicalSerialize for Accumulator where C: Pairing + Size + Serializer + Serializer, @@ -276,16 +630,18 @@ where #[inline] fn serialized_size(&self) -> usize { - sum!(iter!(self.tau_powers_g1).map(C::compressed_size), usize) - + sum!(iter!(self.tau_powers_g2).map(C::compressed_size), usize) - + sum!( - iter!(self.alpha_tau_powers_g1).map(C::compressed_size), - usize - ) - + sum!( - iter!(self.beta_tau_powers_g1).map(C::compressed_size), - usize - ) + cfg_iter!(self.tau_powers_g1) + .map(C::compressed_size) + .sum::() + + cfg_iter!(self.tau_powers_g2) + .map(C::compressed_size) + .sum::() + + cfg_iter!(&self.alpha_tau_powers_g1) + .map(C::compressed_size) + .sum::() + + cfg_iter!(&self.beta_tau_powers_g1) + .map(C::compressed_size) + .sum::() + C::compressed_size(&self.beta_g2) } @@ -312,16 +668,18 @@ where #[inline] fn uncompressed_size(&self) -> usize { - sum!(iter!(self.tau_powers_g1).map(C::uncompressed_size), usize) - + sum!(iter!(self.tau_powers_g2).map(C::uncompressed_size), usize) - + sum!( - iter!(self.alpha_tau_powers_g1).map(C::uncompressed_size), - usize - ) - + sum!( - iter!(self.beta_tau_powers_g1).map(C::uncompressed_size), - usize - ) + cfg_iter!(self.tau_powers_g1) + .map(C::uncompressed_size) + .sum::() + + cfg_iter!(self.tau_powers_g2) + .map(C::uncompressed_size) + .sum::() + + cfg_iter!(&self.alpha_tau_powers_g1) + .map(C::uncompressed_size) + .sum::() + + cfg_iter!(&self.beta_tau_powers_g1) + .map(C::uncompressed_size) + .sum::() + C::uncompressed_size(&self.beta_g2) } } @@ -329,6 +687,8 @@ where impl CanonicalDeserialize for Accumulator where C: Deserializer + Deserializer + Pairing + Size, + >::Error: Send, + >::Error: Send, { #[inline] fn deserialize(mut reader: R) -> Result @@ -366,10 +726,18 @@ where R: Read, { let accumulator = Self::deserialize_unchecked(reader)?; - try_for_each!(iter!(&accumulator.tau_powers_g1), C::check).map_err(Into::into)?; - try_for_each!(iter!(&accumulator.tau_powers_g2), C::check).map_err(Into::into)?; - try_for_each!(iter!(&accumulator.alpha_tau_powers_g1), C::check).map_err(Into::into)?; - try_for_each!(iter!(&accumulator.beta_tau_powers_g1), C::check).map_err(Into::into)?; + cfg_iter!(accumulator.tau_powers_g1) + .try_for_each(C::check) + .map_err(Into::into)?; + cfg_iter!(accumulator.tau_powers_g2) + .try_for_each(C::check) + .map_err(Into::into)?; + cfg_iter!(accumulator.alpha_tau_powers_g1) + .try_for_each(C::check) + .map_err(Into::into)?; + cfg_iter!(accumulator.beta_tau_powers_g1) + .try_for_each(C::check) + .map_err(Into::into)?; C::check(&accumulator.beta_g2).map_err(Into::into)?; Ok(accumulator) } diff --git a/manta-trusted-setup/src/mpc.rs b/manta-trusted-setup/src/mpc.rs index 351e8a0cf..1a6b519c8 100644 --- a/manta-trusted-setup/src/mpc.rs +++ b/manta-trusted-setup/src/mpc.rs @@ -39,10 +39,10 @@ pub trait Contribute: Types { /// Comptues the next state from `state`, `challenge`, and `contribution`. fn contribute( &self, - state: &Self::State, + state: &mut Self::State, challenge: &Self::Challenge, contribution: &Self::Contribution, - ) -> (Self::State, Self::Response, Self::Proof); + ) -> (Self::Response, Self::Proof); } /// Verification @@ -62,19 +62,19 @@ pub trait Verify: Types { challenge: Self::Challenge, ) -> Self::Response; - /// Verifies the transformation from `last` to `next` using the `next_proof` and `next_response` - /// as evidence for the correct update of the state. This method returns the `next` state - /// and `next_response`. + /// Verifies the transformation from `last` to `next` using the `challenge` and `proof` as + /// evidence for the correct update of the state. This method returns the `next` state and + /// the next response. fn verify( &self, last: Self::State, next: Self::State, - next_proof: Self::Proof, - next_response: Self::Challenge, + challenge: Self::Challenge, + proof: Self::Proof, ) -> Result<(Self::State, Self::Response), Self::Error>; /// Verifies all contributions in `iter` chaining from `last` and `last_response` returning the - /// newest [`State`](Self::State) and [`Response`](Self::Response) if all the contributions in + /// newest [`State`](Types::State) and [`Response`](Types::Response) if all the contributions in /// the chain had valid transitions. #[inline] fn verify_all( @@ -90,7 +90,7 @@ pub trait Verify: Types { for item in iter { let (next, next_proof) = item.map_err(Into::into)?; let next_challenge = self.challenge(&next, &last_response); - (last, last_response) = self.verify(last, next, next_proof, next_challenge)?; + (last, last_response) = self.verify(last, next, next_challenge, next_proof)?; } Ok((last, last_response)) } diff --git a/manta-trusted-setup/src/util.rs b/manta-trusted-setup/src/util.rs index e5d0b0d97..ba59c14c7 100644 --- a/manta-trusted-setup/src/util.rs +++ b/manta-trusted-setup/src/util.rs @@ -16,8 +16,15 @@ //! Utilities +use ark_ec::{wnaf::WnafContext, AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ff::{BigInteger, PrimeField, UniformRand}; use ark_std::io; -use core::marker::PhantomData; +use core::{iter, marker::PhantomData}; +use manta_crypto::rand::OsRng; +use manta_util::{cfg_into_iter, cfg_iter, cfg_iter_mut, cfg_reduce}; + +#[cfg(feature = "rayon")] +use rayon::iter::{IndexedParallelIterator, ParallelIterator}; pub use ark_ff::{One, Zero}; pub use ark_serialize::{ @@ -28,7 +35,7 @@ pub use manta_crypto::rand::Sample; /// Distribution Type Extension pub trait HasDistribution { /// Distribution Type - type Distribution; + type Distribution: Default; } /// Custom Serialization Adapter @@ -217,3 +224,168 @@ where Ok(item) } } + +/// Multiplies `point` by `scalar` in-place. +#[inline] +pub fn scalar_mul(point: &mut G, scalar: G::ScalarField) +where + G: AffineCurve, +{ + *point = point.mul(scalar).into_affine(); +} + +/// Multiplies each element in `bases` by `scalar`. +#[inline] +pub fn batch_scalar_mul_affine(points: &mut [G], scalar: G::ScalarField) +where + G: AffineCurve, +{ + cfg_iter_mut!(points).for_each(|point| scalar_mul(point, scalar)) +} + +/// Converts each affine point in `points` into its projective form. +#[inline] +pub fn batch_into_projective(points: &[G]) -> Vec +where + G: AffineCurve, +{ + cfg_iter!(points).map(G::into_projective).collect() +} + +/// Returns the empirically-recommended window size for WNAF on the given `scalar`. +#[inline] +pub fn wnaf_empirical_recommended_window_size(scalar: &F) -> usize +where + F: BigInteger, +{ + let num_bits = scalar.num_bits() as usize; + if num_bits >= 130 { + 4 + } else if num_bits >= 34 { + 3 + } else { + 2 + } +} + +/// Returns a [`WnafContext`] with the empirically-recommended window size. See +/// [`wnaf_empirical_recommended_window_size`] for more. +#[inline] +pub fn recommended_wnaf(scalar: &F) -> WnafContext +where + F: PrimeField, +{ + WnafContext::new(wnaf_empirical_recommended_window_size(&scalar.into_repr())) +} + +/// Compresses `lhs` and `rhs` into a pair of curve points by random linear combination. The same +/// random linear combination is used for both `lhs` and `rhs`, allowing this pair to be used in a +/// consistent ratio test. +#[inline] +pub fn merge_pairs_projective(lhs: &[G], rhs: &[G]) -> (G, G) +where + G: ProjectiveCurve, +{ + assert_eq!(lhs.len(), rhs.len()); + let tmp = cfg_into_iter!(0..lhs.len()) + .map(|_| G::ScalarField::rand(&mut OsRng)) + .zip(lhs) + .zip(rhs) + .map(|((rho, lhs), rhs)| { + let wnaf = recommended_wnaf(&rho); + (wnaf.mul(*lhs, &rho), wnaf.mul(*rhs, &rho)) + }); + cfg_reduce!(tmp, || (G::zero(), G::zero()), |mut acc, next| { + acc.0 += next.0; + acc.1 += next.1; + acc + }) +} + +/// Compresses `lhs` and `rhs` into a pair of curve points by random linear combination. The same +/// random linear combination is used for both `lhs` and `rhs`, allowing this pair to be used in a +/// consistent ratio test. +#[inline] +pub fn merge_pairs_affine(lhs: &[G], rhs: &[G]) -> (G, G) +where + G: AffineCurve, +{ + assert_eq!(lhs.len(), rhs.len()); + let tmp = cfg_into_iter!(0..lhs.len()) + .map(|_| G::ScalarField::rand(&mut OsRng)) + .zip(lhs) + .zip(rhs) + .map(|((rho, lhs), rhs)| (lhs.mul(rho).into_affine(), rhs.mul(rho).into_affine())); + cfg_reduce!(tmp, || (Zero::zero(), Zero::zero()), |mut acc, next| { + acc.0 = acc.0 + next.0; + acc.1 = acc.1 + next.1; + acc + }) +} + +/// Computes a representative ratio pair for `points` by taking consecutive linear combinations +/// across `points`. This prepares `points` for a check that consecutive elements have the same +/// ratio, by computing a pairing ratio against a known pair that share the consecutive scaling +/// ratio. +#[inline] +pub fn power_pairs(points: &[G]) -> (G, G) +where + G: AffineCurve, +{ + let points_proj = batch_into_projective(points); + let (g1_proj, g2_proj) = + merge_pairs_projective(&points_proj[..(points_proj.len() - 1)], &points_proj[1..]); + (g1_proj.into_affine(), g2_proj.into_affine()) +} + +/// Pair from a [`PairingEngine`] +type Pair

= ( +

::G1Prepared, +

::G2Prepared, +); + +/// Pairing Engine Extension +pub trait PairingEngineExt: PairingEngine { + /// Evaluates the pairing function on `pair`. + #[inline] + fn eval(pair: &Pair) -> Self::Fqk { + Self::product_of_pairings(iter::once(pair)) + } + + /// Checks if `lhs` and `rhs` evaluate to the same point under the pairing function. + #[inline] + fn has_same(lhs: &Pair, rhs: &Pair) -> bool { + Self::eval(lhs) == Self::eval(rhs) + } + + /// Checks if `lhs` and `rhs` evaluate to the same point under the pairing function, returning + /// `Some` with prepared points if the pairing outcome is the same. This function checks if + /// there exists an `r` such that `(r * lhs.0 == rhs.0) && (r * lhs.1 == rhs.1)`. + #[inline] + fn same(lhs: (L1, L2), rhs: (R1, R2)) -> Option<(Pair, Pair)> + where + L1: Into, + L2: Into, + R1: Into, + R2: Into, + { + let lhs = (lhs.0.into(), lhs.1.into()); + let rhs = (rhs.0.into(), rhs.1.into()); + Self::has_same(&lhs, &rhs).then(|| (lhs, rhs)) + } + + /// Checks if the ratio of `(lhs.0, lhs.1)` from `G1` is the same as the ratio of + /// `(lhs.0, lhs.1)` from `G2`. + #[inline] + fn same_ratio(lhs: (L1, R1), rhs: (L2, R2)) -> bool + where + L1: Into, + L2: Into, + R1: Into, + R2: Into, + { + Self::has_same(&(lhs.0.into(), rhs.1.into()), &(lhs.1.into(), rhs.0.into())) + } +} + +impl PairingEngineExt for E where E: PairingEngine {} diff --git a/manta-util/src/macros.rs b/manta-util/src/macros.rs index 362374202..28e6373ee 100644 --- a/manta-util/src/macros.rs +++ b/manta-util/src/macros.rs @@ -18,7 +18,7 @@ /// Implements [`From`]`<$from>` for an enum `$to`, choosing the `$kind` variant. #[macro_export] -macro_rules! from_variant_impl { +macro_rules! from_variant { ($to:ty, $kind:ident, $from:ty) => { impl From<$from> for $to { #[inline] @@ -32,144 +32,115 @@ macro_rules! from_variant_impl { /// Calls the `into_iter` method on `$e` or the `into_par_iter` Rayon method if the `rayon` feature /// is enabled. #[macro_export] -macro_rules! into_iter { +macro_rules! cfg_into_iter { ($e:expr) => {{ #[cfg(feature = "rayon")] - let result = ::rayon::iter::IntoParallelIterator::into_par_iter($e); + { + use ::rayon::iter::IntoParallelIterator as _; + $e.into_par_iter() + } #[cfg(not(feature = "rayon"))] - let result = $e.into_iter(); - result + $e.into_iter() + }}; + ($e:expr, $min_len:expr) => {{ + #[cfg(feature = "rayon")] + { + use ::rayon::iter::IntoParallelIterator as _; + $e.into_par_iter().with_min_len($min_len) + } + #[cfg(not(feature = "rayon"))] + $e.into_iter() }}; } /// Calls the `iter` method on `$e` or the `par_iter` Rayon method if the `rayon` feature is /// enabled. #[macro_export] -macro_rules! iter { +macro_rules! cfg_iter { ($e:expr) => {{ #[cfg(feature = "rayon")] - let result = ::rayon::iter::IntoParallelRefIterator::par_iter($e); + { + use ::rayon::iter::IntoParallelRefIterator as _; + $e.par_iter() + } + #[cfg(not(feature = "rayon"))] + $e.iter() + }}; + ($e:expr, $min_len:expr) => {{ + #[cfg(feature = "rayon")] + { + use ::rayon::iter::IntoParallelRefIterator as _; + $e.par_iter().with_min_len($min_len) + } #[cfg(not(feature = "rayon"))] - let result = $e.iter(); - result + $e.iter() }}; } /// Calls the `iter_mut` method on `$e` or the `par_iter_mut` Rayon method if the `rayon` feature is /// enabled. #[macro_export] -macro_rules! iter_mut { +macro_rules! cfg_iter_mut { ($e:expr) => {{ #[cfg(feature = "rayon")] - let result = ::rayon::iter::IntoParallelRefMutIterator::par_iter_mut($e); + { + use ::rayon::iter::IntoParallelRefMutIterator as _; + $e.par_iter_mut() + } + #[cfg(not(feature = "rayon"))] + $e.iter_mut() + }}; + ($e:expr, $min_len:expr) => {{ + #[cfg(feature = "rayon")] + { + use ::rayon::iter::IntoParallelRefMutIterator as _; + $e.par_iter_mut().with_min_len($min_len) + } #[cfg(not(feature = "rayon"))] - let result = $e.iter_mut(); - result + $e.iter_mut() }}; } /// Calls the `chunks` method on `$e` or the `par_chunks` Rayon method if the `rayon` feature is /// enabled. #[macro_export] -macro_rules! chunks { +macro_rules! cfg_chunks { ($e:expr, $size:expr) => {{ #[cfg(feature = "rayon")] - let result = ::rayon::slice::ParallelSlice::par_chunks($e, $size); + { + use ::rayon::iter::ParallelIterator as _; + $e.par_chunks($size) + } #[cfg(not(feature = "rayon"))] - let result = $e.chunks($size); - result + $e.chunks($size) }}; } /// Calls the `chunks_mut` method on `$e` or the `par_chunks_mut` Rayon method if the `rayon` /// feature is enabled. #[macro_export] -macro_rules! chunks_mut { +macro_rules! cfg_chunks_mut { ($e:expr, $size:expr) => {{ #[cfg(feature = "rayon")] - let result = ::rayon::slice::ParallelSliceMut::par_chunks_mut($e, $size); + { + use ::rayon::iter::ParallelIterator as _; + $e.par_chunks_mut($size) + } #[cfg(not(feature = "rayon"))] - let result = $e.chunks_mut($size); - result + $e.chunks_mut($size) }}; } /// Calls the `fold` method on `$e` or the `reduce` Rayon method if the `rayon` feature is enabled. #[macro_export] -macro_rules! reduce { +macro_rules! cfg_reduce { ($e:expr, $default:expr, $op:expr) => {{ #[cfg(feature = "rayon")] - let result = ::rayon::iter::ParallelIterator::reduce($e, $default, $op); - #[cfg(not(feature = "rayon"))] - let result = $e.fold($default(), $op); - result - }}; -} - -/// Calls the `sum` method on `$e` or the `sum` Rayon method if the `rayon` feature is enabled. -#[macro_export] -macro_rules! sum { - ($e:expr) => {{ - $crate::sum!($e, _) - }}; - ($e:expr, $T:ty) => {{ - #[cfg(feature = "rayon")] - let result = ::rayon::iter::ParallelIterator::sum::<$T>($e); - #[cfg(not(feature = "rayon"))] - let result = $e.sum::<$T>(); - result - }}; -} - -/// Calls the `product` method on `$e` or the `product` Rayon method if the `rayon` feature is -/// enabled. -#[macro_export] -macro_rules! product { - ($e:expr) => {{ - $crate::product!($e, _) - }}; - ($e:expr, $T:ty) => {{ - #[cfg(feature = "rayon")] - let result = ::rayon::iter::ParallelIterator::product::<$T>($e); - #[cfg(not(feature = "rayon"))] - let result = $e.product::<$T>(); - result - }}; -} - -/// Calls the `min` method on `$e` or the `min` Rayon method if the `rayon` feature is enabled. -#[macro_export] -macro_rules! min { - ($e:expr) => {{ - #[cfg(feature = "rayon")] - let result = ::rayon::iter::ParallelIterator::min($e); - #[cfg(not(feature = "rayon"))] - let result = $e.min(); - result - }}; -} - -/// Calls the `max` method on `$e` or the `max` Rayon method if the `rayon` feature is enabled. -#[macro_export] -macro_rules! max { - ($e:expr) => {{ - #[cfg(feature = "rayon")] - let result = ::rayon::iter::ParallelIterator::max($e); - #[cfg(not(feature = "rayon"))] - let result = $e.max(); - result - }}; -} - -/// Calls the `try_for_each` method on `$e` or the `try_for_each` Rayon method if the `rayon` -/// feature is enabled. -#[macro_export] -macro_rules! try_for_each { - ($e:expr, $op:expr) => {{ - #[cfg(feature = "rayon")] - let result = ::rayon::iter::ParallelIterator::try_for_each($e, $op); + { + use ::rayon::iter::ParallelIterator as _; + $e.reduce($default, $op) + } #[cfg(not(feature = "rayon"))] - let result = $e.try_for_each($op); - result + $e.fold($default(), $op) }}; } From d7aa16464540204531d78aece8c8f806c5e97077 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Thu, 23 Jun 2022 02:39:07 -0400 Subject: [PATCH 05/17] fix: use consistent naming for from_variant Signed-off-by: Brandon H. Gomes --- manta-accounting/src/fs/mod.rs | 6 +++--- manta-pay/src/signer/client/websocket.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/manta-accounting/src/fs/mod.rs b/manta-accounting/src/fs/mod.rs index b0f22cfe6..0be74d0fc 100644 --- a/manta-accounting/src/fs/mod.rs +++ b/manta-accounting/src/fs/mod.rs @@ -365,7 +365,7 @@ pub mod cocoon { use super::{Block, OpenOptions}; use cocoon::{Error as CocoonError, MiniCocoon}; use core::fmt; - use manta_util::from_variant_impl; + use manta_util::from_variant; use std::{fs, io::Error as IoError, path::Path}; /// Cocoon Loading/Saving Error @@ -378,8 +378,8 @@ pub mod cocoon { Cocoon(CocoonError), } - from_variant_impl!(Error, IoError, IoError); - from_variant_impl!(Error, Cocoon, CocoonError); + from_variant!(Error, IoError, IoError); + from_variant!(Error, Cocoon, CocoonError); impl fmt::Display for Error { #[inline] diff --git a/manta-pay/src/signer/client/websocket.rs b/manta-pay/src/signer/client/websocket.rs index 3d44c4c91..0f2b21cc5 100644 --- a/manta-pay/src/signer/client/websocket.rs +++ b/manta-pay/src/signer/client/websocket.rs @@ -30,7 +30,7 @@ use core::marker::Unpin; use futures::{SinkExt, StreamExt}; use manta_accounting::wallet::{self, signer}; use manta_util::{ - from_variant_impl, + from_variant, future::LocalBoxFutureResult, serde::{de::DeserializeOwned, Deserialize, Serialize}, }; @@ -64,8 +64,8 @@ pub enum Error { WebSocket(WebSocketError), } -from_variant_impl!(Error, SerializationError, serde_json::Error); -from_variant_impl!(Error, WebSocket, WebSocketError); +from_variant!(Error, SerializationError, serde_json::Error); +from_variant!(Error, WebSocket, WebSocketError); /// Request #[derive(derivative::Derivative, Deserialize, Serialize)] From 4c68a30e431a7d61d8780df80b78696c24774c72 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Fri, 24 Jun 2022 16:10:05 -0400 Subject: [PATCH 06/17] fix: remove the response API just for challenge --- manta-trusted-setup/src/kzg.rs | 12 ++++----- manta-trusted-setup/src/lib.rs | 2 ++ manta-trusted-setup/src/mpc.rs | 45 +++++++++++++-------------------- manta-trusted-setup/src/util.rs | 1 + 4 files changed, 26 insertions(+), 34 deletions(-) diff --git a/manta-trusted-setup/src/kzg.rs b/manta-trusted-setup/src/kzg.rs index 7b06b10c3..e89a5831b 100644 --- a/manta-trusted-setup/src/kzg.rs +++ b/manta-trusted-setup/src/kzg.rs @@ -21,6 +21,7 @@ use crate::util::{ HasDistribution, NonZero, One, PairingEngineExt, Read, Sample, SerializationError, Serializer, Write, Zero, }; +use alloc::{vec, vec::Vec}; use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; use ark_ff::{PrimeField, UniformRand}; use core::{iter, ops::Mul}; @@ -548,12 +549,12 @@ where /// Verifies that `next` was computed properly from `last` with `proof` of the contribution. #[inline] - pub fn verify( + pub fn verify_transform( last: Self, next: Self, - challenge: C::Challenge, + next_challenge: C::Challenge, proof: Proof, - ) -> Result<(Self, C::Response), VerificationError> + ) -> Result where C: Configuration, { @@ -563,8 +564,7 @@ where if next.tau_powers_g2[0] != C::g2_prime_subgroup_generator() { return Err(VerificationError::PrimeSubgroupGeneratorG2); } - let response = C::response(&next, &challenge, &proof); - let KnowledgeProofCeritificate { tau, alpha, beta } = proof.verify(&challenge)?; + let KnowledgeProofCeritificate { tau, alpha, beta } = proof.verify(&next_challenge)?; C::Pairing::same( (last.tau_powers_g1[1], tau.0), (next.tau_powers_g1[1], tau.1), @@ -599,7 +599,7 @@ where let (lhs, rhs) = power_pairs(&next.beta_tau_powers_g1); C::Pairing::same((lhs, next_tau_powers_g2_1), (rhs, next_tau_powers_g2_0)) .ok_or(VerificationError::BetaG1Powers)?; - Ok((next, response)) + Ok(next) } } diff --git a/manta-trusted-setup/src/lib.rs b/manta-trusted-setup/src/lib.rs index 02fb3478b..3d0ce4523 100644 --- a/manta-trusted-setup/src/lib.rs +++ b/manta-trusted-setup/src/lib.rs @@ -21,6 +21,8 @@ #![forbid(rustdoc::broken_intra_doc_links)] #![forbid(missing_docs)] +extern crate alloc; + pub mod groth16; pub mod kzg; pub mod mpc; diff --git a/manta-trusted-setup/src/mpc.rs b/manta-trusted-setup/src/mpc.rs index 1a6b519c8..a58dd8527 100644 --- a/manta-trusted-setup/src/mpc.rs +++ b/manta-trusted-setup/src/mpc.rs @@ -21,14 +21,11 @@ pub trait Types { /// State Type type State; - /// Contribution Proof Type - type Proof; - /// Challenge Type type Challenge; - /// Response Type - type Response; + /// Contribution Proof Type + type Proof; } /// Contribution @@ -42,7 +39,7 @@ pub trait Contribute: Types { state: &mut Self::State, challenge: &Self::Challenge, contribution: &Self::Contribution, - ) -> (Self::Response, Self::Proof); + ) -> Self::Proof; } /// Verification @@ -50,48 +47,40 @@ pub trait Verify: Types { /// Error type Error; - /// Computes the challenge associated to `last` and `last_response` for the next player. - fn challenge(&self, last: &Self::State, last_response: &Self::Response) -> Self::Challenge; - - /// Computes the response from `next` and `next_proof` to the `challenge` presented by the - /// previous state. - fn response( - &self, - next: &Self::State, - next_proof: &Self::Proof, - challenge: Self::Challenge, - ) -> Self::Response; + /// Computes the challenge associated to `state` and `challenge` for the next player. + fn challenge(&self, state: &Self::State, challenge: &Self::Challenge) -> Self::Challenge; - /// Verifies the transformation from `last` to `next` using the `challenge` and `proof` as + /// Verifies the transformation from `last` to `next` using the `next_challenge` and `proof` as /// evidence for the correct update of the state. This method returns the `next` state and /// the next response. - fn verify( + fn verify_transform( &self, last: Self::State, next: Self::State, - challenge: Self::Challenge, + next_challenge: Self::Challenge, proof: Self::Proof, - ) -> Result<(Self::State, Self::Response), Self::Error>; + ) -> Result; /// Verifies all contributions in `iter` chaining from `last` and `last_response` returning the /// newest [`State`](Types::State) and [`Response`](Types::Response) if all the contributions in /// the chain had valid transitions. #[inline] - fn verify_all( + fn verify_transform_all( &self, - mut last: Self::State, - mut last_response: Self::Response, + mut state: Self::State, + mut challenge: Self::Challenge, iter: I, - ) -> Result<(Self::State, Self::Response), Self::Error> + ) -> Result<(Self::State, Self::Challenge), Self::Error> where E: Into, I: IntoIterator>, { for item in iter { let (next, next_proof) = item.map_err(Into::into)?; - let next_challenge = self.challenge(&next, &last_response); - (last, last_response) = self.verify(last, next, next_challenge, next_proof)?; + let next_challenge = self.challenge(&state, &challenge); + challenge = self.challenge(&next, &next_challenge); + state = self.verify_transform(state, next, next_challenge, next_proof)?; } - Ok((last, last_response)) + Ok((state, challenge)) } } diff --git a/manta-trusted-setup/src/util.rs b/manta-trusted-setup/src/util.rs index ba59c14c7..3482a2177 100644 --- a/manta-trusted-setup/src/util.rs +++ b/manta-trusted-setup/src/util.rs @@ -16,6 +16,7 @@ //! Utilities +use alloc::vec::Vec; use ark_ec::{wnaf::WnafContext, AffineCurve, PairingEngine, ProjectiveCurve}; use ark_ff::{BigInteger, PrimeField, UniformRand}; use ark_std::io; From dc4ac9fa2a99e8a839df01236cb37426106edaf8 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Fri, 24 Jun 2022 17:38:14 -0400 Subject: [PATCH 07/17] fix: use `Challenge` instead of `Response` --- manta-trusted-setup/src/mpc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manta-trusted-setup/src/mpc.rs b/manta-trusted-setup/src/mpc.rs index a58dd8527..d48916755 100644 --- a/manta-trusted-setup/src/mpc.rs +++ b/manta-trusted-setup/src/mpc.rs @@ -62,8 +62,8 @@ pub trait Verify: Types { ) -> Result; /// Verifies all contributions in `iter` chaining from `last` and `last_response` returning the - /// newest [`State`](Types::State) and [`Response`](Types::Response) if all the contributions in - /// the chain had valid transitions. + /// newest [`State`](Types::State) and [`Challenge`](Types::Challenge) if all the contributions + /// in the chain had valid transitions. #[inline] fn verify_transform_all( &self, From 4b96813ffcd51273e63546831bda9a586314371f Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Mon, 27 Jun 2022 14:46:46 -0400 Subject: [PATCH 08/17] fix: apply suggestions from code review Co-authored-by: Todd Norton <93260651+GhostOfGauss@users.noreply.github.com> Signed-off-by: Brandon H. Gomes --- manta-trusted-setup/src/kzg.rs | 6 +++--- manta-trusted-setup/src/mpc.rs | 2 +- manta-trusted-setup/src/util.rs | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manta-trusted-setup/src/kzg.rs b/manta-trusted-setup/src/kzg.rs index e89a5831b..1b65ecab7 100644 --- a/manta-trusted-setup/src/kzg.rs +++ b/manta-trusted-setup/src/kzg.rs @@ -295,7 +295,7 @@ where } /// Knowledge Proof Certificate -pub struct KnowledgeProofCeritificate +pub struct KnowledgeProofCertificate where C: Pairing, { @@ -336,11 +336,11 @@ where pub fn verify( self, challenge: &C::Challenge, - ) -> Result, KnowledgeError> + ) -> Result, KnowledgeError> where C: Configuration, { - Ok(KnowledgeProofCeritificate { + Ok(KnowledgeProofCertificate { tau: self .tau .verify(C::TAU_DOMAIN_TAG, challenge) diff --git a/manta-trusted-setup/src/mpc.rs b/manta-trusted-setup/src/mpc.rs index d48916755..71dbb2b59 100644 --- a/manta-trusted-setup/src/mpc.rs +++ b/manta-trusted-setup/src/mpc.rs @@ -33,7 +33,7 @@ pub trait Contribute: Types { /// Private Contribution Data type Contribution; - /// Comptues the next state from `state`, `challenge`, and `contribution`. + /// Computes the next state from `state`, `challenge`, and `contribution`. fn contribute( &self, state: &mut Self::State, diff --git a/manta-trusted-setup/src/util.rs b/manta-trusted-setup/src/util.rs index 3482a2177..202a0c686 100644 --- a/manta-trusted-setup/src/util.rs +++ b/manta-trusted-setup/src/util.rs @@ -324,10 +324,10 @@ where }) } -/// Computes a representative ratio pair for `points` by taking consecutive linear combinations -/// across `points`. This prepares `points` for a check that consecutive elements have the same -/// ratio, by computing a pairing ratio against a known pair that share the consecutive scaling -/// ratio. +/// Prepares a sequence of curve points for a check that subsequent terms differ by a constant ratio. +/// Concretely, this computes a random linear combination of all but the last point of the sequence +/// and the same linear combination of all but the first point of the sequence. The original check +/// reduces to checking that these linear combinations differ by the expected ratio. #[inline] pub fn power_pairs(points: &[G]) -> (G, G) where From 4aee7d9424aa155b8fe7d274283f4bcded8508a4 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Mon, 27 Jun 2022 14:56:28 -0400 Subject: [PATCH 09/17] fix: move `kzg` into `groth16` module For many proof system SRS ceremonies, we use a modified KZG scheme. Instead of having a global one, we wanted to have a Groth16-specific KZG ceremony, and in the future we can add a more universal interface for this commitment scheme SRS. Signed-off-by: Brandon H. Gomes --- manta-trusted-setup/src/{ => groth16}/kzg.rs | 6 ++--- .../src/{groth16.rs => groth16/mod.rs} | 2 ++ manta-trusted-setup/src/lib.rs | 1 - manta-trusted-setup/src/util.rs | 22 +++++++++---------- 4 files changed, 16 insertions(+), 15 deletions(-) rename manta-trusted-setup/src/{ => groth16}/kzg.rs (99%) rename manta-trusted-setup/src/{groth16.rs => groth16/mod.rs} (98%) diff --git a/manta-trusted-setup/src/kzg.rs b/manta-trusted-setup/src/groth16/kzg.rs similarity index 99% rename from manta-trusted-setup/src/kzg.rs rename to manta-trusted-setup/src/groth16/kzg.rs index 1b65ecab7..e1911232c 100644 --- a/manta-trusted-setup/src/kzg.rs +++ b/manta-trusted-setup/src/groth16/kzg.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with manta-rs. If not, see . -//! KZG Trusted Setup +//! KZG Trusted Setup for Groth16 use crate::util::{ power_pairs, scalar_mul, CanonicalDeserialize, CanonicalSerialize, Deserializer, @@ -202,7 +202,7 @@ where #[inline] fn sample(_: (), rng: &mut R) -> Self where - R: CryptoRng + RngCore + ?Sized, + R: RngCore + ?Sized, { Self { tau: C::Scalar::rand(rng), @@ -564,7 +564,7 @@ where if next.tau_powers_g2[0] != C::g2_prime_subgroup_generator() { return Err(VerificationError::PrimeSubgroupGeneratorG2); } - let KnowledgeProofCeritificate { tau, alpha, beta } = proof.verify(&next_challenge)?; + let KnowledgeProofCertificate { tau, alpha, beta } = proof.verify(&next_challenge)?; C::Pairing::same( (last.tau_powers_g1[1], tau.0), (next.tau_powers_g1[1], tau.1), diff --git a/manta-trusted-setup/src/groth16.rs b/manta-trusted-setup/src/groth16/mod.rs similarity index 98% rename from manta-trusted-setup/src/groth16.rs rename to manta-trusted-setup/src/groth16/mod.rs index 23a926e1f..d7ac2bd27 100644 --- a/manta-trusted-setup/src/groth16.rs +++ b/manta-trusted-setup/src/groth16/mod.rs @@ -15,3 +15,5 @@ // along with manta-rs. If not, see . //! Groth16 Trusted Setup + +pub mod kzg; diff --git a/manta-trusted-setup/src/lib.rs b/manta-trusted-setup/src/lib.rs index 3d0ce4523..84dabb22a 100644 --- a/manta-trusted-setup/src/lib.rs +++ b/manta-trusted-setup/src/lib.rs @@ -24,6 +24,5 @@ extern crate alloc; pub mod groth16; -pub mod kzg; pub mod mpc; pub mod util; diff --git a/manta-trusted-setup/src/util.rs b/manta-trusted-setup/src/util.rs index 202a0c686..020cab7c0 100644 --- a/manta-trusted-setup/src/util.rs +++ b/manta-trusted-setup/src/util.rs @@ -288,7 +288,7 @@ where G: ProjectiveCurve, { assert_eq!(lhs.len(), rhs.len()); - let tmp = cfg_into_iter!(0..lhs.len()) + let pairs = cfg_into_iter!(0..lhs.len()) .map(|_| G::ScalarField::rand(&mut OsRng)) .zip(lhs) .zip(rhs) @@ -296,7 +296,7 @@ where let wnaf = recommended_wnaf(&rho); (wnaf.mul(*lhs, &rho), wnaf.mul(*rhs, &rho)) }); - cfg_reduce!(tmp, || (G::zero(), G::zero()), |mut acc, next| { + cfg_reduce!(pairs, || (G::zero(), G::zero()), |mut acc, next| { acc.0 += next.0; acc.1 += next.1; acc @@ -307,26 +307,26 @@ where /// random linear combination is used for both `lhs` and `rhs`, allowing this pair to be used in a /// consistent ratio test. #[inline] -pub fn merge_pairs_affine(lhs: &[G], rhs: &[G]) -> (G, G) +pub fn merge_pairs_affine(lhs: &[G], rhs: &[G]) -> (G::Projective, G::Projective) where G: AffineCurve, { assert_eq!(lhs.len(), rhs.len()); - let tmp = cfg_into_iter!(0..lhs.len()) + let pairs = cfg_into_iter!(0..lhs.len()) .map(|_| G::ScalarField::rand(&mut OsRng)) .zip(lhs) .zip(rhs) - .map(|((rho, lhs), rhs)| (lhs.mul(rho).into_affine(), rhs.mul(rho).into_affine())); - cfg_reduce!(tmp, || (Zero::zero(), Zero::zero()), |mut acc, next| { - acc.0 = acc.0 + next.0; - acc.1 = acc.1 + next.1; + .map(|((rho, lhs), rhs)| (lhs.mul(rho), rhs.mul(rho))); + cfg_reduce!(pairs, || (Zero::zero(), Zero::zero()), |mut acc, next| { + acc.0 += next.0; + acc.1 += next.1; acc }) } -/// Prepares a sequence of curve points for a check that subsequent terms differ by a constant ratio. -/// Concretely, this computes a random linear combination of all but the last point of the sequence -/// and the same linear combination of all but the first point of the sequence. The original check +/// Prepares a sequence of curve points for a check that subsequent terms differ by a constant ratio. +/// Concretely, this computes a random linear combination of all but the last point of the sequence +/// and the same linear combination of all but the first point of the sequence. The original check /// reduces to checking that these linear combinations differ by the expected ratio. #[inline] pub fn power_pairs(points: &[G]) -> (G, G) From 9affaed1ce1ca6e5117739090441239bf00135cd Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Mon, 27 Jun 2022 15:06:29 -0400 Subject: [PATCH 10/17] chore: add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bce6b4de4..8b94ba649 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - [\#126](https://github.com/Manta-Network/manta-rs/pull/126) Add ECLAIR v0 scaffolding and deprecate old compiler patterns - [\#128](https://github.com/Manta-Network/manta-rs/pull/128) Add more parameter loading utilities - [\#130](https://github.com/Manta-Network/manta-rs/pull/130) Add the sage script and the hardcoded tests for the security of mds matrix +- [\#131](https://github.com/Manta-Network/manta-rs/pull/131) Add abstract Phase 1 for Groth16 trusted setup ### Changed - [\#132](https://github.com/Manta-Network/manta-rs/pull/132) Simplify algebra APIs and removing ECC-specific design From 5e1e13d9f64c69af735984ce56abd703e77f5a3f Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Sun, 3 Jul 2022 19:34:09 -0400 Subject: [PATCH 11/17] chore: update dependencies --- manta-trusted-setup/Cargo.toml | 1 + manta-util/Cargo.toml | 2 +- manta-util/src/codec.rs | 2 +- manta-workspace-hack/Cargo.toml | 8 ++++---- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/manta-trusted-setup/Cargo.toml b/manta-trusted-setup/Cargo.toml index 413a858bd..12c23fb5e 100644 --- a/manta-trusted-setup/Cargo.toml +++ b/manta-trusted-setup/Cargo.toml @@ -44,3 +44,4 @@ derivative = { version = "2.2.0", default-features = false, features = ["use_cor manta-crypto = { path = "../manta-crypto", default-features = false, features = ["getrandom"] } manta-util = { path = "../manta-util", default-features = false, features = ["alloc"] } rayon = { version = "1.5.3", optional = true, default-features = false } +manta-workspace-hack = { version = "0.1", path = "../manta-workspace-hack" } diff --git a/manta-util/Cargo.toml b/manta-util/Cargo.toml index b95150fc3..efe14e169 100644 --- a/manta-util/Cargo.toml +++ b/manta-util/Cargo.toml @@ -40,6 +40,6 @@ std = ["alloc"] [dependencies] crossbeam-channel = { version = "0.5.4", optional = true, default-features = false } rayon = { version = "1.5.3", optional = true, default-features = false } -serde = { version = "1.0.137", optional = true, default-features = false, features = ["derive"] } +serde = { version = "1.0.138", optional = true, default-features = false, features = ["derive"] } serde_with = { version = "1.14.0", optional = true, default-features = false, features = ["macros"] } manta-workspace-hack = { version = "0.1.0", path = "../manta-workspace-hack" } diff --git a/manta-util/src/codec.rs b/manta-util/src/codec.rs index 83d896e26..df0122322 100644 --- a/manta-util/src/codec.rs +++ b/manta-util/src/codec.rs @@ -433,7 +433,7 @@ impl Write for Vec { fn write(&mut self, input: &mut &[u8]) -> Result { let len = input.len(); self.reserve(len); - self.extend_from_slice(*input); + self.extend_from_slice(input); Ok(len) } diff --git a/manta-workspace-hack/Cargo.toml b/manta-workspace-hack/Cargo.toml index f195722d6..31d5830d8 100644 --- a/manta-workspace-hack/Cargo.toml +++ b/manta-workspace-hack/Cargo.toml @@ -19,7 +19,7 @@ anyhow = { version = "1.0.58", features = ["std"] } bitflags = { version = "1.3.2" } blake3 = { version = "1.3.1", default-features = false, features = ["digest", "std"] } block-buffer = { version = "0.9.0", default-features = false, features = ["block-padding"] } -crypto-common = { version = "0.1.3", default-features = false, features = ["std"] } +crypto-common = { version = "0.1.4", default-features = false, features = ["std"] } digest-93f6ce9d446188ac = { package = "digest", version = "0.10.3", features = ["alloc", "block-buffer", "core-api", "mac", "std", "subtle"] } digest-274715c4dabd11b0 = { package = "digest", version = "0.9.0", default-features = false, features = ["alloc", "std"] } futures = { version = "0.3.21", features = ["alloc", "async-await", "executor", "futures-executor", "std"] } @@ -40,7 +40,7 @@ ppv-lite86 = { version = "0.2.16", default-features = false, features = ["simd", rand = { version = "0.8.5", features = ["alloc", "getrandom", "libc", "rand_chacha", "std", "std_rng"] } rand_chacha = { version = "0.3.1", default-features = false, features = ["std"] } rand_core = { version = "0.6.3", default-features = false, features = ["alloc", "getrandom", "std"] } -serde = { version = "1.0.137", features = ["alloc", "derive", "serde_derive", "std"] } +serde = { version = "1.0.138", features = ["alloc", "derive", "serde_derive", "std"] } serde_json = { version = "1.0.82", features = ["alloc", "std"] } sha2 = { version = "0.9.9", features = ["std"] } standback = { version = "0.2.17", default-features = false, features = ["std"] } @@ -53,12 +53,12 @@ zeroize = { version = "1.4.3", default-features = false, features = ["alloc", "z anyhow = { version = "1.0.58", features = ["std"] } blake3 = { version = "1.3.1", default-features = false, features = ["digest", "std"] } cc = { version = "1.0.73", default-features = false, features = ["jobserver", "parallel"] } -crypto-common = { version = "0.1.3", default-features = false, features = ["std"] } +crypto-common = { version = "0.1.4", default-features = false, features = ["std"] } digest-93f6ce9d446188ac = { package = "digest", version = "0.10.3", features = ["alloc", "block-buffer", "core-api", "mac", "std", "subtle"] } generic-array = { version = "0.14.5", default-features = false, features = ["more_lengths"] } log = { version = "0.4.17", default-features = false, features = ["kv_unstable", "kv_unstable_std", "std", "value-bag"] } num-traits = { version = "0.2.15", features = ["i128", "libm", "std"] } -serde = { version = "1.0.137", features = ["alloc", "derive", "serde_derive", "std"] } +serde = { version = "1.0.138", features = ["alloc", "derive", "serde_derive", "std"] } standback = { version = "0.2.17", default-features = false, features = ["std"] } subtle = { version = "2.4.1", default-features = false, features = ["i128"] } syn = { version = "1.0.98", features = ["clone-impls", "derive", "extra-traits", "fold", "full", "parsing", "printing", "proc-macro", "quote", "visit", "visit-mut"] } From c880059f3a4e680e2c43a27a7dac890f43da76e0 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Wed, 6 Jul 2022 18:36:01 -0400 Subject: [PATCH 12/17] fix: apply suggestions from code review Co-authored-by: Todd Norton <93260651+GhostOfGauss@users.noreply.github.com> Signed-off-by: Brandon H. Gomes --- manta-trusted-setup/src/mpc.rs | 2 +- manta-trusted-setup/src/util.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/manta-trusted-setup/src/mpc.rs b/manta-trusted-setup/src/mpc.rs index 71dbb2b59..d73e23dc9 100644 --- a/manta-trusted-setup/src/mpc.rs +++ b/manta-trusted-setup/src/mpc.rs @@ -61,7 +61,7 @@ pub trait Verify: Types { proof: Self::Proof, ) -> Result; - /// Verifies all contributions in `iter` chaining from `last` and `last_response` returning the + /// Verifies all contributions in `iter` chaining from an initial `state` and `challenge` returning the /// newest [`State`](Types::State) and [`Challenge`](Types::Challenge) if all the contributions /// in the chain had valid transitions. #[inline] diff --git a/manta-trusted-setup/src/util.rs b/manta-trusted-setup/src/util.rs index 020cab7c0..6168f0238 100644 --- a/manta-trusted-setup/src/util.rs +++ b/manta-trusted-setup/src/util.rs @@ -361,7 +361,7 @@ pub trait PairingEngineExt: PairingEngine { /// Checks if `lhs` and `rhs` evaluate to the same point under the pairing function, returning /// `Some` with prepared points if the pairing outcome is the same. This function checks if - /// there exists an `r` such that `(r * lhs.0 == rhs.0) && (r * lhs.1 == rhs.1)`. + /// there exists an `r` such that `(r * lhs.0 == rhs.0) && (lhs.1 == r * rhs.1)`. #[inline] fn same(lhs: (L1, L2), rhs: (R1, R2)) -> Option<(Pair, Pair)> where From 6ed4ab799908cf8369b1dc6692c037d2c17f984b Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Wed, 6 Jul 2022 18:46:51 -0400 Subject: [PATCH 13/17] fix: use minimal trait bounds for scalars and groups --- manta-trusted-setup/src/groth16/kzg.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/manta-trusted-setup/src/groth16/kzg.rs b/manta-trusted-setup/src/groth16/kzg.rs index e1911232c..711f484b5 100644 --- a/manta-trusted-setup/src/groth16/kzg.rs +++ b/manta-trusted-setup/src/groth16/kzg.rs @@ -43,13 +43,12 @@ pub trait Size { /// Pairing Configuration pub trait Pairing: HasDistribution { /// Underlying Scalar Field - type Scalar: PrimeField + One; + type Scalar: PrimeField; /// First Group of the Pairing type G1: AffineCurve + Into - + Sample - + Zero; + + Sample; /// First Group Pairing-Prepared Point type G1Prepared; @@ -57,8 +56,7 @@ pub trait Pairing: HasDistribution { /// Second Group of the Pairing type G2: AffineCurve + Into - + Sample - + Zero; + + Sample; /// Second Group Pairing-Prepared Point type G2Prepared; From 47b343a6305095b099e7c776b03c6fd50c92716e Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Thu, 7 Jul 2022 22:50:50 -0400 Subject: [PATCH 14/17] chore: update zeroize dependency --- manta-trusted-setup/Cargo.toml | 2 +- workspace-hack/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/manta-trusted-setup/Cargo.toml b/manta-trusted-setup/Cargo.toml index 12c23fb5e..1444eb946 100644 --- a/manta-trusted-setup/Cargo.toml +++ b/manta-trusted-setup/Cargo.toml @@ -44,4 +44,4 @@ derivative = { version = "2.2.0", default-features = false, features = ["use_cor manta-crypto = { path = "../manta-crypto", default-features = false, features = ["getrandom"] } manta-util = { path = "../manta-util", default-features = false, features = ["alloc"] } rayon = { version = "1.5.3", optional = true, default-features = false } -manta-workspace-hack = { version = "0.1", path = "../manta-workspace-hack" } +workspace-hack = { version = "0.1.0", path = "../workspace-hack" } diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index 403d9c31e..c2549c617 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -47,7 +47,7 @@ standback = { version = "0.2.17", default-features = false, features = ["std"] } subtle = { version = "2.4.1", default-features = false, features = ["i128"] } url = { version = "2.2.2", default-features = false, features = ["serde"] } web-sys = { version = "0.3.58", default-features = false, features = ["BinaryType", "Blob", "CloseEvent", "DomException", "Event", "EventTarget", "MessageEvent", "WebSocket", "console"] } -zeroize = { version = "1.4.3", default-features = false, features = ["alloc", "zeroize_derive"] } +zeroize = { version = "1.5.6", default-features = false, features = ["alloc", "zeroize_derive"] } [build-dependencies] anyhow = { version = "1.0.58", features = ["std"] } From 4596d31e2fc4c99491e90cec29197cd680bf5453 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Thu, 7 Jul 2022 22:58:48 -0400 Subject: [PATCH 15/17] chore: use correct formatting for `Cargo.toml` --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index eccf46242..70582fc61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,3 @@ [workspace] resolver = "2" -members = ["manta-*", "workspace-hack"] \ No newline at end of file +members = ["manta-*", "workspace-hack"] From c499f2ab54ded60ad92bfc2c20c3ecbcebf7cb82 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Fri, 8 Jul 2022 13:58:13 -0400 Subject: [PATCH 16/17] Update manta-trusted-setup/Cargo.toml Co-authored-by: Boyuan Feng Signed-off-by: Brandon H. Gomes --- manta-trusted-setup/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manta-trusted-setup/Cargo.toml b/manta-trusted-setup/Cargo.toml index 1444eb946..b8cea473b 100644 --- a/manta-trusted-setup/Cargo.toml +++ b/manta-trusted-setup/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "manta-trusted-setup" -version = "0.5.1" +version = "0.5.3" edition = "2021" authors = ["Manta Network "] readme = "README.md" From 7a64cb52c45d53cd04000e27303a0f602a1f5812 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Mon, 11 Jul 2022 23:02:05 -0400 Subject: [PATCH 17/17] fix: add `take` to powers of tau iterator to prevent infinite allocation Signed-off-by: Brandon H. Gomes --- manta-accounting/Cargo.toml | 2 +- manta-pay/Cargo.toml | 2 +- manta-trusted-setup/src/groth16/kzg.rs | 5 +++++ manta-util/Cargo.toml | 2 +- workspace-hack/Cargo.toml | 8 ++++---- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/manta-accounting/Cargo.toml b/manta-accounting/Cargo.toml index 0e5a85de0..8eab33ddd 100644 --- a/manta-accounting/Cargo.toml +++ b/manta-accounting/Cargo.toml @@ -54,7 +54,7 @@ test = [ [dependencies] bitflags = { version = "1.3.2", optional = true, default-features = false } -cocoon = { version = "0.3.0", optional = true, default-features = false } +cocoon = { version = "0.3.1", optional = true, default-features = false } derivative = { version = "2.2.0", default-features = false, features = ["use_core"] } derive_more = { version = "0.99.16", default-features = false, features = ["add", "add_assign", "display", "from", "sum"] } futures = { version = "0.3.21", optional = true, default-features = false, features = ["alloc"] } diff --git a/manta-pay/Cargo.toml b/manta-pay/Cargo.toml index 4bafc6ea9..5869f192e 100644 --- a/manta-pay/Cargo.toml +++ b/manta-pay/Cargo.toml @@ -117,7 +117,7 @@ ark-std = { version = "0.3.0", optional = true, default-features = false } bip32 = { version = "0.3.0", optional = true, default-features = false, features = ["bip39", "secp256k1"] } blake2 = { version = "0.10.4", default-features = false } bs58 = { version = "0.4.0", optional = true, default-features = false, features = ["alloc"] } -clap = { version = "3.2.8", optional = true, default-features = false, features = ["color", "derive", "std", "suggestions", "unicode", "wrap_help"] } +clap = { version = "3.2.10", optional = true, default-features = false, features = ["color", "derive", "std", "suggestions", "unicode", "wrap_help"] } derivative = { version = "2.2.0", default-features = false, features = ["use_core"] } futures = { version = "0.3.21", optional = true, default-features = false } indexmap = { version = "1.8.2", optional = true, default-features = false } diff --git a/manta-trusted-setup/src/groth16/kzg.rs b/manta-trusted-setup/src/groth16/kzg.rs index 711f484b5..22e22b72e 100644 --- a/manta-trusted-setup/src/groth16/kzg.rs +++ b/manta-trusted-setup/src/groth16/kzg.rs @@ -34,9 +34,13 @@ use rayon::iter::{IndexedParallelIterator, ParallelIterator}; /// KZG Trusted Setup Size pub trait Size { /// Number of G1 Powers to Produce + /// + /// The number of G1 powers must be greater than or equal to the number of G2 powers. const G1_POWERS: usize; /// Number of G2 Powers to Produce + /// + /// The number of G2 powers must be smaller than or equal to the number of G1 powers. const G2_POWERS: usize; } @@ -523,6 +527,7 @@ where pub fn update(&mut self, contribution: &Contribution) { let mut tau_powers = iter::successors(Some(C::Scalar::one()), |x| Some(x.mul(contribution.tau))) + .take(C::G1_POWERS) .collect::>(); let remaining_tau_powers = tau_powers.split_off(C::G2_POWERS); cfg_iter_mut!(self.tau_powers_g1) diff --git a/manta-util/Cargo.toml b/manta-util/Cargo.toml index 12e8ee7b9..1e0df1227 100644 --- a/manta-util/Cargo.toml +++ b/manta-util/Cargo.toml @@ -40,6 +40,6 @@ std = ["alloc"] [dependencies] crossbeam-channel = { version = "0.5.4", optional = true, default-features = false } rayon = { version = "1.5.3", optional = true, default-features = false } -serde = { version = "1.0.138", optional = true, default-features = false, features = ["derive"] } +serde = { version = "1.0.139", optional = true, default-features = false, features = ["derive"] } serde_with = { version = "1.14.0", optional = true, default-features = false, features = ["macros"] } workspace-hack = { version = "0.1.0", path = "../workspace-hack" } diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index c2549c617..b7d9e3f2e 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -19,7 +19,7 @@ anyhow = { version = "1.0.58", features = ["std"] } bitflags = { version = "1.3.2" } blake3 = { version = "1.3.1", default-features = false, features = ["digest", "std"] } block-buffer = { version = "0.9.0", default-features = false, features = ["block-padding"] } -crypto-common = { version = "0.1.4", default-features = false, features = ["std"] } +crypto-common = { version = "0.1.5", default-features = false, features = ["std"] } digest-93f6ce9d446188ac = { package = "digest", version = "0.10.3", features = ["alloc", "block-buffer", "core-api", "mac", "std", "subtle"] } digest-274715c4dabd11b0 = { package = "digest", version = "0.9.0", default-features = false, features = ["alloc", "std"] } futures = { version = "0.3.21", features = ["alloc", "async-await", "executor", "futures-executor", "std"] } @@ -40,7 +40,7 @@ ppv-lite86 = { version = "0.2.16", default-features = false, features = ["simd", rand = { version = "0.8.5", features = ["alloc", "getrandom", "libc", "rand_chacha", "std", "std_rng"] } rand_chacha = { version = "0.3.1", default-features = false, features = ["std"] } rand_core = { version = "0.6.3", default-features = false, features = ["alloc", "getrandom", "std"] } -serde = { version = "1.0.138", features = ["alloc", "derive", "serde_derive", "std"] } +serde = { version = "1.0.139", features = ["alloc", "derive", "serde_derive", "std"] } serde_json = { version = "1.0.82", features = ["alloc", "std"] } sha2 = { version = "0.9.9", features = ["std"] } standback = { version = "0.2.17", default-features = false, features = ["std"] } @@ -53,12 +53,12 @@ zeroize = { version = "1.5.6", default-features = false, features = ["alloc", "z anyhow = { version = "1.0.58", features = ["std"] } blake3 = { version = "1.3.1", default-features = false, features = ["digest", "std"] } cc = { version = "1.0.73", default-features = false, features = ["jobserver", "parallel"] } -crypto-common = { version = "0.1.4", default-features = false, features = ["std"] } +crypto-common = { version = "0.1.5", default-features = false, features = ["std"] } digest-93f6ce9d446188ac = { package = "digest", version = "0.10.3", features = ["alloc", "block-buffer", "core-api", "mac", "std", "subtle"] } generic-array = { version = "0.14.5", default-features = false, features = ["more_lengths"] } log = { version = "0.4.17", default-features = false, features = ["kv_unstable", "kv_unstable_std", "std", "value-bag"] } num-traits = { version = "0.2.15", features = ["i128", "libm", "std"] } -serde = { version = "1.0.138", features = ["alloc", "derive", "serde_derive", "std"] } +serde = { version = "1.0.139", features = ["alloc", "derive", "serde_derive", "std"] } standback = { version = "0.2.17", default-features = false, features = ["std"] } subtle = { version = "2.4.1", default-features = false, features = ["i128"] } syn = { version = "1.0.98", features = ["clone-impls", "derive", "extra-traits", "fold", "full", "parsing", "printing", "proc-macro", "quote", "visit", "visit-mut"] }