From d41b8e88306c1b07829f8fe0f2fcb89643ab64e1 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Mon, 18 Jul 2022 17:27:09 -0400 Subject: [PATCH 1/7] feat: upgrade manta-crypto abstractions for new circuits --- manta-crypto/src/accumulator.rs | 216 +++++++++++++----- manta-crypto/src/algebra.rs | 4 +- manta-crypto/src/constraint.rs | 5 +- manta-crypto/src/eclair/alloc.rs | 23 +- manta-crypto/src/eclair/bool.rs | 66 +----- manta-crypto/src/eclair/cmp.rs | 30 ++- manta-crypto/src/eclair/mod.rs | 13 +- manta-crypto/src/eclair/num.rs | 18 ++ manta-crypto/src/encryption/convert/key.rs | 2 +- manta-crypto/src/encryption/convert/mod.rs | 2 +- .../src/encryption/convert/plaintext.rs | 4 +- manta-crypto/src/encryption/hybrid.rs | 104 ++++++++- manta-crypto/src/encryption/mod.rs | 144 +++++++++++- manta-crypto/src/key.rs | 2 +- manta-crypto/src/merkle_tree/tree.rs | 26 ++- manta-util/src/num.rs | 18 ++ manta-util/src/vec.rs | 18 ++ 17 files changed, 531 insertions(+), 164 deletions(-) diff --git a/manta-crypto/src/accumulator.rs b/manta-crypto/src/accumulator.rs index 97d66cc70..324177eb7 100644 --- a/manta-crypto/src/accumulator.rs +++ b/manta-crypto/src/accumulator.rs @@ -16,8 +16,11 @@ //! Dynamic Cryptographic Accumulators -/// Accumulator Membership Model -pub trait Model { +use crate::constraint::{Allocate, Allocator, Constant, Derived, Variable}; +use core::marker::PhantomData; + +/// Accumulator Membership Model Types +pub trait Types { /// Item Type type Item: ?Sized; @@ -26,7 +29,10 @@ pub trait Model { /// Output Type type Output; +} +/// Accumulator Membership Model +pub trait Model: Types { /// Verification Type /// /// Typically this is either [`bool`], a [`Result`] type, or a circuit boolean variable. @@ -43,6 +49,16 @@ pub trait Model { ) -> Self::Verification; } +/// Accumulator Item Hash Function +pub trait ItemHashFunction { + /// Item Type + type Item; + + /// Converts `value` into an [`Item`](Self::Item) that is compatible with the relevant + /// accumulator. + fn item_hash(&self, value: &T, compiler: &mut COM) -> Self::Item; +} + /// Accumulator Membership Model Validity Assertion /// /// For situations where we just want to assert validity of the membership proof, we can use this @@ -64,8 +80,11 @@ pub trait AssertValidVerification: Model { ); } +/// Accumulator Witness Type +pub type Witness = <::Model as Types>::Witness; + /// Accumulator Output Type -pub type Output = <::Model as Model>::Output; +pub type Output = <::Model as Types>::Output; /// Accumulator pub trait Accumulator { @@ -193,6 +212,102 @@ pub trait OptimizedAccumulator: Accumulator { } } +/// Item Hash Accumulator Model +pub struct ItemHashAccumulatorModel +where + H: ItemHashFunction, + A: Accumulator, +{ + /// Item Hash Function + item_hash_function: H, + + /// Accumulator + accumulator: A, + + /// Type Parameter Marker + __: PhantomData, +} + +impl Types for ItemHashAccumulatorModel +where + H: ItemHashFunction, + A: Accumulator, +{ + type Item = T; + type Witness = Witness; + type Output = Output; +} + +impl Model for ItemHashAccumulatorModel +where + H: ItemHashFunction, + A: Accumulator, +{ + type Verification = ::Verification; + + #[inline] + fn verify( + &self, + item: &Self::Item, + witness: &Self::Witness, + output: &Self::Output, + compiler: &mut (), + ) -> Self::Verification { + self.accumulator.model().verify( + &self.item_hash_function.item_hash(item, compiler), + witness, + output, + compiler, + ) + } +} + +/// Item Hash Accumulator +pub struct ItemHashAccumulator +where + H: ItemHashFunction, + A: Accumulator, +{ + /// Item Hash Accumulator Model + model: ItemHashAccumulatorModel, +} + +impl Accumulator for ItemHashAccumulator +where + H: ItemHashFunction, + A: Accumulator, +{ + type Item = T; + type Model = ItemHashAccumulatorModel; + + #[inline] + fn model(&self) -> &Self::Model { + &self.model + } + + #[inline] + fn insert(&mut self, item: &Self::Item) -> bool { + self.model + .accumulator + .insert(&self.model.item_hash_function.item_hash(item, &mut ())) + } + + #[inline] + fn prove(&self, item: &Self::Item) -> Option> { + self.model + .accumulator + .prove(&self.model.item_hash_function.item_hash(item, &mut ())) + .map(MembershipProof::into) + } + + #[inline] + fn contains(&self, item: &Self::Item) -> bool { + self.model + .accumulator + .contains(&self.model.item_hash_function.item_hash(item, &mut ())) + } +} + /// Accumulator Membership Proof pub struct MembershipProof where @@ -203,6 +318,9 @@ where /// Accumulator Output output: M::Output, + + /// Type Parameter Marker + __: PhantomData, } impl MembershipProof @@ -212,10 +330,14 @@ where /// Builds a new [`MembershipProof`] from `witness` and `output`. #[inline] pub fn new(witness: M::Witness, output: M::Output) -> Self { - Self { witness, output } + Self { + witness, + output, + __: PhantomData, + } } - /// Returns the accumulated output part of `self`, dropping the [`M::Witness`](Model::Witness). + /// Returns the accumulated output part of `self`, dropping the [`M::Witness`](Types::Witness). #[inline] pub fn into_output(self) -> M::Output { self.output @@ -241,71 +363,39 @@ where { model.assert_valid(item, &self.witness, &self.output, compiler) } -} - -/// Constraint System Gadgets -pub mod constraint { - use super::*; - use crate::constraint::{Allocate, Allocator, Constant, Derived, Variable}; - use core::marker::PhantomData; - - /// Membership Proof Allocation Mode Entry - #[derive(derivative::Derivative)] - #[derivative(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] - pub struct MembershipProofModeEntry { - /// Secret Witness Allocation Mode - pub witness: WitnessMode, - - /// Accumulated Value Allocation Mode - pub output: OutputMode, - } - - impl MembershipProofModeEntry { - /// Builds a new [`MembershipProofModeEntry`] from a witness` mode and an `output` mode. - #[inline] - pub fn new(witness: WitnessMode, output: OutputMode) -> Self { - Self { witness, output } - } - } - impl From for MembershipProofModeEntry + /// + #[inline] + pub fn into(self) -> MembershipProof where - WitnessMode: From, - OutputMode: From, + N: Model + ?Sized, + M::Witness: Into, + M::Output: Into, { - #[inline] - fn from(d: Derived) -> Self { - Self::new(d.into(), d.into()) - } + MembershipProof::new(self.witness.into(), self.output.into()) } +} - /// Membership Proof Allocation Mode - #[derive(derivative::Derivative)] - #[derivative(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] - pub struct MembershipProofMode(PhantomData<(WitnessMode, OutputMode)>); +impl Variable, COM> for MembershipProof +where + M: Model + Constant, + M::Type: Model, + M::Witness: Variable::Witness>, + M::Output: Variable::Output>, +{ + type Type = MembershipProof; - impl - Variable, COM> for MembershipProof - where - M: Model + Constant, - M::Type: Model, - M::Witness: Variable::Witness>, - M::Output: Variable::Output>, - { - type Type = MembershipProof; - - #[inline] - fn new_known(this: &Self::Type, compiler: &mut COM) -> Self { - Self::new( - this.witness.as_known(compiler), - this.output.as_known(compiler), - ) - } + #[inline] + fn new_unknown(compiler: &mut COM) -> Self { + Self::new(compiler.allocate_unknown(), compiler.allocate_unknown()) + } - #[inline] - fn new_unknown(compiler: &mut COM) -> Self { - Self::new(compiler.allocate_unknown(), compiler.allocate_unknown()) - } + #[inline] + fn new_known(this: &Self::Type, compiler: &mut COM) -> Self { + Self::new( + this.witness.as_known(compiler), + this.output.as_known(compiler), + ) } } diff --git a/manta-crypto/src/algebra.rs b/manta-crypto/src/algebra.rs index 62549920f..f661f4aa5 100644 --- a/manta-crypto/src/algebra.rs +++ b/manta-crypto/src/algebra.rs @@ -138,7 +138,7 @@ where where R: Read, { - Ok(Self::new(G::decode(&mut reader)?)) + Ok(Self::new(Decode::decode(&mut reader)?)) } } @@ -165,7 +165,7 @@ where where R: RngCore + ?Sized, { - Self::new(G::sample(distribution, rng)) + Self::new(Sample::sample(distribution, rng)) } } diff --git a/manta-crypto/src/constraint.rs b/manta-crypto/src/constraint.rs index ee14f5196..7d60318e1 100644 --- a/manta-crypto/src/constraint.rs +++ b/manta-crypto/src/constraint.rs @@ -31,8 +31,9 @@ pub use crate::eclair::{ }, bool::{Assert, AssertEq, Bool, ConditionalSelect, ConditionalSwap}, cmp::{Eq, PartialEq}, - ops::{Add, Not, Sub}, - Has, Native, + num::Zero, + ops::{Add, BitAnd, BitOr, Not, Sub}, + Has, Native, NonNative, }; /// Proof System diff --git a/manta-crypto/src/eclair/alloc.rs b/manta-crypto/src/eclair/alloc.rs index eab8bf848..8e6901e69 100644 --- a/manta-crypto/src/eclair/alloc.rs +++ b/manta-crypto/src/eclair/alloc.rs @@ -27,6 +27,8 @@ //! abstractions inside of compilers, like heap allocation. Allocation only refers to lifting //! constants and variables from one compiler to another. +// TODO: How can we have objects that have both `Constant` and `Variable` parts? + use core::marker::PhantomData; /// Constant Type Alias @@ -253,12 +255,20 @@ impl Allocator for COM where COM: ?Sized {} /// [`Secret`]: mode::Secret /// [`ProofSystem`]: crate::eclair::execution::ProofSystem pub mod mode { + use super::*; + /// Generic Derived Allocation Mode /// /// Whenever a variable has internal structure that employs different allocation modes for /// different internal variables, it should be marked with this allocation mode. + /// + /// # Optional Type Annotations + /// + /// To ensure that all types are constrained when implementing [`Variable`], we can provide + /// optional types to [`Derived`]. See [E0207](https://doc.rust-lang.org/error-index.html#E0207) + /// for more on unconstrained type errors. #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] - pub struct Derived; + pub struct Derived(PhantomData); /// Constant Allocation Mode /// @@ -267,9 +277,6 @@ pub mod mode { /// this allocation mode may be useful to add some leakage to the [`Variable`] abstraction. This /// marker can also be used in situations where a canonical name is needed to refer to /// constants. - /// - /// [`Constant`]: super::Constant - /// [`Variable`]: super::Variable #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Constant; @@ -280,9 +287,9 @@ pub mod mode { #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Public; - impl From for Public { + impl From> for Public { #[inline] - fn from(d: Derived) -> Self { + fn from(d: Derived) -> Self { let _ = d; Self } @@ -295,9 +302,9 @@ pub mod mode { #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Secret; - impl From for Secret { + impl From> for Secret { #[inline] - fn from(d: Derived) -> Self { + fn from(d: Derived) -> Self { let _ = d; Self } diff --git a/manta-crypto/src/eclair/bool.rs b/manta-crypto/src/eclair/bool.rs index f546c1534..c0050bd17 100644 --- a/manta-crypto/src/eclair/bool.rs +++ b/manta-crypto/src/eclair/bool.rs @@ -42,16 +42,6 @@ pub trait Assert: Has { } } -/* FIXME: We cannot implement this yet. -impl Assert for () { - #[inline] - fn assert(&mut self, bit: &Bool) { - // TODO: Use `dbg!` macro here to get more info, but add a feature-flag for this. - assert!(bit); - } -} -*/ - /// Equality Assertion pub trait AssertEq: Assert { /// Asserts that `lhs` and `rhs` are equal. @@ -60,8 +50,7 @@ pub trait AssertEq: Assert { where T: PartialEq, { - let are_equal = lhs.eq(rhs, self); - self.assert(&are_equal); + T::assert_equal(lhs, rhs, self); } /// Asserts that all the elements in `iter` are equal to some `base` element. @@ -91,49 +80,19 @@ pub trait AssertEq: Assert { } } +impl AssertEq for COM where COM: Assert {} + /// Conditional Selection -pub trait ConditionalSelect: Sized +pub trait ConditionalSelect: Sized where COM: Has + ?Sized, { - /// Selects the result of `true_value` when `bit == true` and the result of `false_value` when - /// `bit == false`. - fn select_from( - bit: &Bool, - true_value: T, - false_value: F, - compiler: &mut COM, - ) -> Self - where - T: FnOnce() -> Self, - F: FnOnce() -> Self; - /// Selects `true_value` when `bit == true` and `false_value` when `bit == false`. - #[inline] - fn select(bit: &Bool, true_value: Self, false_value: Self, compiler: &mut COM) -> Self { - Self::select_from(bit, || true_value, || false_value, compiler) - } + fn select(bit: &Bool, true_value: &Self, false_value: &Self, compiler: &mut COM) -> Self; } -/* FIXME: We cannot implement this yet. -impl ConditionalSelect for V { - #[inline] - fn select_from(bit: &bool, true_value: T, false_value: F, _: &mut ()) -> Self - where - T: FnOnce() -> Self, - F: FnOnce() -> Self, - { - if *bit { - true_value() - } else { - false_value() - } - } -} -*/ - /// Conditional Swap -pub trait ConditionalSwap: Sized +pub trait ConditionalSwap: Sized where COM: Has + ?Sized, { @@ -141,16 +100,3 @@ where /// false`. fn swap(bit: &Bool, lhs: &Self, rhs: &Self, compiler: &mut COM) -> (Self, Self); } - -/* FIXME: We cannot implement this yet. -impl ConditionalSwap for V { - #[inline] - fn swap(bit: &bool, lhs: Self, rhs: Self, _: &mut ()) -> (Self, Self) { - if *bit { - (rhs, lhs) - } else { - (lhs, rhs) - } - } -} -*/ diff --git a/manta-crypto/src/eclair/cmp.rs b/manta-crypto/src/eclair/cmp.rs index 2f3cc3625..1f40ac258 100644 --- a/manta-crypto/src/eclair/cmp.rs +++ b/manta-crypto/src/eclair/cmp.rs @@ -16,10 +16,15 @@ //! Comparison -use crate::eclair::{bool::Bool, ops::Not, Has}; +use crate::eclair::{ + bool::{Assert, Bool}, + ops::Not, + Has, +}; +use core::cmp; /// Partial Equivalence Relations -pub trait PartialEq +pub trait PartialEq where Rhs: ?Sized, COM: Has + ?Sized, @@ -35,9 +40,23 @@ where { self.eq(other, compiler).not(compiler) } + + /// Asserts that `self` and `rhs` are equal. + /// + /// # Implementation Note + /// + /// This method is an optimization path for the case when comparing for equality and then + /// asserting is more expensive than a custom assertion. + #[inline] + fn assert_equal(&self, rhs: &Rhs, compiler: &mut COM) + where + COM: Assert, + { + let are_equal = self.eq(rhs, compiler); + compiler.assert(&are_equal); + } } -/* FIXME: We cannot implement this yet. impl PartialEq for T where T: cmp::PartialEq, @@ -52,15 +71,12 @@ where self.ne(rhs) } } -*/ /// Equality -pub trait Eq: PartialEq +pub trait Eq: PartialEq where COM: Has, { } -/* FIXME: We cannot implement this yet. impl Eq for T where T: cmp::Eq {} -*/ diff --git a/manta-crypto/src/eclair/mod.rs b/manta-crypto/src/eclair/mod.rs index 53d084afb..bdbc2c2d7 100644 --- a/manta-crypto/src/eclair/mod.rs +++ b/manta-crypto/src/eclair/mod.rs @@ -41,6 +41,13 @@ impl Native for () { fn compiler() -> Self {} } +/// Non-Native Compiler Marker Trait +/// +/// This `trait` is explicitly not implemented for `()`, the default native compiler. This marker +/// can be used to write explicitly different implementations for native and non-native compilers +/// where otherwise a generic implementation would have to exist. +pub trait NonNative {} + /// Compiler Type Introspection pub trait Has { /// Compiler Type @@ -53,8 +60,10 @@ pub trait Has { type Type; } -/* FIXME: We cannot implement this yet. +/// Introspection for the Native Compiler +/// +/// The native compiler has access to all the types available to Rust and has access to them in +/// their native form so the allocated type [`Type`](Has::Type) is exactly the generic type `T`. impl Has for () { type Type = T; } -*/ diff --git a/manta-crypto/src/eclair/num.rs b/manta-crypto/src/eclair/num.rs index 1675ef5ed..507bec67f 100644 --- a/manta-crypto/src/eclair/num.rs +++ b/manta-crypto/src/eclair/num.rs @@ -19,6 +19,24 @@ use crate::eclair::ops::{Add, AddAssign, Mul, MulAssign}; use core::{borrow::Borrow, ops::Deref}; +/// Additive Identity +pub trait Zero { + /// Verification Type + type Verification; + + /// Returns a truthy value if `self` is equal to the additive identity. + fn is_zero(&self, compiler: &mut COM) -> Self::Verification; +} + +/// Multiplicative Identity +pub trait One { + /// Verification Type + type Verification; + + /// Returns a truthy value if `self` is equal to the multiplicative identity. + fn is_one(&self, compiler: &mut COM) -> Self::Verification; +} + /// Within-Bit-Range Assertion pub trait AssertWithinBitRange { /// Asserts that `value` is smaller than `2^BITS` diff --git a/manta-crypto/src/encryption/convert/key.rs b/manta-crypto/src/encryption/convert/key.rs index 7966003be..fc176015c 100644 --- a/manta-crypto/src/encryption/convert/key.rs +++ b/manta-crypto/src/encryption/convert/key.rs @@ -217,7 +217,7 @@ where where R: Read, { - Ok(Self::new(E::decode(&mut reader)?)) + Ok(Self::new(Decode::decode(&mut reader)?)) } } diff --git a/manta-crypto/src/encryption/convert/mod.rs b/manta-crypto/src/encryption/convert/mod.rs index 178ce22f1..13f06759e 100644 --- a/manta-crypto/src/encryption/convert/mod.rs +++ b/manta-crypto/src/encryption/convert/mod.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with manta-rs. If not, see . -//! Conversion Primitives and Adapters +//! Encryption Scheme Conversion Primitives and Adapters pub mod key; pub mod plaintext; diff --git a/manta-crypto/src/encryption/convert/plaintext.rs b/manta-crypto/src/encryption/convert/plaintext.rs index a67f41689..786625271 100644 --- a/manta-crypto/src/encryption/convert/plaintext.rs +++ b/manta-crypto/src/encryption/convert/plaintext.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with manta-rs. If not, see . -//! Plaintext Conversion Primitives and Adapters +//! Encryption Scheme Plaintext Conversion Primitives and Adapters use crate::{ encryption::{ @@ -226,7 +226,7 @@ where where R: Read, { - Ok(Self::new(E::decode(&mut reader)?)) + Ok(Self::new(Decode::decode(&mut reader)?)) } } diff --git a/manta-crypto/src/encryption/hybrid.rs b/manta-crypto/src/encryption/hybrid.rs index 4a911a739..7013ea6fb 100644 --- a/manta-crypto/src/encryption/hybrid.rs +++ b/manta-crypto/src/encryption/hybrid.rs @@ -21,6 +21,10 @@ //! encryption scheme inlines this complexity into the encryption interfaces. use crate::{ + constraint::{ + self, Allocate, Allocator, Assert, AssertEq, BitAnd, Bool, Constant, Derived, Has, Var, + Variable, + }, encryption::{ CiphertextType, Decrypt, DecryptedPlaintextType, DecryptionKeyType, Derive, Encrypt, EncryptedMessage, EncryptionKeyType, HeaderType, PlaintextType, RandomnessType, @@ -111,6 +115,31 @@ where } } +impl Variable, COM> for Randomness +where + K: key::agreement::Types + Constant, + E: RandomnessType + Constant, + K::SecretKey: Variable, + E::Randomness: Variable, + K::Type: key::agreement::Types>, + E::Type: RandomnessType>, +{ + type Type = Randomness; + + #[inline] + fn new_unknown(compiler: &mut COM) -> Self { + Self::new(compiler.allocate_unknown(), compiler.allocate_unknown()) + } + + #[inline] + fn new_known(this: &Self::Type, compiler: &mut COM) -> Self { + Self::new( + this.ephemeral_secret_key.as_known(compiler), + this.randomness.as_known(compiler), + ) + } +} + /// Full Ciphertext #[cfg_attr( feature = "serde", @@ -123,9 +152,7 @@ where Copy(bound = "K::PublicKey: Copy, E::Ciphertext: Copy"), Debug(bound = "K::PublicKey: Debug, E::Ciphertext: Debug"), Default(bound = "K::PublicKey: Default, E::Ciphertext: Default"), - Eq(bound = "K::PublicKey: Eq, E::Ciphertext: Eq"), - Hash(bound = "K::PublicKey: Hash, E::Ciphertext: Hash"), - PartialEq(bound = "K::PublicKey: PartialEq, E::Ciphertext: PartialEq") + Hash(bound = "K::PublicKey: Hash, E::Ciphertext: Hash") )] pub struct Ciphertext where @@ -170,6 +197,57 @@ where } } +impl constraint::PartialEq for Ciphertext +where + COM: Has, + Bool: BitAnd, COM, Output = Bool>, + K: key::agreement::Types, + E: CiphertextType, + K::PublicKey: constraint::PartialEq, + E::Ciphertext: constraint::PartialEq, +{ + #[inline] + fn eq(&self, rhs: &Self, compiler: &mut COM) -> Bool { + self.ephemeral_public_key + .eq(&rhs.ephemeral_public_key, compiler) + .bitand(self.ciphertext.eq(&rhs.ciphertext, compiler), compiler) + } + + #[inline] + fn assert_equal(&self, rhs: &Self, compiler: &mut COM) + where + COM: Assert, + { + compiler.assert_eq(&self.ephemeral_public_key, &rhs.ephemeral_public_key); + compiler.assert_eq(&self.ciphertext, &rhs.ciphertext); + } +} + +impl Variable, COM> for Ciphertext +where + K: key::agreement::Types + Constant, + E: CiphertextType + Constant, + K::PublicKey: Variable, + E::Ciphertext: Variable, + K::Type: key::agreement::Types>, + E::Type: CiphertextType>, +{ + type Type = Ciphertext; + + #[inline] + fn new_unknown(compiler: &mut COM) -> Self { + Self::new(compiler.allocate_unknown(), compiler.allocate_unknown()) + } + + #[inline] + fn new_known(this: &Self::Type, compiler: &mut COM) -> Self { + Self::new( + this.ephemeral_public_key.as_known(compiler), + this.ciphertext.as_known(compiler), + ) + } +} + /// Hybrid Encryption Scheme #[cfg_attr( feature = "serde", @@ -346,8 +424,8 @@ where R: Read, { Ok(Self::new( - K::decode(&mut reader).map_err(|err| err.map_decode(|_| ()))?, - E::decode(&mut reader).map_err(|err| err.map_decode(|_| ()))?, + Decode::decode(&mut reader).map_err(|err| err.map_decode(|_| ()))?, + Decode::decode(&mut reader).map_err(|err| err.map_decode(|_| ()))?, )) } } @@ -381,3 +459,19 @@ where Self::new(rng.sample(distribution.0), rng.sample(distribution.1)) } } + +impl Constant for Hybrid +where + K: Constant, + E: Constant, +{ + type Type = Hybrid; + + #[inline] + fn new_constant(this: &Self::Type, compiler: &mut COM) -> Self { + Self::new( + this.key_agreement_scheme.as_constant(compiler), + this.encryption_scheme.as_constant(compiler), + ) + } +} diff --git a/manta-crypto/src/encryption/mod.rs b/manta-crypto/src/encryption/mod.rs index 0180e1b41..5ab112755 100644 --- a/manta-crypto/src/encryption/mod.rs +++ b/manta-crypto/src/encryption/mod.rs @@ -20,7 +20,13 @@ //! set of behavior `trait`s which require those types to be implemented. See the [`Encrypt`] and //! [`Decrypt`] `trait`s for more. -use crate::rand::{Rand, RngCore, Sample}; +use crate::{ + constraint::{ + self, Allocate, Allocator, Assert, AssertEq, BitAnd, Bool, Constant, Derived, Has, Public, + Var, Variable, + }, + rand::{Rand, RngCore, Sample}, +}; use core::{fmt::Debug, hash::Hash}; #[cfg(feature = "serde")] @@ -52,6 +58,9 @@ where type Header = T::Header; } +/// Header Type +pub type Header = ::Header; + /// Ciphertext /// /// The ciphertext type represents the piece of the encrypt-decrypt interface that contains the @@ -71,6 +80,9 @@ where type Ciphertext = T::Ciphertext; } +/// Ciphertext Type +pub type Ciphertext = ::Ciphertext; + /// Encryption Key /// /// The encryption key is the information required to produce a valid ciphertext that is targeted @@ -89,6 +101,9 @@ where type EncryptionKey = T::EncryptionKey; } +/// Encryption Key Type +pub type EncryptionKey = ::EncryptionKey; + /// Decryption Key /// /// The decryption key is the information required to open a valid ciphertext that was encrypted @@ -107,6 +122,9 @@ where type DecryptionKey = T::DecryptionKey; } +/// Decryption Key Type +pub type DecryptionKey = ::DecryptionKey; + /// Plaintext /// /// The core payload of the encryption/decryption protocol. All the information in the plaintext @@ -127,6 +145,9 @@ where type Plaintext = T::Plaintext; } +/// Plaintext Type +pub type Plaintext = ::Plaintext; + /// Randomness /// /// The randomness type allows us to inject some extra randomness to hide repeated encryptions @@ -147,6 +168,9 @@ where type Randomness = T::Randomness; } +/// Randomness Type +pub type Randomness = ::Randomness; + /// Decrypted Plaintext /// /// For decryption, we not only get out some data resembling the [`Plaintext`], but also @@ -168,6 +192,9 @@ where type DecryptedPlaintext = T::DecryptedPlaintext; } +/// Decrypted Plaintext Type +pub type DecryptedPlaintext = ::DecryptedPlaintext; + /// Encryption Key Derivation /// /// For protocols that can derive the [`EncryptionKey`] from the [`DecryptionKey`], this `trait` can @@ -370,6 +397,30 @@ where } } +impl Variable, COM> for Message +where + E: HeaderType + PlaintextType + Constant, + E::Header: Variable, + E::Plaintext: Variable, + E::Type: HeaderType
> + + PlaintextType>, +{ + type Type = Message<E::Type>; + + #[inline] + fn new_unknown(compiler: &mut COM) -> Self { + Self::new(compiler.allocate_unknown(), compiler.allocate_unknown()) + } + + #[inline] + fn new_known(this: &Self::Type, compiler: &mut COM) -> Self { + Self::new( + this.header.as_known(compiler), + this.plaintext.as_known(compiler), + ) + } +} + /// Encrypted Message #[cfg_attr( feature = "serde", @@ -382,9 +433,7 @@ where Copy(bound = "E::Header: Copy, E::Ciphertext: Copy"), Debug(bound = "E::Header: Debug, E::Ciphertext: Debug"), Default(bound = "E::Header: Default, E::Ciphertext: Default"), - Eq(bound = "E::Header: Eq, E::Ciphertext: Eq"), - Hash(bound = "E::Header: Hash, E::Ciphertext: Hash"), - PartialEq(bound = "E::Header: PartialEq, E::Ciphertext: PartialEq") + Hash(bound = "E::Header: Hash, E::Ciphertext: Hash") )] pub struct EncryptedMessage<E> where @@ -420,11 +469,48 @@ where { cipher.decrypt(key, &self.header, &self.ciphertext, compiler) } + + /// Converts the [`EncryptedMessage`] into the new cipher `F` converting the ciphertext and + /// header. + #[inline] + pub fn into<F>(self) -> EncryptedMessage<F> + where + F: CiphertextType + HeaderType + ?Sized, + E::Ciphertext: Into<F::Ciphertext>, + E::Header: Into<F::Header>, + { + EncryptedMessage::new(self.header.into(), self.ciphertext.into()) + } +} + +impl<E, COM> constraint::PartialEq<Self, COM> for EncryptedMessage<E> +where + E: CiphertextType + HeaderType + ?Sized, + COM: Has<bool>, + Bool<COM>: BitAnd<Bool<COM>, COM, Output = Bool<COM>>, + E::Ciphertext: constraint::PartialEq<E::Ciphertext, COM>, + E::Header: constraint::PartialEq<E::Header, COM>, +{ + #[inline] + fn eq(&self, rhs: &Self, compiler: &mut COM) -> Bool<COM> { + self.header + .eq(&rhs.header, compiler) + .bitand(self.ciphertext.eq(&rhs.ciphertext, compiler), compiler) + } + + #[inline] + fn assert_equal(&self, rhs: &Self, compiler: &mut COM) + where + COM: Assert, + { + compiler.assert_eq(&self.header, &rhs.header); + compiler.assert_eq(&self.ciphertext, &rhs.ciphertext); + } } impl<E, H, C> Sample<(H, C)> for EncryptedMessage<E> where - E: HeaderType + CiphertextType, + E: CiphertextType + HeaderType, E::Header: Sample<H>, E::Ciphertext: Sample<C>, { @@ -437,6 +523,54 @@ where } } +impl<E, H, C, COM> Variable<Derived<(H, C)>, COM> for EncryptedMessage<E> +where + E: CiphertextType + HeaderType + Constant<COM>, + E::Header: Variable<H, COM>, + E::Ciphertext: Variable<C, COM>, + E::Type: CiphertextType<Ciphertext = Var<E::Ciphertext, C, COM>> + + HeaderType<Header = Var<E::Header, H, COM>>, +{ + type Type = EncryptedMessage<E::Type>; + + #[inline] + fn new_unknown(compiler: &mut COM) -> Self { + Self::new(compiler.allocate_unknown(), compiler.allocate_unknown()) + } + + #[inline] + fn new_known(this: &Self::Type, compiler: &mut COM) -> Self { + Self::new( + this.header.as_known(compiler), + this.ciphertext.as_known(compiler), + ) + } +} + +impl<E, COM> Variable<Public, COM> for EncryptedMessage<E> +where + E: CiphertextType + HeaderType + Constant<COM>, + E::Header: Variable<Public, COM>, + E::Ciphertext: Variable<Public, COM>, + E::Type: CiphertextType<Ciphertext = Var<E::Ciphertext, Public, COM>> + + HeaderType<Header = Var<E::Header, Public, COM>>, +{ + type Type = EncryptedMessage<E::Type>; + + #[inline] + fn new_unknown(compiler: &mut COM) -> Self { + Self::new(compiler.allocate_unknown(), compiler.allocate_unknown()) + } + + #[inline] + fn new_known(this: &Self::Type, compiler: &mut COM) -> Self { + Self::new( + this.header.as_known(compiler), + this.ciphertext.as_known(compiler), + ) + } +} + /// Testing Framework #[cfg(feature = "test")] #[cfg_attr(doc_cfg, doc(cfg(feature = "test")))] diff --git a/manta-crypto/src/key.rs b/manta-crypto/src/key.rs index 97369f274..0eb147c63 100644 --- a/manta-crypto/src/key.rs +++ b/manta-crypto/src/key.rs @@ -231,7 +231,7 @@ pub mod kdf { R: Read, { Ok(Self::new( - F::decode(&mut reader).map_err(|err| err.map_decode(|_| ()))?, + Decode::decode(&mut reader).map_err(|err| err.map_decode(|_| ()))?, )) } } diff --git a/manta-crypto/src/merkle_tree/tree.rs b/manta-crypto/src/merkle_tree/tree.rs index 0f0ed005a..5124660e2 100644 --- a/manta-crypto/src/merkle_tree/tree.rs +++ b/manta-crypto/src/merkle_tree/tree.rs @@ -29,7 +29,7 @@ use crate::{ self, Accumulator, ConstantCapacityAccumulator, ExactSizeAccumulator, MembershipProof, OptimizedAccumulator, }, - constraint::{self, Allocate, AssertEq, Bool, ConditionalSwap, Constant, Has}, + constraint::{self, Allocate, AssertEq, Bool, ConditionalSwap, Constant, Has, NonNative}, merkle_tree::{ fork::{ForkedTree, Trunk}, inner_tree::InnerMap, @@ -670,7 +670,7 @@ where /// Merkle Tree Root pub type Root<C, COM = ()> = InnerDigest<C, COM>; -impl<C> accumulator::Model for Parameters<C> +impl<C> accumulator::Types for Parameters<C> where C: Configuration + ?Sized, InnerDigest<C>: PartialEq, @@ -678,6 +678,13 @@ where type Item = Leaf<C>; type Witness = Path<C>; type Output = Root<C>; +} + +impl<C> accumulator::Model for Parameters<C> +where + C: Configuration + ?Sized, + InnerDigest<C>: PartialEq, +{ type Verification = bool; #[inline] @@ -692,16 +699,25 @@ where } } -impl<C, COM> accumulator::Model<COM> for Parameters<C, COM> +impl<C, COM> accumulator::Types for Parameters<C, COM> where C: Configuration<COM> + ?Sized, - COM: Has<bool>, + COM: Has<bool> + NonNative, InnerDigest<C, COM>: ConditionalSwap<COM> + constraint::PartialEq<InnerDigest<C, COM>, COM>, LeafDigest<C, COM>: ConditionalSwap<COM>, { type Item = Leaf<C, COM>; type Witness = PathVar<C, COM>; type Output = Root<C, COM>; +} + +impl<C, COM> accumulator::Model<COM> for Parameters<C, COM> +where + C: Configuration<COM> + ?Sized, + COM: Has<bool> + NonNative, + InnerDigest<C, COM>: ConditionalSwap<COM> + constraint::PartialEq<InnerDigest<C, COM>, COM>, + LeafDigest<C, COM>: ConditionalSwap<COM>, +{ type Verification = Bool<COM>; #[inline] @@ -718,8 +734,8 @@ where impl<C, COM> accumulator::AssertValidVerification<COM> for Parameters<C, COM> where - COM: AssertEq, C: Configuration<COM> + ?Sized, + COM: AssertEq + NonNative, InnerDigest<C, COM>: ConditionalSwap<COM> + constraint::PartialEq<InnerDigest<C, COM>, COM>, LeafDigest<C, COM>: ConditionalSwap<COM>, { diff --git a/manta-util/src/num.rs b/manta-util/src/num.rs index 6f960ed8c..73f9796ea 100644 --- a/manta-util/src/num.rs +++ b/manta-util/src/num.rs @@ -49,3 +49,21 @@ impl Ceil<usize> for f64 { self.ceil() as usize } } + +/// Checked Addition +pub trait CheckedAdd<Rhs = Self> { + /// Output Type + type Output; + + /// Checked integer subtraction. Computes `self + rhs`, returning `None` if overflow occurred. + fn checked_add(self, rhs: Rhs) -> Option<Self::Output>; +} + +/// Checked Subtraction +pub trait CheckedSub<Rhs = Self> { + /// Output Type + type Output; + + /// Checked integer subtraction. Computes `self - rhs`, returning `None` if overflow occurred. + fn checked_sub(self, rhs: Rhs) -> Option<Self::Output>; +} diff --git a/manta-util/src/vec.rs b/manta-util/src/vec.rs index 6969c414e..52937a0dd 100644 --- a/manta-util/src/vec.rs +++ b/manta-util/src/vec.rs @@ -105,3 +105,21 @@ where { padded_chunks_with(slice, width, Default::default) } + +/// Returns `true` if all elements of `slice` return `false` when compared with `eq`. +/// +/// # Partial Equivalence Relation +/// +/// The `eq` function _must_ satisfy all the requirements for a [`PartialEq`] implementation. +#[inline] +pub fn all_unequal<T, F>(slice: &[T], mut eq: F) -> bool +where + F: FnMut(&T, &T) -> bool, +{ + for (i, x) in slice.iter().enumerate() { + if slice.iter().skip(i + 1).any(|y| eq(x, y)) { + return false; + } + } + true +} From a00a5f5ba034ca4eee064b121ddfe9798b1c197f Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" <bhgomes@pm.me> Date: Tue, 19 Jul 2022 10:11:16 -0400 Subject: [PATCH 2/7] feat: add implementations of `BitAnd` to arkworks backend --- CHANGELOG.md | 1 + .../src/crypto/constraint/arkworks/mod.rs | 25 +++++++++++++------ workspace-hack/Cargo.toml | 4 +-- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7917297ea..d5a071d9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] ### Added - [\#131](https://github.com/Manta-Network/manta-rs/pull/131) Add abstract Phase 1 for Groth16 trusted setup +- [\#176](https://github.com/Manta-Network/manta-rs/pull/176) Add ECLAIR utilities for the new circuits ### Changed diff --git a/manta-pay/src/crypto/constraint/arkworks/mod.rs b/manta-pay/src/crypto/constraint/arkworks/mod.rs index dd3b1f854..29fb1e9fe 100644 --- a/manta-pay/src/crypto/constraint/arkworks/mod.rs +++ b/manta-pay/src/crypto/constraint/arkworks/mod.rs @@ -28,7 +28,8 @@ use manta_crypto::{ constraint::{ self, measure::{Count, Measure}, - mode, Add, Assert, AssertEq, ConditionalSwap, Constant, Has, Public, Secret, Variable, + mode, Add, Assert, AssertEq, BitAnd, ConditionalSwap, Constant, Has, NonNative, Public, + Secret, Variable, }, eclair::num::AssertWithinBitRange, rand::{RngCore, Sample}, @@ -310,6 +311,8 @@ where } } +impl<F> NonNative for R1CS<F> where F: PrimeField {} + impl<F> Has<bool> for R1CS<F> where F: PrimeField, @@ -328,12 +331,7 @@ where } } -impl<F> AssertEq for R1CS<F> -where - F: PrimeField, -{ - // TODO: Implement these optimizations. -} +impl<F> AssertEq for R1CS<F> where F: PrimeField {} impl<F, const BITS: usize> AssertWithinBitRange<FpVar<F>, BITS> for R1CS<F> where @@ -470,6 +468,19 @@ where } } +impl<F> BitAnd<Self, R1CS<F>> for Boolean<F> +where + F: PrimeField, +{ + type Output = Self; + + #[inline] + fn bitand(self, rhs: Self, compiler: &mut R1CS<F>) -> Self::Output { + let _ = compiler; + self.and(&rhs).expect("Bitwise AND is not allowed to fail.") + } +} + impl<F> Constant<R1CS<F>> for FpVar<F> where F: PrimeField, diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index b7d9e3f2e..0756740e5 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.5", default-features = false, features = ["std"] } +crypto-common = { version = "0.1.6", 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"] } @@ -53,7 +53,7 @@ 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.5", default-features = false, features = ["std"] } +crypto-common = { version = "0.1.6", 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"] } From 58837f45094af7b6057d7d5b2821cd55ed298ec3 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" <bhgomes@pm.me> Date: Tue, 19 Jul 2022 10:28:04 -0400 Subject: [PATCH 3/7] fix: remove blanket implementation for ECLAIR traits for now --- manta-accounting/src/transfer/mod.rs | 8 +++++--- manta-accounting/src/transfer/sender.rs | 2 +- manta-crypto/src/eclair/cmp.rs | 5 ++++- manta-crypto/src/encryption/hybrid.rs | 4 +++- manta-crypto/src/encryption/mod.rs | 14 +++++++++++++- manta-pay/src/config.rs | 6 ++---- manta-pay/src/crypto/constraint/arkworks/mod.rs | 6 ++---- 7 files changed, 30 insertions(+), 15 deletions(-) diff --git a/manta-accounting/src/transfer/mod.rs b/manta-accounting/src/transfer/mod.rs index d852843de..bd5c6d725 100644 --- a/manta-accounting/src/transfer/mod.rs +++ b/manta-accounting/src/transfer/mod.rs @@ -33,7 +33,7 @@ use crate::asset::{Asset, AssetId, AssetValue}; use alloc::vec::Vec; use core::{fmt::Debug, hash::Hash, marker::PhantomData, ops::Deref}; use manta_crypto::{ - accumulator::{AssertValidVerification, MembershipProof, Model}, + accumulator::{self, AssertValidVerification, MembershipProof, Model}, constraint::{ self, Add, Allocate, Allocator, AssertEq, Bool, Constant, Derived, ProofSystem, ProofSystemInput, Public, Secret, Variable, @@ -280,10 +280,12 @@ pub type VoidNumber<C> = <C as Configuration>::VoidNumber; pub type VoidNumberVar<C> = <C as Configuration>::VoidNumberVar; /// UTXO Accumulator Witness Type -pub type UtxoAccumulatorWitness<C> = <<C as Configuration>::UtxoAccumulatorModel as Model>::Witness; +pub type UtxoAccumulatorWitness<C> = + <<C as Configuration>::UtxoAccumulatorModel as accumulator::Types>::Witness; /// UTXO Accumulator Output Type -pub type UtxoAccumulatorOutput<C> = <<C as Configuration>::UtxoAccumulatorModel as Model>::Output; +pub type UtxoAccumulatorOutput<C> = + <<C as Configuration>::UtxoAccumulatorModel as accumulator::Types>::Output; /// UTXO Membership Proof Type pub type UtxoMembershipProof<C> = MembershipProof<<C as Configuration>::UtxoAccumulatorModel>; diff --git a/manta-accounting/src/transfer/sender.rs b/manta-accounting/src/transfer/sender.rs index 2b19f2349..09611b9f6 100644 --- a/manta-accounting/src/transfer/sender.rs +++ b/manta-accounting/src/transfer/sender.rs @@ -356,7 +356,7 @@ where /// called before [`is_unspent`](Self::is_unspent) and /// [`has_matching_utxo_accumulator_output`](Self::has_matching_utxo_accumulator_output). /// - /// [`S::Output`]: manta_crypto::accumulator::Model::Output + /// [`S::Output`]: manta_crypto::accumulator::Types::Output type ValidUtxoAccumulatorOutput: AsRef<UtxoAccumulatorOutput<C>>; /// Super Posting Key diff --git a/manta-crypto/src/eclair/cmp.rs b/manta-crypto/src/eclair/cmp.rs index 1f40ac258..66ece418d 100644 --- a/manta-crypto/src/eclair/cmp.rs +++ b/manta-crypto/src/eclair/cmp.rs @@ -21,7 +21,6 @@ use crate::eclair::{ ops::Not, Has, }; -use core::cmp; /// Partial Equivalence Relations pub trait PartialEq<Rhs, COM = ()> @@ -57,6 +56,7 @@ where } } +/* TODO: impl<T, Rhs> PartialEq<Rhs> for T where T: cmp::PartialEq<Rhs>, @@ -71,6 +71,7 @@ where self.ne(rhs) } } +*/ /// Equality pub trait Eq<COM = ()>: PartialEq<Self, COM> @@ -79,4 +80,6 @@ where { } +/* TODO: impl<T> Eq for T where T: cmp::Eq {} +*/ diff --git a/manta-crypto/src/encryption/hybrid.rs b/manta-crypto/src/encryption/hybrid.rs index 7013ea6fb..4257a4878 100644 --- a/manta-crypto/src/encryption/hybrid.rs +++ b/manta-crypto/src/encryption/hybrid.rs @@ -152,7 +152,9 @@ where Copy(bound = "K::PublicKey: Copy, E::Ciphertext: Copy"), Debug(bound = "K::PublicKey: Debug, E::Ciphertext: Debug"), Default(bound = "K::PublicKey: Default, E::Ciphertext: Default"), - Hash(bound = "K::PublicKey: Hash, E::Ciphertext: Hash") + Eq(bound = "K::PublicKey: Eq, E::Ciphertext: Eq"), + Hash(bound = "K::PublicKey: Hash, E::Ciphertext: Hash"), + PartialEq(bound = "K::PublicKey: PartialEq, E::Ciphertext: PartialEq") )] pub struct Ciphertext<K, E> where diff --git a/manta-crypto/src/encryption/mod.rs b/manta-crypto/src/encryption/mod.rs index 5ab112755..b173fbf2f 100644 --- a/manta-crypto/src/encryption/mod.rs +++ b/manta-crypto/src/encryption/mod.rs @@ -433,7 +433,9 @@ where Copy(bound = "E::Header: Copy, E::Ciphertext: Copy"), Debug(bound = "E::Header: Debug, E::Ciphertext: Debug"), Default(bound = "E::Header: Default, E::Ciphertext: Default"), - Hash(bound = "E::Header: Hash, E::Ciphertext: Hash") + Eq(bound = "E::Header: Eq, E::Ciphertext: Eq"), + Hash(bound = "E::Header: Hash, E::Ciphertext: Hash"), + PartialEq(bound = "E::Header: PartialEq, E::Ciphertext: PartialEq") )] pub struct EncryptedMessage<E> where @@ -508,6 +510,16 @@ where } } +impl<E, COM> constraint::Eq<COM> for EncryptedMessage<E> +where + E: CiphertextType + HeaderType + ?Sized, + COM: Has<bool>, + Bool<COM>: BitAnd<Bool<COM>, COM, Output = Bool<COM>>, + E::Ciphertext: constraint::Eq<COM>, + E::Header: constraint::Eq<COM>, +{ +} + impl<E, H, C> Sample<(H, C)> for EncryptedMessage<E> where E: CiphertextType + HeaderType, diff --git a/manta-pay/src/config.rs b/manta-pay/src/config.rs index b74ec640c..af59e3d3d 100644 --- a/manta-pay/src/config.rs +++ b/manta-pay/src/config.rs @@ -766,10 +766,8 @@ impl transfer::Configuration for Config { >>::VoidNumber; type VoidNumberCommitmentSchemeVar = VoidNumberCommitmentSchemeVar; type UtxoAccumulatorModel = UtxoAccumulatorModel; - type UtxoAccumulatorWitnessVar = - <Self::UtxoAccumulatorModelVar as accumulator::Model<Self::Compiler>>::Witness; - type UtxoAccumulatorOutputVar = - <Self::UtxoAccumulatorModelVar as accumulator::Model<Self::Compiler>>::Output; + type UtxoAccumulatorWitnessVar = <Self::UtxoAccumulatorModelVar as accumulator::Types>::Witness; + type UtxoAccumulatorOutputVar = <Self::UtxoAccumulatorModelVar as accumulator::Types>::Output; type UtxoAccumulatorModelVar = merkle_tree::Parameters<MerkleTreeConfigurationVar, Compiler>; type AssetIdVar = AssetIdVar; type AssetValueVar = AssetValueVar; diff --git a/manta-pay/src/crypto/constraint/arkworks/mod.rs b/manta-pay/src/crypto/constraint/arkworks/mod.rs index 29fb1e9fe..47cacc8ad 100644 --- a/manta-pay/src/crypto/constraint/arkworks/mod.rs +++ b/manta-pay/src/crypto/constraint/arkworks/mod.rs @@ -28,8 +28,8 @@ use manta_crypto::{ constraint::{ self, measure::{Count, Measure}, - mode, Add, Assert, AssertEq, BitAnd, ConditionalSwap, Constant, Has, NonNative, Public, - Secret, Variable, + mode, Add, Assert, BitAnd, ConditionalSwap, Constant, Has, NonNative, Public, Secret, + Variable, }, eclair::num::AssertWithinBitRange, rand::{RngCore, Sample}, @@ -331,8 +331,6 @@ where } } -impl<F> AssertEq for R1CS<F> where F: PrimeField {} - impl<F, const BITS: usize> AssertWithinBitRange<FpVar<F>, BITS> for R1CS<F> where F: PrimeField, From 5e92ffa9a247ca211fe208af3002a112957274ec Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" <bhgomes@pm.me> Date: Tue, 19 Jul 2022 10:44:51 -0400 Subject: [PATCH 4/7] fix: resolve clippy issues and missing comment Signed-off-by: Brandon H. Gomes <bhgomes@pm.me> --- manta-accounting/src/transfer/test.rs | 4 ++-- manta-crypto/src/accumulator.rs | 5 +++++ manta-crypto/src/merkle_tree/tree.rs | 2 +- manta-pay/src/crypto/poseidon/matrix.rs | 2 +- manta-pay/src/simulation/ledger/mod.rs | 2 +- manta-trusted-setup/src/util.rs | 2 +- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/manta-accounting/src/transfer/test.rs b/manta-accounting/src/transfer/test.rs index fade4b812..f1c373269 100644 --- a/manta-accounting/src/transfer/test.rs +++ b/manta-accounting/src/transfer/test.rs @@ -371,7 +371,7 @@ where rng, ); Self::new( - has_public_participants(SOURCES, SINKS).then(|| asset.id), + has_public_participants(SOURCES, SINKS).then_some(asset.id), into_array_unchecked(input), into_array_unchecked(senders), into_array_unchecked(receivers), @@ -407,7 +407,7 @@ where rng, ); Self::new( - has_public_participants(SOURCES, SINKS).then(|| distribution.asset_id), + has_public_participants(SOURCES, SINKS).then_some(distribution.asset_id), sample_asset_values(distribution.source_sum, rng), into_array_unchecked(senders), into_array_unchecked(receivers), diff --git a/manta-crypto/src/accumulator.rs b/manta-crypto/src/accumulator.rs index 324177eb7..7943940c5 100644 --- a/manta-crypto/src/accumulator.rs +++ b/manta-crypto/src/accumulator.rs @@ -364,7 +364,12 @@ where model.assert_valid(item, &self.witness, &self.output, compiler) } + /// Converts `self` from the `M` accumulator model to the `N` accumulator model. /// + /// # Validity + /// + /// This function cannot guarantee that the point-wise conversion of the witness and output + /// preserves the membership proof validity. #[inline] pub fn into<N>(self) -> MembershipProof<N, COM> where diff --git a/manta-crypto/src/merkle_tree/tree.rs b/manta-crypto/src/merkle_tree/tree.rs index 5124660e2..d3eacce84 100644 --- a/manta-crypto/src/merkle_tree/tree.rs +++ b/manta-crypto/src/merkle_tree/tree.rs @@ -241,7 +241,7 @@ where L: IntoIterator<Item = &'l Leaf<C>>, { let mut tree = Self::new(parameters); - tree.extend(parameters, leaves).then(move || tree) + tree.extend(parameters, leaves).then_some(tree) } /// Builds a new merkle tree with the given `leaves` returning `None` if the slice diff --git a/manta-pay/src/crypto/poseidon/matrix.rs b/manta-pay/src/crypto/poseidon/matrix.rs index 43f81d6e5..319defacf 100644 --- a/manta-pay/src/crypto/poseidon/matrix.rs +++ b/manta-pay/src/crypto/poseidon/matrix.rs @@ -347,7 +347,7 @@ where { /// Returns a new [`SquareMatrix`] representation of `m` if it returns `true` to [`is_square`](Matrix::is_square). pub fn new(m: Matrix<F>) -> Option<Self> { - m.is_square().then(|| Self(m)) + m.is_square().then_some(Self(m)) } /// Builds a new [`SquareMatrix`] without checking whether `m` is a valid square matrix. diff --git a/manta-pay/src/simulation/ledger/mod.rs b/manta-pay/src/simulation/ledger/mod.rs index f851a5bef..0d6c19836 100644 --- a/manta-pay/src/simulation/ledger/mod.rs +++ b/manta-pay/src/simulation/ledger/mod.rs @@ -371,7 +371,7 @@ impl TransferLedger<Config> for Ledger { &proof, ) .ok()? - .then(move || (Wrap(()), ())) + .then_some((Wrap(()), ())) } #[inline] diff --git a/manta-trusted-setup/src/util.rs b/manta-trusted-setup/src/util.rs index 6168f0238..2357a08d2 100644 --- a/manta-trusted-setup/src/util.rs +++ b/manta-trusted-setup/src/util.rs @@ -372,7 +372,7 @@ pub trait PairingEngineExt: PairingEngine { { let lhs = (lhs.0.into(), lhs.1.into()); let rhs = (rhs.0.into(), rhs.1.into()); - Self::has_same(&lhs, &rhs).then(|| (lhs, rhs)) + Self::has_same(&lhs, &rhs).then_some((lhs, rhs)) } /// Checks if the ratio of `(lhs.0, lhs.1)` from `G1` is the same as the ratio of From 7d7a975bc7d0e941adb650404a9f60468c5bb32c Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" <bhgomes@pm.me> Date: Sat, 23 Jul 2022 13:12:18 -0400 Subject: [PATCH 5/7] chore: update dependencies Signed-off-by: Brandon H. Gomes <bhgomes@pm.me> --- manta-pay/Cargo.toml | 4 ++-- manta-util/Cargo.toml | 4 ++-- workspace-hack/Cargo.toml | 8 +++----- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/manta-pay/Cargo.toml b/manta-pay/Cargo.toml index 512ba85c7..68a680eb3 100644 --- a/manta-pay/Cargo.toml +++ b/manta-pay/Cargo.toml @@ -114,10 +114,10 @@ ark-relations = { version = "0.3.0", optional = true, default-features = false } ark-serialize = { version = "0.3.0", optional = true, default-features = false, features = ["derive"] } ark-snark = { version = "0.3.0", optional = true, default-features = false } ark-std = { version = "0.3.0", optional = true, default-features = false } -bip32 = { version = "0.3.0", optional = true, default-features = false, features = ["bip39", "secp256k1"] } +bip32 = { version = "0.4.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.12", optional = true, default-features = false, features = ["color", "derive", "std", "suggestions", "unicode", "wrap_help"] } +clap = { version = "3.2.14", 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-util/Cargo.toml b/manta-util/Cargo.toml index 1e0df1227..970fecdbc 100644 --- a/manta-util/Cargo.toml +++ b/manta-util/Cargo.toml @@ -38,8 +38,8 @@ serde-array = ["serde", "serde_with"] std = ["alloc"] [dependencies] -crossbeam-channel = { version = "0.5.4", optional = true, default-features = false } +crossbeam-channel = { version = "0.5.6", optional = true, default-features = false } rayon = { version = "1.5.3", optional = true, default-features = false } -serde = { version = "1.0.139", optional = true, default-features = false, features = ["derive"] } +serde = { version = "1.0.140", 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 0756740e5..c83afd8b9 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -18,7 +18,6 @@ aes-gcm = { version = "0.9.4", features = ["aes", "alloc"] } 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.6", 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"] } @@ -35,19 +34,18 @@ indexmap = { version = "1.9.1", default-features = false, features = ["std"] } log = { version = "0.4.17", default-features = false, features = ["kv_unstable", "kv_unstable_std", "std", "value-bag"] } memchr = { version = "2.5.0", features = ["std"] } num-traits = { version = "0.2.15", features = ["i128", "libm", "std"] } -pbkdf2 = { version = "0.9.0", default-features = false, features = ["hmac", "sha2"] } ppv-lite86 = { version = "0.2.16", default-features = false, features = ["simd", "std"] } 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.139", features = ["alloc", "derive", "serde_derive", "std"] } +serde = { version = "1.0.140", 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"] } 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.5.6", default-features = false, features = ["alloc", "zeroize_derive"] } +zeroize = { version = "1.5.7", default-features = false, features = ["alloc", "zeroize_derive"] } [build-dependencies] anyhow = { version = "1.0.58", features = ["std"] } @@ -58,7 +56,7 @@ digest-93f6ce9d446188ac = { package = "digest", version = "0.10.3", features = [ 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.139", features = ["alloc", "derive", "serde_derive", "std"] } +serde = { version = "1.0.140", 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 fc5244b526ca022f7b15a01914465d1caa41a26f Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" <bhgomes@pm.me> Date: Thu, 28 Jul 2022 02:38:23 +0100 Subject: [PATCH 6/7] chore: address comments and update dependencies Signed-off-by: Brandon H. Gomes <bhgomes@pm.me> --- manta-benchmark/Cargo.toml | 4 ++-- manta-crypto/src/eclair/alloc.rs | 2 -- manta-pay/Cargo.toml | 4 ++-- manta-util/src/num.rs | 2 +- workspace-hack/Cargo.toml | 2 +- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/manta-benchmark/Cargo.toml b/manta-benchmark/Cargo.toml index 83b6c7b8e..cd95a8c27 100644 --- a/manta-benchmark/Cargo.toml +++ b/manta-benchmark/Cargo.toml @@ -52,9 +52,9 @@ instant = { version = "0.1.12", default-features = false, features = [ "wasm-bin manta-accounting = { path = "../manta-accounting", default-features = false, features = ["test"] } manta-crypto = { path = "../manta-crypto", default-features = false, features = ["getrandom", "test"] } manta-pay = { path = "../manta-pay", default-features = false, features = ["groth16", "test"] } -wasm-bindgen = { version = "0.2.81", default-features = false } +wasm-bindgen = { version = "0.2.82", default-features = false } wasm-bindgen-test = { version = "0.3.30", default-features = false } -web-sys = { version = "0.3.58", default-features = false, features = ["console"] } +web-sys = { version = "0.3.59", default-features = false, features = ["console"] } workspace-hack = { version = "0.1.0", path = "../workspace-hack" } [dev-dependencies] diff --git a/manta-crypto/src/eclair/alloc.rs b/manta-crypto/src/eclair/alloc.rs index 8e6901e69..d2000924c 100644 --- a/manta-crypto/src/eclair/alloc.rs +++ b/manta-crypto/src/eclair/alloc.rs @@ -27,8 +27,6 @@ //! abstractions inside of compilers, like heap allocation. Allocation only refers to lifting //! constants and variables from one compiler to another. -// TODO: How can we have objects that have both `Constant` and `Variable` parts? - use core::marker::PhantomData; /// Constant Type Alias diff --git a/manta-pay/Cargo.toml b/manta-pay/Cargo.toml index 68a680eb3..e3148cef1 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.4.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.14", optional = true, default-features = false, features = ["color", "derive", "std", "suggestions", "unicode", "wrap_help"] } +clap = { version = "3.2.15", 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 } @@ -134,7 +134,7 @@ scale-info = { version = "2.1.2", optional = true, default-features = false, fea serde_json = { version = "1.0.82", optional = true, default-features = false, features = ["alloc"] } tempfile = { version = "3.3.0", optional = true, default-features = false } tide = { version = "0.16.0", optional = true, default-features = false, features = ["h1-server"] } -tokio = { version = "1.20.0", optional = true, default-features = false } +tokio = { version = "1.20.1", optional = true, default-features = false } tokio-tungstenite = { version = "0.17.2", optional = true, default-features = false, features = ["native-tls"] } workspace-hack = { version = "0.1.0", path = "../workspace-hack" } ws_stream_wasm = { version = "0.7.3", optional = true, default-features = false } diff --git a/manta-util/src/num.rs b/manta-util/src/num.rs index 73f9796ea..22a46c323 100644 --- a/manta-util/src/num.rs +++ b/manta-util/src/num.rs @@ -55,7 +55,7 @@ pub trait CheckedAdd<Rhs = Self> { /// Output Type type Output; - /// Checked integer subtraction. Computes `self + rhs`, returning `None` if overflow occurred. + /// Checked integer addition. Computes `self + rhs`, returning `None` if overflow occurred. fn checked_add(self, rhs: Rhs) -> Option<Self::Output>; } diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index c83afd8b9..c8aaef181 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -44,7 +44,7 @@ sha2 = { version = "0.9.9", features = ["std"] } 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"] } +web-sys = { version = "0.3.59", default-features = false, features = ["BinaryType", "Blob", "CloseEvent", "DomException", "Event", "EventTarget", "MessageEvent", "WebSocket", "console"] } zeroize = { version = "1.5.7", default-features = false, features = ["alloc", "zeroize_derive"] } [build-dependencies] From 1d201147435e1fa6a1616b60724ce26e94d4d705 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" <bhgomes@pm.me> Date: Thu, 28 Jul 2022 03:11:46 +0100 Subject: [PATCH 7/7] fix: update based on new nightly compiler version Signed-off-by: Brandon H. Gomes <bhgomes@pm.me> --- .../src/crypto/constraint/arkworks/groth16.rs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/manta-pay/src/crypto/constraint/arkworks/groth16.rs b/manta-pay/src/crypto/constraint/arkworks/groth16.rs index 4772ec424..58c88621b 100644 --- a/manta-pay/src/crypto/constraint/arkworks/groth16.rs +++ b/manta-pay/src/crypto/constraint/arkworks/groth16.rs @@ -252,9 +252,9 @@ where } = &self.0; vk.serialize(&mut writer)?; alpha_g1_beta_g2.serialize(&mut writer)?; - <E::G2Prepared as HasSerialization>::Serialize::from(gamma_g2_neg_pc) + <E::G2Prepared as HasSerialization<'_>>::Serialize::from(gamma_g2_neg_pc) .serialize(&mut writer)?; - <E::G2Prepared as HasSerialization>::Serialize::from(delta_g2_neg_pc) + <E::G2Prepared as HasSerialization<'_>>::Serialize::from(delta_g2_neg_pc) .serialize(&mut writer)?; Ok(()) } @@ -269,9 +269,9 @@ where } = &self.0; vk.serialized_size() + alpha_g1_beta_g2.serialized_size() - + <E::G2Prepared as HasSerialization>::Serialize::from(gamma_g2_neg_pc) + + <E::G2Prepared as HasSerialization<'_>>::Serialize::from(gamma_g2_neg_pc) .serialized_size() - + <E::G2Prepared as HasSerialization>::Serialize::from(delta_g2_neg_pc) + + <E::G2Prepared as HasSerialization<'_>>::Serialize::from(delta_g2_neg_pc) .serialized_size() } @@ -288,9 +288,9 @@ where } = &self.0; vk.serialize_uncompressed(&mut writer)?; alpha_g1_beta_g2.serialize_uncompressed(&mut writer)?; - <E::G2Prepared as HasSerialization>::Serialize::from(gamma_g2_neg_pc) + <E::G2Prepared as HasSerialization<'_>>::Serialize::from(gamma_g2_neg_pc) .serialize_uncompressed(&mut writer)?; - <E::G2Prepared as HasSerialization>::Serialize::from(delta_g2_neg_pc) + <E::G2Prepared as HasSerialization<'_>>::Serialize::from(delta_g2_neg_pc) .serialize_uncompressed(&mut writer)?; Ok(()) } @@ -308,9 +308,9 @@ where } = &self.0; vk.serialize_unchecked(&mut writer)?; alpha_g1_beta_g2.serialize_unchecked(&mut writer)?; - <E::G2Prepared as HasSerialization>::Serialize::from(gamma_g2_neg_pc) + <E::G2Prepared as HasSerialization<'_>>::Serialize::from(gamma_g2_neg_pc) .serialize_unchecked(&mut writer)?; - <E::G2Prepared as HasSerialization>::Serialize::from(delta_g2_neg_pc) + <E::G2Prepared as HasSerialization<'_>>::Serialize::from(delta_g2_neg_pc) .serialize_unchecked(&mut writer)?; Ok(()) } @@ -325,9 +325,9 @@ where } = &self.0; vk.uncompressed_size() + alpha_g1_beta_g2.uncompressed_size() - + <E::G2Prepared as HasSerialization>::Serialize::from(gamma_g2_neg_pc) + + <E::G2Prepared as HasSerialization<'_>>::Serialize::from(gamma_g2_neg_pc) .uncompressed_size() - + <E::G2Prepared as HasSerialization>::Serialize::from(delta_g2_neg_pc) + + <E::G2Prepared as HasSerialization<'_>>::Serialize::from(delta_g2_neg_pc) .uncompressed_size() } }