diff --git a/CHANGELOG.md b/CHANGELOG.md index cc9fa6e22..d133bbc0f 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 - [\#175](https://github.com/Manta-Network/manta-rs/pull/175) Add more documentation around `cargo-hakari` ### Changed 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 = ::VoidNumber; pub type VoidNumberVar = ::VoidNumberVar; /// UTXO Accumulator Witness Type -pub type UtxoAccumulatorWitness = <::UtxoAccumulatorModel as Model>::Witness; +pub type UtxoAccumulatorWitness = + <::UtxoAccumulatorModel as accumulator::Types>::Witness; /// UTXO Accumulator Output Type -pub type UtxoAccumulatorOutput = <::UtxoAccumulatorModel as Model>::Output; +pub type UtxoAccumulatorOutput = + <::UtxoAccumulatorModel as accumulator::Types>::Output; /// UTXO Membership Proof Type pub type UtxoMembershipProof = MembershipProof<::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>; /// Super Posting Key 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/accumulator.rs b/manta-crypto/src/accumulator.rs index 97d66cc70..7943940c5 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,44 @@ 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 + /// 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(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..d2000924c 100644 --- a/manta-crypto/src/eclair/alloc.rs +++ b/manta-crypto/src/eclair/alloc.rs @@ -253,12 +253,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 +275,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 +285,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 +300,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..66ece418d 100644 --- a/manta-crypto/src/eclair/cmp.rs +++ b/manta-crypto/src/eclair/cmp.rs @@ -16,10 +16,14 @@ //! Comparison -use crate::eclair::{bool::Bool, ops::Not, Has}; +use crate::eclair::{ + bool::{Assert, Bool}, + ops::Not, + Has, +}; /// Partial Equivalence Relations -pub trait PartialEq +pub trait PartialEq where Rhs: ?Sized, COM: Has + ?Sized, @@ -35,9 +39,24 @@ 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. +/* TODO: impl PartialEq for T where T: cmp::PartialEq, @@ -55,12 +74,12 @@ where */ /// Equality -pub trait Eq: PartialEq +pub trait Eq: PartialEq where COM: Has, { } -/* FIXME: We cannot implement this yet. +/* TODO: 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..4257a4878 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", @@ -170,6 +199,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 +426,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 +461,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..b173fbf2f 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", @@ -420,11 +471,58 @@ 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, 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: HeaderType + CiphertextType, + E: CiphertextType + HeaderType, E::Header: Sample<H>, E::Ciphertext: Sample<C>, { @@ -437,6 +535,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 783a87f5d..d3eacce84 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-pay/Cargo.toml b/manta-pay/Cargo.toml index 512ba85c7..e3148cef1 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.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-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/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() } } diff --git a/manta-pay/src/crypto/constraint/arkworks/mod.rs b/manta-pay/src/crypto/constraint/arkworks/mod.rs index dd3b1f854..47cacc8ad 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, 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,13 +331,6 @@ where } } -impl<F> AssertEq for R1CS<F> -where - F: PrimeField, -{ - // TODO: Implement these optimizations. -} - impl<F, const BITS: usize> AssertWithinBitRange<FpVar<F>, BITS> for R1CS<F> where F: PrimeField, @@ -470,6 +466,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/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/manta-util/src/num.rs b/manta-util/src/num.rs index 6f960ed8c..22a46c323 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 addition. 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 +} diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index 0756740e5..c8aaef181 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"] } +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] 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"] }