diff --git a/CHANGELOG.md b/CHANGELOG.md index 145e19d88..f31fcf555 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] ### Added +- [\#126](https://github.com/Manta-Network/manta-rs/pull/126) Add ECLAIR v0 scaffolding and deprecate old compiler patterns - [\#128](https://github.com/Manta-Network/manta-rs/pull/128) Add more parameter loading utilities - [\#130](https://github.com/Manta-Network/manta-rs/pull/130) Add the sage script and the hardcoded tests for the security of mds matrix diff --git a/manta-accounting/src/asset.rs b/manta-accounting/src/asset.rs index 8f609905d..1a08dfb71 100644 --- a/manta-accounting/src/asset.rs +++ b/manta-accounting/src/asset.rs @@ -38,7 +38,7 @@ use core::{ }; use derive_more::{Add, AddAssign, Display, From, Sub, SubAssign, Sum}; use manta_crypto::{ - constraint::{Allocator, Secret, ValueSource, Variable}, + constraint::{Allocate, Allocator, Secret, Variable}, rand::{CryptoRng, Rand, RngCore, Sample}, }; use manta_util::{into_array_unchecked, Array, SizeLimit}; diff --git a/manta-accounting/src/key.rs b/manta-accounting/src/key.rs index a384fbd1a..ab87bf006 100644 --- a/manta-accounting/src/key.rs +++ b/manta-accounting/src/key.rs @@ -246,19 +246,19 @@ where #[inline] fn derive(&self, account: AccountIndex, kind: Kind, index: KeyIndex) -> Self::SecretKey { self.key_derivation_function - .derive(&self.base.derive(account, kind, index)) + .derive(&self.base.derive(account, kind, index), &mut ()) } #[inline] fn derive_spend(&self, account: AccountIndex, index: KeyIndex) -> Self::SecretKey { self.key_derivation_function - .derive(&self.base.derive_spend(account, index)) + .derive(&self.base.derive_spend(account, index), &mut ()) } #[inline] fn derive_view(&self, account: AccountIndex, index: KeyIndex) -> Self::SecretKey { self.key_derivation_function - .derive(&self.base.derive_view(account, index)) + .derive(&self.base.derive_view(account, index), &mut ()) } } diff --git a/manta-accounting/src/transfer/mod.rs b/manta-accounting/src/transfer/mod.rs index 6f66df025..eafc9330c 100644 --- a/manta-accounting/src/transfer/mod.rs +++ b/manta-accounting/src/transfer/mod.rs @@ -33,10 +33,10 @@ use crate::asset::{Asset, AssetId, AssetValue}; use alloc::vec::Vec; use core::{fmt::Debug, hash::Hash, iter, marker::PhantomData, ops::Deref}; use manta_crypto::{ - accumulator::{Accumulator, MembershipProof, Model}, + accumulator::{Accumulator, AssertValidVerification, MembershipProof, Model}, constraint::{ - Add, Allocator, Constant, ConstraintSystem, Derived, Equal, Native, ProofSystem, - ProofSystemInput, Public, Secret, ValueSource, Variable, + self, Add, Allocate, Allocator, AssertEq, Bool, Constant, Derived, ProofSystem, + ProofSystemInput, Public, Secret, Variable, }, encryption::hybrid::{DecryptedMessage, EncryptedMessage, HybridPublicKeyEncryptionScheme}, key::{KeyAgreementScheme, KeyDerivationFunction}, @@ -77,34 +77,14 @@ pub trait UtxoCommitmentScheme { /// Unspent Transaction Output Type type Utxo; - /// Commits to the `ephemeral_secret_key`, `public_spend_key`, and `asset` for a UTXO inside of - /// `compiler`. - fn commit_in( - &self, - ephemeral_secret_key: &Self::EphemeralSecretKey, - public_spend_key: &Self::PublicSpendKey, - asset: &Self::Asset, - compiler: &mut COM, - ) -> Self::Utxo; - /// Commits to the `ephemeral_secret_key`, `public_spend_key`, and `asset` for a UTXO. - #[inline] fn commit( &self, ephemeral_secret_key: &Self::EphemeralSecretKey, public_spend_key: &Self::PublicSpendKey, asset: &Self::Asset, - ) -> Self::Utxo - where - COM: Native, - { - self.commit_in( - ephemeral_secret_key, - public_spend_key, - asset, - &mut COM::compiler(), - ) - } + compiler: &mut COM, + ) -> Self::Utxo; } /// Void Number Commitment Scheme @@ -118,22 +98,13 @@ pub trait VoidNumberCommitmentScheme { /// Void Number Type type VoidNumber; - /// Commits to the `secret_spend_key` and `utxo` for a Void Number inside of `compiler`. - fn commit_in( + /// Commits to the `secret_spend_key` and `utxo` for a Void Number. + fn commit( &self, secret_spend_key: &Self::SecretSpendKey, utxo: &Self::Utxo, compiler: &mut COM, ) -> Self::VoidNumber; - - /// Commits to the `secret_spend_key` and `utxo` for a Void Number. - #[inline] - fn commit(&self, secret_spend_key: &Self::SecretSpendKey, utxo: &Self::Utxo) -> Self::VoidNumber - where - COM: Native, - { - self.commit_in(secret_spend_key, utxo, &mut COM::compiler()) - } } /// Transfer Configuration @@ -155,7 +126,7 @@ pub trait Configuration { /// Public Key Variable Type type PublicKeyVar: Variable> - + Equal; + + constraint::PartialEq; /// Key Agreement Scheme Variable Type type KeyAgreementSchemeVar: KeyAgreementScheme< @@ -178,7 +149,7 @@ pub trait Configuration { /// UTXO Variable Type type UtxoVar: Variable> + Variable> - + Equal; + + constraint::PartialEq; /// UTXO Commitment Scheme Variable Type type UtxoCommitmentSchemeVar: UtxoCommitmentScheme< @@ -201,7 +172,7 @@ pub trait Configuration { /// Void Number Variable Type type VoidNumberVar: Variable - + Equal; + + constraint::PartialEq; /// Void Number Commitment Scheme Variable Type type VoidNumberCommitmentSchemeVar: VoidNumberCommitmentScheme< @@ -229,30 +200,31 @@ pub trait Configuration { >; /// UTXO Accumulator Model Variable Type - type UtxoAccumulatorModelVar: Model< + type UtxoAccumulatorModelVar: AssertValidVerification + + Model< Self::Compiler, Item = Self::UtxoVar, Witness = Self::UtxoAccumulatorWitnessVar, Output = Self::UtxoAccumulatorOutputVar, - Verification = ::Bool, + Verification = Bool, > + Constant; /// Asset Id Variable Type type AssetIdVar: Variable + Variable - + Equal; + + constraint::PartialEq; /// Asset Value Variable Type type AssetValueVar: Variable + Variable - + Add - + Equal; + + Add + + constraint::PartialEq; /// Constraint System Type - type Compiler: ConstraintSystem; + type Compiler: AssertEq; /// Proof System Type - type ProofSystem: ProofSystem + type ProofSystem: ProofSystem + ProofSystemInput + ProofSystemInput + ProofSystemInput> @@ -420,7 +392,7 @@ where pub fn derive(&self, secret_key: &SecretKey) -> PublicKey { self.note_encryption_scheme .key_agreement_scheme() - .derive(secret_key) + .derive(secret_key, &mut ()) } /// Derives a [`PublicKey`] from an owned `secret_key`. @@ -428,7 +400,7 @@ where pub fn derive_owned(&self, secret_key: SecretKey) -> PublicKey { self.note_encryption_scheme .key_agreement_scheme() - .derive_owned(secret_key) + .derive_owned(secret_key, &mut ()) } /// Computes the [`Utxo`] associated to `ephemeral_secret_key`, `public_spend_key`, and `asset`. @@ -440,13 +412,14 @@ where asset: &Asset, ) -> Utxo { self.utxo_commitment - .commit(ephemeral_secret_key, public_spend_key, asset) + .commit(ephemeral_secret_key, public_spend_key, asset, &mut ()) } /// Computes the [`VoidNumber`] associated to `secret_spend_key` and `utxo`. #[inline] pub fn void_number(&self, secret_spend_key: &SecretKey, utxo: &Utxo) -> VoidNumber { - self.void_number_commitment.commit(secret_spend_key, utxo) + self.void_number_commitment + .commit(secret_spend_key, utxo, &mut ()) } /// Validates the `utxo` against the `secret_spend_key` and the given `ephemeral_secret_key` @@ -542,14 +515,14 @@ impl<'p, C> FullParametersVar<'p, C> where C: Configuration, { - /// Derives a [`PublicKeyVar`] from `secret_key` inside the `compiler`. + /// Derives a [`PublicKeyVar`] from `secret_key`. #[inline] fn derive(&self, secret_key: &SecretKeyVar, compiler: &mut C::Compiler) -> PublicKeyVar { - self.key_agreement.derive_in(secret_key, compiler) + self.key_agreement.derive(secret_key, compiler) } /// Computes the [`UtxoVar`] associated to `ephemeral_secret_key`, `public_spend_key`, and - /// `asset` inside the `compiler`. + /// `asset`. #[inline] fn utxo( &self, @@ -559,11 +532,10 @@ where compiler: &mut C::Compiler, ) -> UtxoVar { self.utxo_commitment - .commit_in(ephemeral_secret_key, public_spend_key, asset, compiler) + .commit(ephemeral_secret_key, public_spend_key, asset, compiler) } - /// Computes the [`VoidNumberVar`] associated to `secret_spend_key` and `utxo` in the - /// `compiler`. + /// Computes the [`VoidNumberVar`] associated to `secret_spend_key` and `utxo`. #[inline] fn void_number( &self, @@ -572,7 +544,7 @@ where compiler: &mut C::Compiler, ) -> VoidNumberVar { self.void_number_commitment - .commit_in(secret_spend_key, utxo, compiler) + .commit(secret_spend_key, utxo, compiler) } } @@ -626,8 +598,8 @@ where #[inline] pub fn derive(&self, parameters: &C::KeyAgreementScheme) -> ReceivingKey { ReceivingKey { - spend: parameters.derive(&self.spend), - view: parameters.derive(&self.view), + spend: parameters.derive(&self.spend, &mut ()), + view: parameters.derive(&self.view, &mut ()), } } @@ -999,7 +971,7 @@ impl SenderVar where C: Configuration, { - /// Returns the asset for `self`, checking if `self` is well-formed in the given `compiler`. + /// Returns the asset for `self`, checking if `self` is well-formed. #[inline] pub fn get_well_formed_asset( self, @@ -1447,8 +1419,7 @@ impl ReceiverVar where C: Configuration, { - /// Returns the asset for `self`, checking if `self` is well-formed in the given constraint - /// system `compiler`. + /// Returns the asset for `self`, checking if `self` is well-formed. #[inline] pub fn get_well_formed_asset( self, @@ -1818,7 +1789,7 @@ where /// Builds a constraint system which asserts constraints against unknown variables. #[inline] pub fn unknown_constraints(parameters: FullParameters) -> C::Compiler { - let mut compiler = C::ProofSystem::for_unknown(); + let mut compiler = C::ProofSystem::context_compiler(); TransferVar::::new_unknown(&mut compiler) .build_validity_constraints(¶meters.as_constant(&mut compiler), &mut compiler); compiler @@ -1827,7 +1798,7 @@ where /// Builds a constraint system which asserts constraints against known variables. #[inline] pub fn known_constraints(&self, parameters: FullParameters) -> C::Compiler { - let mut compiler = C::ProofSystem::for_known(); + let mut compiler = C::ProofSystem::proof_compiler(); let transfer: TransferVar = self.as_known(&mut compiler); transfer.build_validity_constraints(¶meters.as_constant(&mut compiler), &mut compiler); @@ -1844,7 +1815,7 @@ where where R: CryptoRng + RngCore + ?Sized, { - C::ProofSystem::generate_context( + C::ProofSystem::compile( public_parameters, Self::unknown_constraints(parameters), rng, @@ -1951,7 +1922,7 @@ where } } - /// Computes the sum of the asset values over `iter` inside of `compiler`. + /// Computes the sum of the asset values over `iter`. #[inline] fn value_sum(iter: I, compiler: &mut C::Compiler) -> C::AssetValueVar where diff --git a/manta-benchmark/Cargo.toml b/manta-benchmark/Cargo.toml index 2b026ce87..95e3bf54e 100644 --- a/manta-benchmark/Cargo.toml +++ b/manta-benchmark/Cargo.toml @@ -40,7 +40,7 @@ name = "reclaim" harness = false [dependencies] -getrandom = { version = "0.2.6", features = ["js"]} +getrandom = { version = "0.2.6", features = ["js"] } instant = { version = "0.1.12", features = [ "wasm-bindgen" ] } manta-accounting = { path = "../manta-accounting", default-features = false, features = ["test"] } manta-crypto = { path = "../manta-crypto", default-features = false, features = ["getrandom", "test"] } diff --git a/manta-crypto/src/accumulator.rs b/manta-crypto/src/accumulator.rs index c7fe9fcd3..97d66cc70 100644 --- a/manta-crypto/src/accumulator.rs +++ b/manta-crypto/src/accumulator.rs @@ -16,8 +16,6 @@ //! Dynamic Cryptographic Accumulators -use crate::constraint::{ConstraintSystem, Native}; - /// Accumulator Membership Model pub trait Model { /// Item Type @@ -34,46 +32,36 @@ pub trait Model { /// Typically this is either [`bool`], a [`Result`] type, or a circuit boolean variable. type Verification; - /// Verifies that `item` is stored in a known accumulator with accumulated `output` and - /// membership `witness` inside the given `compiler`. - fn verify_in( - &self, - item: &Self::Item, - witness: &Self::Witness, - output: &Self::Output, - compiler: &mut COM, - ) -> Self::Verification; - /// Verifies that `item` is stored in a known accumulator with accumulated `output` and /// membership `witness`. - #[inline] fn verify( &self, item: &Self::Item, witness: &Self::Witness, output: &Self::Output, - ) -> Self::Verification - where - COM: Native, - { - self.verify_in(item, witness, output, &mut COM::compiler()) - } + compiler: &mut COM, + ) -> Self::Verification; +} - /// Asserts that the verification of the storage of `item` in the known accumulator is valid - /// inside the `compiler`. - #[inline] +/// Accumulator Membership Model Validity Assertion +/// +/// For situations where we just want to assert validity of the membership proof, we can use this +/// trait as an optimization path for [`Model::verify`]. See [`assert_valid`](Self::assert_valid) +/// for more details. +pub trait AssertValidVerification: Model { + /// Asserts that the verification of the storage of `item` in the known accumulator is valid. + /// + /// # Optimization + /// + /// In compilers where assertions for more complex statements other than booleans being `true`, + /// this function can provide an optimization path to reduce the cost of assertion. fn assert_valid( &self, item: &Self::Item, witness: &Self::Witness, output: &Self::Output, compiler: &mut COM, - ) where - COM: ConstraintSystem, - { - let is_valid_proof = self.verify_in(item, witness, output, compiler); - compiler.assert(is_valid_proof) - } + ); } /// Accumulator Output Type @@ -233,27 +221,23 @@ where self.output } - /// Verifies that `item` is stored in a known accumulator using `model` inside the `compiler`. + /// Returns a reference to the accumulated output part of `self`. #[inline] - pub fn verify_in(&self, model: &M, item: &M::Item, compiler: &mut COM) -> M::Verification { - model.verify_in(item, &self.witness, &self.output, compiler) + pub fn output(&self) -> &M::Output { + &self.output } /// Verifies that `item` is stored in a known accumulator using `model`. #[inline] - pub fn verify(&self, model: &M, item: &M::Item) -> M::Verification - where - COM: Native, - { - model.verify(item, &self.witness, &self.output) + pub fn verify(&self, model: &M, item: &M::Item, compiler: &mut COM) -> M::Verification { + model.verify(item, &self.witness, &self.output, compiler) } - /// Asserts that the verification of the storage of `item` in the known accumulator is valid - /// inside the `compiler`. + /// Asserts that the verification of the storage of `item` in the known accumulator is valid. #[inline] pub fn assert_valid(&self, model: &M, item: &M::Item, compiler: &mut COM) where - COM: ConstraintSystem, + M: AssertValidVerification, { model.assert_valid(item, &self.witness, &self.output, compiler) } @@ -262,7 +246,7 @@ where /// Constraint System Gadgets pub mod constraint { use super::*; - use crate::constraint::{Allocator, Constant, Derived, ValueSource, Variable}; + use crate::constraint::{Allocate, Allocator, Constant, Derived, Variable}; use core::marker::PhantomData; /// Membership Proof Allocation Mode Entry @@ -350,7 +334,7 @@ pub mod test { ); if let Some(proof) = accumulator.prove(item) { assert!( - proof.verify(accumulator.model(), item), + proof.verify(accumulator.model(), item, &mut ()), "Invalid proof returned for inserted item." ); proof.into_output() diff --git a/manta-crypto/src/commitment.rs b/manta-crypto/src/commitment.rs index 8bfdba944..ba352691b 100644 --- a/manta-crypto/src/commitment.rs +++ b/manta-crypto/src/commitment.rs @@ -16,8 +16,6 @@ //! Commitment Schemes -use crate::constraint::Native; - /// Commitment Scheme pub trait CommitmentScheme { /// Randomness Type @@ -29,20 +27,11 @@ pub trait CommitmentScheme { /// Output Type type Output; - /// Commits to the `input` value using `randomness` inside the `compiler`. - fn commit_in( + /// Commits to the `input` value using `randomness`. + fn commit( &self, randomness: &Self::Randomness, input: &Self::Input, compiler: &mut COM, ) -> Self::Output; - - /// Commits to the `input` value using `randomness` - #[inline] - fn commit(&self, randomness: &Self::Randomness, input: &Self::Input) -> Self::Output - where - COM: Native, - { - self.commit_in(randomness, input, &mut COM::compiler()) - } } diff --git a/manta-crypto/src/constraint.rs b/manta-crypto/src/constraint.rs index f026d5059..ee14f5196 100644 --- a/manta-crypto/src/constraint.rs +++ b/manta-crypto/src/constraint.rs @@ -23,451 +23,22 @@ // vector by the wrong amount or in the wrong order. use crate::rand::{CryptoRng, RngCore}; -use core::{fmt::Debug, hash::Hash, marker::PhantomData, ops}; -use manta_util::{create_seal, seal}; -create_seal! {} - -/// Generic Derived Allocation Mode -#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct Derived; - -/// Public Allocation Mode -#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct Public; - -impl From for Public { - #[inline] - fn from(d: Derived) -> Self { - let _ = d; - Self - } -} - -/// Secret Allocation Mode -#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct Secret; - -impl From for Secret { - #[inline] - fn from(d: Derived) -> Self { - let _ = d; - Self - } -} - -/// Constant Type Alias -pub type Const = >::Type; - -/// Compiler Constant -pub trait Constant -where - COM: ?Sized, -{ - /// Underlying Type - type Type; - - /// Allocates a new constant from `this` into the `compiler`. - fn new_constant(this: &Self::Type, compiler: &mut COM) -> Self; -} - -impl Constant for () -where - COM: ?Sized, -{ - type Type = (); - - #[inline] - fn new_constant(this: &Self::Type, compiler: &mut COM) -> Self { - let _ = (this, compiler); - } -} - -impl Constant for PhantomData -where - COM: ?Sized, -{ - type Type = PhantomData; - - #[inline] - fn new_constant(this: &Self::Type, compiler: &mut COM) -> Self { - let _ = (this, compiler); - PhantomData - } -} - -/// Variable Type Alias -pub type Var = >::Type; - -/// Compiler Variable -pub trait Variable -where - COM: ?Sized, -{ - /// Underlying Type - type Type; - - /// Allocates a new known value from `this` into the `compiler`. - fn new_known(this: &Self::Type, compiler: &mut COM) -> Self; - - /// Allocates a new unknown value into the `compiler`. - fn new_unknown(compiler: &mut COM) -> Self; -} - -impl Variable for () -where - COM: ?Sized, -{ - type Type = (); - - #[inline] - fn new_known(this: &Self::Type, compiler: &mut COM) -> Self { - let _ = (this, compiler); - } - - #[inline] - fn new_unknown(compiler: &mut COM) -> Self { - let _ = compiler; - } -} - -impl Variable for PhantomData -where - COM: ?Sized, -{ - type Type = PhantomData; - - #[inline] - fn new_known(this: &Self::Type, compiler: &mut COM) -> Self { - let _ = (this, compiler); - PhantomData - } - - #[inline] - fn new_unknown(compiler: &mut COM) -> Self { - let _ = compiler; - PhantomData - } -} - -/// Value Source Auto-Trait -pub trait ValueSource -where - COM: ?Sized, -{ - /// Allocates `self` as a constant in `compiler`. - #[inline] - fn as_constant(&self, compiler: &mut COM) -> C - where - C: Constant, - { - C::new_constant(self, compiler) - } - - /// Allocates `self` as a known value in `compiler`. - #[inline] - fn as_known(&self, compiler: &mut COM) -> V - where - V: Variable, - { - V::new_known(self, compiler) - } - - /// Allocates an unknown value of type `Self` into `compiler`. - #[inline] - fn as_unknown(compiler: &mut COM) -> V - where - V: Variable, - { - V::new_unknown(compiler) - } -} - -impl ValueSource for T where T: ?Sized {} - -/// Allocator Auto-Trait -pub trait Allocator { - /// Allocates a constant with the given `value` into `self`. - #[inline] - fn allocate_constant(&mut self, value: &C::Type) -> C - where - C: Constant, - { - C::new_constant(value, self) - } - - /// Allocates a known variable with the given `value` into `self`. - #[inline] - fn allocate_known(&mut self, value: &V::Type) -> V - where - V: Variable, - { - V::new_known(value, self) - } - - /// Allocates an unknown variable into `self`. - #[inline] - fn allocate_unknown(&mut self) -> V - where - V: Variable, - { - V::new_unknown(self) - } -} - -impl Allocator for COM where COM: ?Sized {} - -/// Native Compiler Marker Trait -/// -/// This trait is only implemented for `()`, the only native compiler. -pub trait Native: sealed::Sealed { - /// Returns the native compiler. - fn compiler() -> Self; -} - -seal! { () } - -impl Native for () { - #[inline] - fn compiler() -> Self {} -} - -/// Constraint System -pub trait ConstraintSystem { - /// Boolean Variable Type - type Bool; - - /// Asserts that `b == 1`. - fn assert(&mut self, b: Self::Bool); - - /// Asserts that all the booleans in `iter` are equal to `1`. - #[inline] - fn assert_all(&mut self, iter: I) - where - I: IntoIterator, - { - iter.into_iter().for_each(move |b| self.assert(b)); - } - - /// Generates a boolean that represents the fact that `lhs` and `rhs` may be equal. - #[inline] - fn eq(&mut self, lhs: &V, rhs: &V) -> Self::Bool - where - V: Equal, - { - V::eq(lhs, rhs, self) - } - - /// Asserts that `lhs` and `rhs` are equal. - #[inline] - fn assert_eq(&mut self, lhs: &V, rhs: &V) - where - V: Equal, - { - V::assert_eq(lhs, rhs, self); - } - - /// Asserts that all the elements in `iter` are equal to some `base` element. - #[inline] - fn assert_all_eq_to_base<'t, V, I>(&mut self, base: &'t V, iter: I) - where - V: 't + Equal, - I: IntoIterator, - { - V::assert_all_eq_to_base(base, iter, self); - } - - /// Asserts that all the elements in `iter` are equal. - #[inline] - fn assert_all_eq<'t, V, I>(&mut self, iter: I) - where - V: 't + Equal, - I: IntoIterator, - { - V::assert_all_eq(iter, self); - } - - /// Selects `true_value` when `bit == 1` and `false_value` when `bit == 0`. - #[inline] - fn conditional_select(&mut self, bit: &Self::Bool, true_value: &V, false_value: &V) -> V - where - V: ConditionalSelect, - { - V::select(bit, true_value, false_value, self) - } - - /// Swaps `lhs` and `rhs` if `bit == 1`. - #[inline] - fn conditional_swap(&mut self, bit: &Self::Bool, lhs: &V, rhs: &V) -> (V, V) - where - V: ConditionalSelect, - { - V::swap(bit, lhs, rhs, self) - } - - /// Swaps `lhs` and `rhs` in-place if `bit == 1`. - #[inline] - fn conditional_swap_in_place(&mut self, bit: &Self::Bool, lhs: &mut V, rhs: &mut V) - where - V: ConditionalSelect, - { - V::swap_in_place(bit, lhs, rhs, self) - } -} - -/* TODO: Can we safely implement this? -impl ConstraintSystem for () { - type Bool = bool; - - #[inline] - fn assert(&mut self, b: Self::Bool) { - assert!(b, "Native Constraint System Assertion"); - } -} -*/ - -/// Equality Trait -pub trait Equal -where - COM: ConstraintSystem + ?Sized, -{ - /// Generates a boolean that represents the fact that `lhs` and `rhs` may be equal. - fn eq(lhs: &Self, rhs: &Self, compiler: &mut COM) -> COM::Bool; - - /// Asserts that `lhs` and `rhs` are equal. - #[inline] - fn assert_eq(lhs: &Self, rhs: &Self, compiler: &mut COM) { - let boolean = Self::eq(lhs, rhs, compiler); - compiler.assert(boolean); - } - - /// Asserts that all the elements in `iter` are equal to some `base` element. - #[inline] - fn assert_all_eq_to_base<'t, I>(base: &'t Self, iter: I, compiler: &mut COM) - where - I: IntoIterator, - { - for item in iter { - Self::assert_eq(base, item, compiler); - } - } - - /// Asserts that all the elements in `iter` are equal. - #[inline] - fn assert_all_eq<'t, I>(iter: I, compiler: &mut COM) - where - Self: 't, - I: IntoIterator, - { - let mut iter = iter.into_iter(); - if let Some(base) = iter.next() { - Self::assert_all_eq_to_base(base, iter, compiler); - } - } -} - -/* TODO: Implement this: -impl Equal<()> for T -where - T: PartialEq, -{ - #[inline] - fn eq(lhs: &Self, rhs: &Self, _: &mut ()) -> bool { - lhs.eq(rhs) - } -} -*/ - -/// Conditional Selection -pub trait ConditionalSelect -where - COM: ConstraintSystem + ?Sized, -{ - /// Selects `true_value` when `bit == 1` and `false_value` when `bit == 0`. - fn select(bit: &COM::Bool, true_value: &Self, false_value: &Self, compiler: &mut COM) -> Self; - - /// Swaps `lhs` and `rhs` if `bit == 1`. - #[inline] - fn swap(bit: &COM::Bool, lhs: &Self, rhs: &Self, compiler: &mut COM) -> (Self, Self) - where - Self: Sized, - { - ( - Self::select(bit, rhs, lhs, compiler), - Self::select(bit, lhs, rhs, compiler), - ) - } - - /// Swaps `lhs` and `rhs` in-place if `bit == 1`. - #[inline] - fn swap_in_place(bit: &COM::Bool, lhs: &mut Self, rhs: &mut Self, compiler: &mut COM) - where - Self: Sized, - { - let (swapped_lhs, swapped_rhs) = Self::swap(bit, lhs, rhs, compiler); - *lhs = swapped_lhs; - *rhs = swapped_rhs; - } -} - -/* TODO: Implement this: -impl ConditionalSelect<()> for T -where - T: Clone, -{ - #[inline] - fn select(bit: &bool, true_value: &Self, false_value: &Self, _: &mut ()) -> Self { - if bit { - true_value - } else { - false_value - } - } -} -*/ - -/// Addition -pub trait Add -where - COM: ?Sized, -{ - /// Adds `lhs` and `rhs` inside of `compiler`. - fn add(lhs: Self, rhs: Self, compiler: &mut COM) -> Self; -} - -impl Add<()> for T -where - T: ops::Add, -{ - #[inline] - fn add(lhs: Self, rhs: Self, _: &mut ()) -> Self { - lhs.add(rhs) - } -} - -/// Subtraction -pub trait Sub -where - COM: ?Sized, -{ - /// Subtracts `rhs` from `lhs` inside of `compiler`. - fn sub(lhs: Self, rhs: Self, compiler: &mut COM) -> Self; -} - -impl Sub<()> for T -where - T: ops::Sub, -{ - #[inline] - fn sub(lhs: Self, rhs: Self, _: &mut ()) -> Self { - lhs.sub(rhs) - } -} +pub use crate::eclair::{ + alloc::{ + mode::{self, Derived, Public, Secret}, + Allocate, Allocator, Const, Constant, Var, Variable, + }, + bool::{Assert, AssertEq, Bool, ConditionalSelect, ConditionalSwap}, + cmp::{Eq, PartialEq}, + ops::{Add, Not, Sub}, + Has, Native, +}; /// Proof System pub trait ProofSystem { - /// Constraint System - type ConstraintSystem: ConstraintSystem; + /// Context Compiler + type Compiler; /// Public Parameters Type type PublicParameters; @@ -487,27 +58,29 @@ pub trait ProofSystem { /// Error Type type Error; - /// Returns a constraint system which is setup to build proving and verifying contexts. + /// Returns a compiler which is setup to build proving and verifying contexts. #[must_use] - fn for_unknown() -> Self::ConstraintSystem; + fn context_compiler() -> Self::Compiler; - /// Returns a constraint system which is setup to build a proof. + /// Returns a compiler which is setup to build a proof. #[must_use] - fn for_known() -> Self::ConstraintSystem; + fn proof_compiler() -> Self::Compiler; - /// Returns proving and verifying contexts for the constraints contained in `compiler`. - fn generate_context( + /// Returns proving and verifying contexts for the constraints contained in `compiler` using + /// `public_parameters`. + fn compile( public_parameters: &Self::PublicParameters, - compiler: Self::ConstraintSystem, + compiler: Self::Compiler, rng: &mut R, ) -> Result<(Self::ProvingContext, Self::VerifyingContext), Self::Error> where R: CryptoRng + RngCore + ?Sized; - /// Returns a proof that the constraint system `compiler` is consistent. + /// Returns a proof that the constraint system encoded in `compiler` is consistent with the + /// proving `context`. fn prove( context: &Self::ProvingContext, - compiler: Self::ConstraintSystem, + compiler: Self::Compiler, rng: &mut R, ) -> Result where @@ -532,47 +105,39 @@ where /// Constraint System Measurement pub mod measure { - use super::*; - use alloc::{format, string::String, vec::Vec}; + use super::mode::{Constant, Public, Secret}; + use alloc::{fmt::Display, format, string::String, vec::Vec}; use core::{ - fmt::Display, + fmt::Debug, + hash::Hash, ops::{Add, AddAssign, Deref, DerefMut}, }; #[cfg(feature = "serde")] use manta_util::serde::{Deserialize, Serialize}; - /// Constraint System Measurement - pub trait Measure { - /// Returns the number of constraints stored in `self`. - fn constraint_count(&self) -> usize; - - /// Returns the number of allocated constants. - #[inline] - fn constant_count(&self) -> Option { - None - } - - /// Returns the number of allocated public variables. + /// Variable Counting + pub trait Count { + /// Returns the number of variables of the given mode `M` stored in `self`. #[inline] - fn public_variable_count(&self) -> Option { + fn count(&self) -> Option { None } + } - /// Returns the number of allocated secret variables. - #[inline] - fn secret_variable_count(&self) -> Option { - None - } + /// Constraint System Measurement + pub trait Measure: Count + Count + Count { + /// Returns the number of constraints stored in `self`. + fn constraint_count(&self) -> usize; /// Returns a [`Size`] with the number of constraints and variables of each kind. #[inline] fn measure(&self) -> Size { Size { constraint_count: self.constraint_count(), - constant_count: self.constant_count(), - public_variable_count: self.public_variable_count(), - secret_variable_count: self.secret_variable_count(), + constant_count: Count::::count(self), + public_variable_count: Count::::count(self), + secret_variable_count: Count::::count(self), } } diff --git a/manta-crypto/src/ecc.rs b/manta-crypto/src/ecc.rs index eb39eca14..30badd2c6 100644 --- a/manta-crypto/src/ecc.rs +++ b/manta-crypto/src/ecc.rs @@ -329,7 +329,7 @@ where type Output = G::Output; #[inline] - fn derive_in(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { + fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { self.generator.scalar_mul(key, compiler) } } @@ -344,7 +344,7 @@ where type SharedSecret = G::Output; #[inline] - fn agree_in( + fn agree( &self, secret_key: &Self::SecretKey, public_key: &Self::PublicKey, diff --git a/manta-crypto/src/eclair/alloc.rs b/manta-crypto/src/eclair/alloc.rs new file mode 100644 index 000000000..eab8bf848 --- /dev/null +++ b/manta-crypto/src/eclair/alloc.rs @@ -0,0 +1,305 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! Compiler Allocation +//! +//! When building programs, we may need to transfer values across compilers, say from a native +//! compiler into a circuit-building compiler. This lifting of values into another compiler is known +//! as "allocation". The two `trait`s responsible for this allocation scheme are [`Constant`] and +//! [`Variable`]. See their documentation for more. +//! +//! # Note on Terminology +//! +//! Allocation does not necessarily refer to allocation of memory nor the simulation of memory-based +//! abstractions inside of compilers, like heap allocation. Allocation only refers to lifting +//! constants and variables from one compiler to another. + +use core::marker::PhantomData; + +/// Constant Type Alias +pub type Const = >::Type; + +/// Compiler Constant +/// +/// A compiler [`Constant`] is a kind of allocated value that **must** be known at +/// _compilation time_. In this case, we take an explicit value of the underlying type and directly +/// return an allocated value in the `COM` compiler. Contrast this with [`Variable`] types whose +/// values are not known at _compilation time_ and are only known at _execution time_. +pub trait Constant +where + COM: ?Sized, +{ + /// Underlying Type + type Type; + + /// Allocates a new constant from `this` into the `compiler`. + fn new_constant(this: &Self::Type, compiler: &mut COM) -> Self; +} + +impl Constant for () +where + COM: ?Sized, +{ + type Type = (); + + #[inline] + fn new_constant(this: &Self::Type, compiler: &mut COM) -> Self { + let _ = (this, compiler); + } +} + +impl Constant for PhantomData +where + COM: ?Sized, +{ + type Type = PhantomData; + + #[inline] + fn new_constant(this: &Self::Type, compiler: &mut COM) -> Self { + let _ = (this, compiler); + PhantomData + } +} + +/// Variable Type Alias +pub type Var = >::Type; + +/// Compiler Variable +/// +/// A compiler [`Variable`] is a kind of allocated value that **cannot** have a known value at +/// _compilation time_ but _does_ have one at _execution time_. In this case, we require two +/// allocation methods [`new_unknown`](Self::new_unknown) and [`new_known`](Self::new_known) in +/// order to use the variables in `COM` during both the compilation and execution phases. Contrast +/// this with [`Constant`] types whose values must be known at _compilation time_. +/// +/// # Allocation Modes +/// +/// The tag `M` in the type parameters of this trait refers to the [`Variable`]'s allocation mode. +/// See the [`mode`] module for more details on why allocation modes are necessary and useful and +/// how to use them. +pub trait Variable +where + COM: ?Sized, +{ + /// Underlying Type + type Type; + + /// Allocates a new unknown value into the `compiler`. The terminology "unknown" refers to the + /// fact that we need to allocate a slot for this variable during compilation time, but do not + /// yet know its underlying value. + fn new_unknown(compiler: &mut COM) -> Self; + + /// Allocates a new known value from `this` into the `compiler`. The terminology "known" refers + /// to the fact that we have access to the underyling value during execution time where we are + /// able to use its concrete value for execution. + fn new_known(this: &Self::Type, compiler: &mut COM) -> Self; +} + +impl Variable for () +where + COM: ?Sized, +{ + type Type = (); + + #[inline] + fn new_unknown(compiler: &mut COM) -> Self { + let _ = compiler; + } + + #[inline] + fn new_known(this: &Self::Type, compiler: &mut COM) -> Self { + let _ = (this, compiler); + } +} + +impl Variable for PhantomData +where + COM: ?Sized, +{ + type Type = PhantomData; + + #[inline] + fn new_unknown(compiler: &mut COM) -> Self { + let _ = compiler; + PhantomData + } + + #[inline] + fn new_known(this: &Self::Type, compiler: &mut COM) -> Self { + let _ = (this, compiler); + PhantomData + } +} + +/// Allocation Auto-`trait` +/// +/// Allocation schemes are built up from the individual variables which can be allocated into a +/// given compiler. This `trait` is automatically implemented to give allocate-able values access to +/// generic methods that perform allocation into any compiler whenever the associated allocation +/// scheme allows it. +/// +/// See [`Constant`] and [`Variable`] for more details on including a specific variable in the +/// allocation scheme for a compiler. +pub trait Allocate +where + COM: ?Sized, +{ + /// Allocates `self` as a constant in `compiler`. See [`C::new_constant`] for more. + /// + /// [`C::new_constant`]: Constant::new_constant + #[inline] + fn as_constant(&self, compiler: &mut COM) -> C + where + C: Constant, + { + C::new_constant(self, compiler) + } + + /// Allocates an unknown value of type `Self` into `compiler`. See [`V::new_unknown`] for more. + /// + /// [`V::new_unknown`]: Variable::new_unknown + #[inline] + fn as_unknown(compiler: &mut COM) -> V + where + V: Variable, + { + V::new_unknown(compiler) + } + + /// Allocates `self` as a known value in `compiler`. See [`V::new_known`] for more. + /// + /// [`V::new_known`]: Variable::new_known + #[inline] + fn as_known(&self, compiler: &mut COM) -> V + where + V: Variable, + { + V::new_known(self, compiler) + } +} + +impl Allocate for T where T: ?Sized {} + +/// Allocator Auto-`trait` +/// +/// Allocation schemes are built up from the individual variables which can be allocated into a +/// given compiler. This `trait` is automatically implemented to give compilers access to generic +/// methods that perform allocation over any variables defined over them. +/// +/// See [`Constant`] and [`Variable`] for more details on including a specific variable in the +/// allocation scheme for a compiler. +pub trait Allocator { + /// Allocates a constant with the given `value` into `self`. See [`C::new_constant`] for more. + /// + /// [`C::new_constant`]: Constant::new_constant + #[inline] + fn allocate_constant(&mut self, value: &C::Type) -> C + where + C: Constant, + { + C::new_constant(value, self) + } + + /// Allocates an unknown variable into `self`. See [`V::new_unknown`] for more. + /// + /// [`V::new_unknown`]: Variable::new_unknown + #[inline] + fn allocate_unknown(&mut self) -> V + where + V: Variable, + { + V::new_unknown(self) + } + + /// Allocates a known variable with the given `value` into `self`. See [`V::new_known`] for + /// more. + /// + /// [`V::new_known`]: Variable::new_known + #[inline] + fn allocate_known(&mut self, value: &V::Type) -> V + where + V: Variable, + { + V::new_known(value, self) + } +} + +impl Allocator for COM where COM: ?Sized {} + +/// Allocation Modes for [`Variable`] Types +/// +/// When allocating objects of type [`Variable`], we can attach an explicit mode tag to inform the +/// compiler that the variable will have some custom allocation semantics. Below we define some +/// useful canonical modes [`Derived`], [`Constant`], [`Public`], and [`Secret`]. The latter two +/// modes are most useful for zero-knowledge [`ProofSystem`]-based execution engines where we want +/// to distinguish between _secret witness_ variables and _public input_ variables. +/// +/// [`Derived`]: mode::Derived +/// [`Constant`]: mode::Constant +/// [`Public`]: mode::Public +/// [`Secret`]: mode::Secret +/// [`ProofSystem`]: crate::eclair::execution::ProofSystem +pub mod mode { + /// 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. + #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] + pub struct Derived; + + /// Constant Allocation Mode + /// + /// In some cases, compilers may not be able to adapt under the [`Constant`]-[`Variable`] + /// distinction and may need to use [`Variable`] for all of their allocation. In those cases, + /// 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; + + /// Public Allocation Mode + /// + /// Whenever a variable's underlying value **must** be publicly revealed during execution, it + /// should be marked with this allocation mode. + #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] + pub struct Public; + + impl From for Public { + #[inline] + fn from(d: Derived) -> Self { + let _ = d; + Self + } + } + + /// Secret Allocation Mode + /// + /// Whenever a variable's underlying value **must not** be publicly revealed during execution, + /// it should be marked with this allocation mode. + #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] + pub struct Secret; + + impl From for Secret { + #[inline] + fn from(d: Derived) -> Self { + let _ = d; + Self + } + } +} diff --git a/manta-crypto/src/eclair/bool.rs b/manta-crypto/src/eclair/bool.rs new file mode 100644 index 000000000..f546c1534 --- /dev/null +++ b/manta-crypto/src/eclair/bool.rs @@ -0,0 +1,156 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! Structures over Booleans +//! +//! For many of the standard Rust operations we need access to some simulation of the primitive +//! types. In this module, we define the access interfaces needed to simulate the [`bool`] type with +//! [`Bool`]. + +use crate::eclair::{cmp::PartialEq, Has}; + +/// Boolean Type Inside of the Compiler +pub type Bool = >::Type; + +/// Assertion +pub trait Assert: Has { + /// Asserts that `bit` reduces to `true`. + fn assert(&mut self, bit: &Bool); + + /// Asserts that all the items in the `iter` reduce to `true`. + #[inline] + fn assert_all<'b, I>(&mut self, iter: I) + where + Self: Assert, + Bool: 'b, + I: IntoIterator>, + { + iter.into_iter().for_each(move |b| self.assert(b)); + } +} + +/* 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. + #[inline] + fn assert_eq(&mut self, lhs: &T, rhs: &Rhs) + where + T: PartialEq, + { + let are_equal = lhs.eq(rhs, self); + self.assert(&are_equal); + } + + /// Asserts that all the elements in `iter` are equal to some `base` element. + #[inline] + fn assert_all_eq_to_base<'t, T, Rhs, I>(&mut self, base: &'t T, iter: I) + where + T: PartialEq, + Rhs: 't, + I: IntoIterator, + { + for item in iter { + self.assert_eq(base, item); + } + } + + /// Asserts that all the elements in `iter` are equal. + #[inline] + fn assert_all_eq<'t, T, I>(&mut self, iter: I) + where + T: 't + PartialEq, + I: IntoIterator, + { + let mut iter = iter.into_iter(); + if let Some(base) = iter.next() { + self.assert_all_eq_to_base(base, iter); + } + } +} + +/// Conditional Selection +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) + } +} + +/* 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 +where + COM: Has + ?Sized, +{ + /// Swaps `lhs` and `rhs` whenever `bit == true` and keeps them in the same order when `bit == + /// 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 new file mode 100644 index 000000000..2f3cc3625 --- /dev/null +++ b/manta-crypto/src/eclair/cmp.rs @@ -0,0 +1,66 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! Comparison + +use crate::eclair::{bool::Bool, ops::Not, Has}; + +/// Partial Equivalence Relations +pub trait PartialEq +where + Rhs: ?Sized, + COM: Has + ?Sized, +{ + /// Returns `true` if `self` and `rhs` are equal. + fn eq(&self, rhs: &Rhs, compiler: &mut COM) -> Bool; + + /// Returns `true` if `self` and `rhs` are not equal. + #[inline] + fn ne(&self, other: &Rhs, compiler: &mut COM) -> Bool + where + Bool: Not>, + { + self.eq(other, compiler).not(compiler) + } +} + +/* FIXME: We cannot implement this yet. +impl PartialEq for T +where + T: cmp::PartialEq, +{ + #[inline] + fn eq(&self, rhs: &Rhs, _: &mut ()) -> bool { + self.eq(rhs) + } + + #[inline] + fn ne(&self, rhs: &Rhs, _: &mut ()) -> bool { + self.ne(rhs) + } +} +*/ + +/// Equality +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/execution.rs b/manta-crypto/src/eclair/execution.rs new file mode 100644 index 000000000..72784a11f --- /dev/null +++ b/manta-crypto/src/eclair/execution.rs @@ -0,0 +1,77 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! Execution Engines + +use crate::rand::RngCore; + +/// Execution Engine +pub trait Engine { + /// Engine Output Type + type Output; + + /// Error Type + type Error; + + /// Initializes a compiler that will be used to construct execution information. + fn init(&self) -> COM; + + /// Finalizes the exectution with `compiler` producing [`Output`](Self::Output). + fn finalize(&self, compiler: COM, rng: &mut R) -> Result + where + R: RngCore + ?Sized; +} + +/// Proof System +pub trait ProofSystem { + /// Base Compiler + type Compiler; + + /// Proving Context + type ProvingContext; + + /// Verifying Context + type VerifyingContext; + + /// Context Generation Engine + type ContextEngine: Engine< + Self::Compiler, + Output = (Self::ProvingContext, Self::VerifyingContext), + >; + + /// Proof + type Proof; + + /// Proof Engine + type ProofEngine: Engine; + + /// Public Input + type Input; + + /// Verification Error + type Error; + + /// Verifies that `proof` with `input` is valid with respect to the [`ContextEngine`] and + /// [`ProofEngine`] for this proof system. + /// + /// [`ContextEngine`]: Self::ContextEngine + /// [`ProofEngine`]: Self::ProofEngine + fn verify( + context: &Self::VerifyingContext, + input: &Self::Input, + proof: &Self::Proof, + ) -> Result; +} diff --git a/manta-crypto/src/eclair/mod.rs b/manta-crypto/src/eclair/mod.rs new file mode 100644 index 000000000..d71ac7279 --- /dev/null +++ b/manta-crypto/src/eclair/mod.rs @@ -0,0 +1,59 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! **_ECLAIR_**: Embedded Circuit Language And Intermediate Representation + +use manta_util::{create_seal, seal}; + +pub mod alloc; +pub mod bool; +pub mod cmp; +pub mod execution; +pub mod ops; + +/// Native Compiler Marker Trait +/// +/// This `trait` is only implemented for `()`, the default native compiler. +pub trait Native: sealed::Sealed { + /// Returns an instance of the native compiler. + fn compiler() -> Self; +} + +create_seal! {} +seal! { () } + +impl Native for () { + #[inline] + fn compiler() -> Self {} +} + +/// Compiler Type Introspection +pub trait Has { + /// Compiler Type + /// + /// This type represents the allocation of `T` into `Self` as a compiler. Whenever we need to + /// define absractions that require the compiler to have access to some type internally, we can + /// use this `trait` as a requirement of that abstraction. + /// + /// See the [`bool`](crate::eclair::bool) module for an example of how to use introspection. + type Type; +} + +/* FIXME: We cannot implement this yet. +impl Has for () { + type Type = T; +} +*/ diff --git a/manta-crypto/src/eclair/ops.rs b/manta-crypto/src/eclair/ops.rs new file mode 100644 index 000000000..fcbf9f8af --- /dev/null +++ b/manta-crypto/src/eclair/ops.rs @@ -0,0 +1,146 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! Overloadable Operations + +use core::ops; + +/// Defines a unary operation for compilers based on those defined in [`core::ops`]. +macro_rules! unary_op { + ($op:ident, $name:ident, $doc:expr, $doc_op:expr) => { + #[doc = $doc] + #[doc = " with the `"] + #[doc = $doc_op] + #[doc = "` Operator"] + pub trait $op + where + COM: ?Sized, + { + /// Output Type + #[doc = "The resulting type after applying the `"] + #[doc = $doc_op] + #[doc = "` operator."] + type Output; + + #[doc = "Performs the `"] + #[doc = $doc_op] + #[doc = "self` operation."] + fn $name(self, compiler: &mut COM) -> Self::Output; + } + + impl $op for T + where + T: ops::$op, + { + type Output = T::Output; + + #[inline] + fn $name(self, _: &mut ()) -> Self::Output { + self.$name() + } + } + }; +} + +/// Defines a binary operation for compilers based on those defined in [`core::ops`]. +macro_rules! binary_op { + ($op:ident, $name:ident, $doc:expr, $doc_op:expr) => { + #[doc = $doc] + #[doc = " with the `"] + #[doc = $doc_op] + #[doc = "` Operator"] + pub trait $op + where + COM: ?Sized, + { + #[doc = "The resulting type after applying the `"] + #[doc = $doc_op] + #[doc = "` operator."] + type Output; + + #[doc = "Performs the `self"] + #[doc = $doc_op] + #[doc = " rhs` operation."] + fn $name(self, rhs: Rhs, compiler: &mut COM) -> Self::Output; + } + + impl $op for T + where + T: ops::$op, + { + type Output = T::Output; + + #[inline] + fn $name(self, rhs: Rhs, _: &mut ()) -> Self::Output { + self.$name(rhs) + } + } + }; +} + +/// Defines the assignment variant of a binary operation for compilers based on those defined in +/// [`core::ops`]. +macro_rules! binary_op_assign { + ($op:ident, $name:ident, $doc:expr, $doc_op:expr) => { + #[doc = "Assigned "] + #[doc = $doc] + #[doc = " with the `"] + #[doc = $doc_op] + #[doc = "` Operator"] + pub trait $op + where + COM: ?Sized, + { + #[doc = "Performs the `self"] + #[doc = $doc_op] + #[doc = "rhs` operation."] + fn $name(&mut self, rhs: Rhs, compiler: &mut COM); + } + + impl $op for T + where + T: ops::$op, + { + #[inline] + fn $name(&mut self, rhs: Rhs, _: &mut ()) { + self.$name(rhs) + } + } + }; +} + +unary_op!(Neg, neg, "Negation", r"\-"); +unary_op!(Not, not, "Negation", "!"); +binary_op!(Add, add, "Addition", r"\+"); +binary_op!(BitAnd, bitand, "Bitwise AND", "&"); +binary_op!(BitOr, bitor, "Bitwise OR", "|"); +binary_op!(BitXor, bitxor, "Bitwise XOR", "^"); +binary_op!(Div, div, "Division", "/"); +binary_op!(Mul, mul, "Multiplication", r"\*"); +binary_op!(Rem, rem, "Remainder", "%"); +binary_op!(Shl, shl, "Left Shift", "<<"); +binary_op!(Shr, shr, "Right Shift", ">>"); +binary_op!(Sub, sub, "Subtraction", r"\-"); +binary_op_assign!(AddAssign, add_assign, "Addition", "+="); +binary_op_assign!(BitAndAssign, bitand_assign, "Bitwise AND", "&="); +binary_op_assign!(BitOrAssign, bitor_assign, "Bitwise OR", "|="); +binary_op_assign!(BitXorAssign, bitxor_assign, "Bitwise XOR", "^="); +binary_op_assign!(DivAssign, div_assign, "Division", "/="); +binary_op_assign!(MulAssign, mul_assign, "Multiplication", "*="); +binary_op_assign!(RemAssign, rem_assign, "Remainder", "%="); +binary_op_assign!(ShlAssign, shl_assign, "Left Shift", "<<="); +binary_op_assign!(ShrAssign, shr_assign, "Right Shift", ">>="); +binary_op_assign!(SubAssign, sub_assign, "Subtraction", "-="); diff --git a/manta-crypto/src/encryption/hybrid.rs b/manta-crypto/src/encryption/hybrid.rs index 7208b5fa4..fcea0bd3e 100644 --- a/manta-crypto/src/encryption/hybrid.rs +++ b/manta-crypto/src/encryption/hybrid.rs @@ -59,8 +59,12 @@ pub trait HybridPublicKeyEncryptionScheme: SymmetricKeyEncryptionScheme { secret_key: &SecretKey, public_key: &PublicKey, ) -> SymmetricKey { - self.key_derivation_function() - .derive(&self.key_agreement_scheme().agree(secret_key, public_key)) + self.key_derivation_function().derive( + &self + .key_agreement_scheme() + .agree(secret_key, public_key, &mut ()), + &mut (), + ) } } @@ -286,7 +290,9 @@ where cipher.agree_derive(ephemeral_secret_key, public_key), plaintext, ), - ephemeral_public_key: cipher.key_agreement_scheme().derive(ephemeral_secret_key), + ephemeral_public_key: cipher + .key_agreement_scheme() + .derive(ephemeral_secret_key, &mut ()), } } @@ -441,7 +447,7 @@ pub mod test { let decrypted_message = EncryptedMessage::::new( cipher, ephemeral_secret_key, - &cipher.key_agreement_scheme().derive(secret_key), + &cipher.key_agreement_scheme().derive(secret_key, &mut ()), plaintext.clone(), ) .decrypt(cipher, secret_key) @@ -452,7 +458,9 @@ pub mod test { ); assert_eq!( decrypted_message.ephemeral_public_key, - cipher.key_agreement_scheme().derive(ephemeral_secret_key), + cipher + .key_agreement_scheme() + .derive(ephemeral_secret_key, &mut ()), "Decrypted message should have included the correct ephemeral public key.", ); } diff --git a/manta-crypto/src/hash.rs b/manta-crypto/src/hash.rs index 4f798e8af..78a2ddbc2 100644 --- a/manta-crypto/src/hash.rs +++ b/manta-crypto/src/hash.rs @@ -16,8 +16,6 @@ //! Hash Functions -use crate::constraint::Native; - /// Unary Hash Function pub trait UnaryHashFunction { /// Input Type @@ -26,17 +24,8 @@ pub trait UnaryHashFunction { /// Output Type type Output; - /// Computes the hash over `input` in the given `compiler`. - fn hash_in(&self, input: &Self::Input, compiler: &mut COM) -> Self::Output; - /// Computes the hash over `input`. - #[inline] - fn hash(&self, input: &Self::Input) -> Self::Output - where - COM: Native, - { - self.hash_in(input, &mut COM::compiler()) - } + fn hash(&self, input: &Self::Input, compiler: &mut COM) -> Self::Output; } impl UnaryHashFunction for &H @@ -47,16 +36,8 @@ where type Output = H::Output; #[inline] - fn hash_in(&self, input: &Self::Input, compiler: &mut COM) -> Self::Output { - (*self).hash_in(input, compiler) - } - - #[inline] - fn hash(&self, input: &Self::Input) -> Self::Output - where - COM: Native, - { - (*self).hash(input) + fn hash(&self, input: &Self::Input, compiler: &mut COM) -> Self::Output { + (*self).hash(input, compiler) } } @@ -71,17 +52,8 @@ pub trait BinaryHashFunction { /// Output Type type Output; - /// Computes the hash over `lhs` and `rhs` in the given `compiler`. - fn hash_in(&self, lhs: &Self::Left, rhs: &Self::Right, compiler: &mut COM) -> Self::Output; - /// Computes the hash over `lhs` and `rhs`. - #[inline] - fn hash(&self, lhs: &Self::Left, rhs: &Self::Right) -> Self::Output - where - COM: Native, - { - self.hash_in(lhs, rhs, &mut COM::compiler()) - } + fn hash(&self, lhs: &Self::Left, rhs: &Self::Right, compiler: &mut COM) -> Self::Output; } /// Array Hash Function @@ -92,17 +64,8 @@ pub trait ArrayHashFunction { /// Output Type type Output; - /// Computes the hash over `input` in the given `compiler`. - fn hash_in(&self, input: [&Self::Input; ARITY], compiler: &mut COM) -> Self::Output; - /// Computes the hash over `input`. - #[inline] - fn hash(&self, input: [&Self::Input; ARITY]) -> Self::Output - where - COM: Native, - { - self.hash_in(input, &mut COM::compiler()) - } + fn hash(&self, input: [&Self::Input; ARITY], compiler: &mut COM) -> Self::Output; } /// Array Hashing Utilities @@ -164,16 +127,8 @@ pub mod array { type Output = H::Output; #[inline] - fn hash_in(&self, input: &Self::Input, compiler: &mut COM) -> Self::Output { - self.hasher.hash_in([input], compiler) - } - - #[inline] - fn hash(&self, input: &Self::Input) -> Self::Output - where - COM: Native, - { - self.hasher.hash([input]) + fn hash(&self, input: &Self::Input, compiler: &mut COM) -> Self::Output { + self.hasher.hash([input], compiler) } } } diff --git a/manta-crypto/src/key.rs b/manta-crypto/src/key.rs index 2a3f6b22b..ce605a37a 100644 --- a/manta-crypto/src/key.rs +++ b/manta-crypto/src/key.rs @@ -16,8 +16,6 @@ //! Cryptographic Key Primitives -use crate::constraint::Native; - /// Key Derivation Function pub trait KeyDerivationFunction { /// Input Key Type @@ -26,45 +24,24 @@ pub trait KeyDerivationFunction { /// Output Key Type type Output; - /// Derives a key of type [`Output`](Self::Output) from `key` in `compiler`. - fn derive_in(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output; - /// Derives a key of type [`Output`](Self::Output) from `key`. - #[inline] - fn derive(&self, key: &Self::Key) -> Self::Output - where - COM: Native, - { - self.derive_in(key, &mut COM::compiler()) - } + fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output; - /// Derives a key of type [`Output`](Self::Output) from `key` in `compiler`. + /// Derives a key of type [`Output`](Self::Output) from `key`. /// /// # Implementation Note /// - /// This method is an optimization path for [`derive_in`] when the `key` value is owned, and by - /// default, [`derive_in`] is used as its implementation. This method must return the same value - /// as [`derive_in`] on the same input. - /// - /// [`derive_in`]: Self::derive_in - #[inline] - fn derive_owned_in(&self, key: Self::Key, compiler: &mut COM) -> Self::Output - where - Self::Key: Sized, - { - self.derive_in(&key, compiler) - } - - /// Derives a key of type [`Output`](Self::Output) from `key`. + /// This method is an optimization path for [`derive`] when the `key` value is owned, and by + /// default, [`derive`] is used as its implementation. This method must return the same value + /// as [`derive`] on the same input. /// - /// See [`derive_owned_in`](Self::derive_owned_in) for more. + /// [`derive`]: Self::derive #[inline] - fn derive_owned(&self, key: Self::Key) -> Self::Output + fn derive_owned(&self, key: Self::Key, compiler: &mut COM) -> Self::Output where - COM: Native, Self::Key: Sized, { - self.derive(&key) + self.derive(&key, compiler) } /// Borrows `self` rather than consuming it, returning an implementation of @@ -83,33 +60,16 @@ where type Output = F::Output; #[inline] - fn derive_in(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { - (*self).derive_in(key, compiler) + fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { + (*self).derive(key, compiler) } #[inline] - fn derive(&self, key: &Self::Key) -> Self::Output - where - COM: Native, - { - (*self).derive(key) - } - - #[inline] - fn derive_owned_in(&self, key: Self::Key, compiler: &mut COM) -> Self::Output + fn derive_owned(&self, key: Self::Key, compiler: &mut COM) -> Self::Output where Self::Key: Sized, { - (*self).derive_owned_in(key, compiler) - } - - #[inline] - fn derive_owned(&self, key: Self::Key) -> Self::Output - where - COM: Native, - Self::Key: Sized, - { - (*self).derive_owned(key) + (*self).derive_owned(key, compiler) } } @@ -144,7 +104,7 @@ pub mod kdf { type Output = K; #[inline] - fn derive_in(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { + fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { let _ = compiler; key.clone() } @@ -229,9 +189,8 @@ pub mod kdf { type Output = F::Output; #[inline] - fn derive_in(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { - self.key_derivation_function - .derive_in(key.as_ref(), compiler) + fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { + self.key_derivation_function.derive(key.as_ref(), compiler) } } @@ -334,9 +293,9 @@ pub mod kdf { type Output = F::Output; #[inline] - fn derive_in(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { + fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { self.key_derivation_function - .derive_in(&key.as_bytes(), compiler) + .derive(&key.as_bytes(), compiler) } } @@ -382,9 +341,8 @@ pub trait KeyAgreementScheme: /// Shared Secret Type type SharedSecret; - /// Computes the shared secret given the known `secret_key` and the given `public_key` in the - /// given `compiler`. - fn agree_in( + /// Computes the shared secret given the known `secret_key` and the given `public_key`. + fn agree( &self, secret_key: &Self::SecretKey, public_key: &Self::PublicKey, @@ -392,51 +350,22 @@ pub trait KeyAgreementScheme: ) -> Self::SharedSecret; /// Computes the shared secret given the known `secret_key` and the given `public_key`. - #[inline] - fn agree( - &self, - secret_key: &Self::SecretKey, - public_key: &Self::PublicKey, - ) -> Self::SharedSecret - where - COM: Native, - { - self.agree_in(secret_key, public_key, &mut COM::compiler()) - } - - /// Computes the shared secret given the known `secret_key` and the given `public_key` in the - /// given `compiler`. /// /// # Implementation Note /// - /// This method is an optimization path for [`agree_in`] when the `secret_key` value and - /// `public_key` value are owned, and by default, [`agree_in`] is used as its implementation. - /// This method must return the same value as [`agree_in`] on the same input. + /// This method is an optimization path for [`agree`] when the `secret_key` value and + /// `public_key` value are owned, and by default, [`agree`] is used as its implementation. This + /// method must return the same value as [`agree`] on the same input. /// - /// [`agree_in`]: Self::agree_in + /// [`agree`]: Self::agree #[inline] - fn agree_owned_in( + fn agree_owned( &self, secret_key: Self::SecretKey, public_key: Self::PublicKey, compiler: &mut COM, ) -> Self::SharedSecret { - self.agree_in(&secret_key, &public_key, compiler) - } - - /// Computes the shared secret given the known `secret_key` and the given `public_key`. - /// - /// See [`agree_owned_in`](Self::agree_owned_in) for more. - #[inline] - fn agree_owned( - &self, - secret_key: Self::SecretKey, - public_key: Self::PublicKey, - ) -> Self::SharedSecret - where - COM: Native, - { - self.agree(&secret_key, &public_key) + self.agree(&secret_key, &public_key, compiler) } /// Borrows `self` rather than consuming it, returning an implementation of @@ -455,36 +384,14 @@ where type PublicKey = K::PublicKey; type SharedSecret = K::SharedSecret; - #[inline] - fn agree_in( - &self, - secret_key: &Self::SecretKey, - public_key: &Self::PublicKey, - compiler: &mut COM, - ) -> Self::SharedSecret { - (*self).agree_in(secret_key, public_key, compiler) - } - #[inline] fn agree( &self, secret_key: &Self::SecretKey, public_key: &Self::PublicKey, - ) -> Self::SharedSecret - where - COM: Native, - { - (*self).agree(secret_key, public_key) - } - - #[inline] - fn agree_owned_in( - &self, - secret_key: Self::SecretKey, - public_key: Self::PublicKey, compiler: &mut COM, ) -> Self::SharedSecret { - (*self).agree_owned_in(secret_key, public_key, compiler) + (*self).agree(secret_key, public_key, compiler) } #[inline] @@ -492,11 +399,9 @@ where &self, secret_key: Self::SecretKey, public_key: Self::PublicKey, - ) -> Self::SharedSecret - where - COM: Native, - { - (*self).agree_owned(secret_key, public_key) + compiler: &mut COM, + ) -> Self::SharedSecret { + (*self).agree_owned(secret_key, public_key, compiler) } } @@ -515,8 +420,8 @@ pub mod test { K::SharedSecret: Debug + PartialEq, { assert_eq!( - scheme.agree(lhs, &scheme.derive(rhs)), - scheme.agree(rhs, &scheme.derive(lhs)), + scheme.agree(lhs, &scheme.derive(rhs, &mut ()), &mut ()), + scheme.agree(rhs, &scheme.derive(lhs, &mut ()), &mut ()), "Key agreement schemes should satisfy the agreement property." ) } diff --git a/manta-crypto/src/lib.rs b/manta-crypto/src/lib.rs index 46f0a812a..cfc84fa3d 100644 --- a/manta-crypto/src/lib.rs +++ b/manta-crypto/src/lib.rs @@ -27,6 +27,7 @@ pub mod accumulator; pub mod commitment; pub mod constraint; pub mod ecc; +pub mod eclair; pub mod encryption; pub mod hash; pub mod key; diff --git a/manta-crypto/src/merkle_tree/forest.rs b/manta-crypto/src/merkle_tree/forest.rs index da72286a9..de2d946b5 100644 --- a/manta-crypto/src/merkle_tree/forest.rs +++ b/manta-crypto/src/merkle_tree/forest.rs @@ -170,7 +170,7 @@ where C: Configuration + ?Sized, F: ConstantWidthForest, { - F::WIDTH * tree::capacity::() + F::WIDTH * tree::capacity::() } /// Merkle Forest diff --git a/manta-crypto/src/merkle_tree/fork.rs b/manta-crypto/src/merkle_tree/fork.rs index cbed72161..9adc3d7e3 100644 --- a/manta-crypto/src/merkle_tree/fork.rs +++ b/manta-crypto/src/merkle_tree/fork.rs @@ -295,7 +295,7 @@ where LeafDigest: Clone + Default, InnerDigest: Default, { - if leaf_digests.len() + base.len() >= capacity::() { + if leaf_digests.len() + base.len() >= capacity::() { return None; } Some(Self::new_unchecked(parameters, base, leaf_digests)) @@ -395,7 +395,7 @@ where LeafDigest: Clone + Default, InnerDigest: Default, { - if self.data.len() + base.len() - (self.base_contribution as usize) >= capacity::() { + if self.data.len() + base.len() - (self.base_contribution as usize) >= capacity::() { return false; } let new_branch = Self::new_unchecked( diff --git a/manta-crypto/src/merkle_tree/full.rs b/manta-crypto/src/merkle_tree/full.rs index 63c27b2d1..97ee30d85 100644 --- a/manta-crypto/src/merkle_tree/full.rs +++ b/manta-crypto/src/merkle_tree/full.rs @@ -203,7 +203,7 @@ where F: FnOnce() -> Option>, { let len = self.len(); - if len >= capacity::() { + if len >= capacity::() { return Some(false); } self.push_leaf_digest(parameters, Node(len), leaf_digest()?); diff --git a/manta-crypto/src/merkle_tree/inner_tree.rs b/manta-crypto/src/merkle_tree/inner_tree.rs index aa37001a9..35b7004d9 100644 --- a/manta-crypto/src/merkle_tree/inner_tree.rs +++ b/manta-crypto/src/merkle_tree/inner_tree.rs @@ -62,7 +62,7 @@ impl InnerNode { where C: Configuration + ?Sized, { - Self::new(path_length::(), leaf_index).parent() + Self::new(path_length::(), leaf_index).parent() } /// Returns the [`Parity`] of this inner node. diff --git a/manta-crypto/src/merkle_tree/node.rs b/manta-crypto/src/merkle_tree/node.rs index 55bede1f0..a511744e1 100644 --- a/manta-crypto/src/merkle_tree/node.rs +++ b/manta-crypto/src/merkle_tree/node.rs @@ -126,7 +126,7 @@ impl Parity { C: HashConfiguration + ?Sized, { let (lhs, rhs) = self.order(lhs, rhs); - C::InnerHash::join(¶meters.inner, lhs, rhs) + C::InnerHash::join(¶meters.inner, lhs, rhs, &mut ()) } /// Combines two leaf digests into a new inner digest using `parameters`, swapping the order @@ -142,7 +142,7 @@ impl Parity { C: HashConfiguration + ?Sized, { let (lhs, rhs) = self.order(lhs, rhs); - C::InnerHash::join_leaves(¶meters.inner, lhs, rhs) + C::InnerHash::join_leaves(¶meters.inner, lhs, rhs, &mut ()) } } diff --git a/manta-crypto/src/merkle_tree/partial.rs b/manta-crypto/src/merkle_tree/partial.rs index e5791b21f..f9cc34aae 100644 --- a/manta-crypto/src/merkle_tree/partial.rs +++ b/manta-crypto/src/merkle_tree/partial.rs @@ -240,7 +240,7 @@ where LeafDigest: Default, { let len = self.len(); - if len >= capacity::() { + if len >= capacity::() { return false; } self.push_leaf_digest(parameters, Node(len), parameters.digest(leaf)); @@ -260,7 +260,7 @@ where { // TODO: Push without keeping unnecessary proof. let len = self.len(); - if len >= capacity::() { + if len >= capacity::() { return Some(false); } self.push_leaf_digest(parameters, Node(len), leaf_digest()?); diff --git a/manta-crypto/src/merkle_tree/path.rs b/manta-crypto/src/merkle_tree/path.rs index f2714275d..1e6b0ee1e 100644 --- a/manta-crypto/src/merkle_tree/path.rs +++ b/manta-crypto/src/merkle_tree/path.rs @@ -186,7 +186,7 @@ where { #[inline] fn default() -> Self { - let path_length = path_length::(); + let path_length = path_length::(); let mut path = Vec::with_capacity(path_length); path.resize_with(path_length, InnerDigest::::default); Self::new(Default::default(), path) @@ -403,7 +403,7 @@ where I: IntoIterator>, { let mut iter = iter.into_iter().peekable(); - (depth..path_length::()).fold(base, move |acc, _| { + (depth..path_length::()).fold(base, move |acc, _| { Self::fold_fn(parameters, index.into_parent(), &acc, default, || { iter.next().unwrap() }) @@ -931,23 +931,22 @@ pub mod constraint { use super::*; use crate::{ constraint::{ - Allocator, ConditionalSelect, Constant, ConstraintSystem, Equal, Secret, ValueSource, - Variable, + Allocate, Allocator, Bool, ConditionalSwap, Constant, Has, PartialEq, Secret, Variable, }, - merkle_tree::path_length_in, + merkle_tree::path_length, }; /// Inner Path Variable pub struct InnerPathVar where C: Configuration + ?Sized, - COM: ConstraintSystem, + COM: Has, { /// Leaf Index - pub leaf_index: COM::Bool, + pub leaf_index: Bool, /// Digest Indices - pub inner_indices: Vec, + pub inner_indices: Vec>, /// Inner Digest Path /// @@ -958,8 +957,8 @@ pub mod constraint { impl InnerPathVar where C: Configuration + ?Sized, - COM: ConstraintSystem, - InnerDigest: ConditionalSelect, + COM: Has, + InnerDigest: ConditionalSwap, { /// Computes the root of the merkle tree relative to `base` using `parameters`. #[inline] @@ -988,13 +987,13 @@ pub mod constraint { compiler: &mut COM, ) -> Root where - LeafDigest: ConditionalSelect, + LeafDigest: ConditionalSwap, { let (lhs, rhs) = - compiler.conditional_swap(&self.leaf_index, leaf_digest, sibling_digest); + ConditionalSwap::swap(&self.leaf_index, leaf_digest, sibling_digest, compiler); self.root_from_base( parameters, - parameters.join_leaves_in(&lhs, &rhs, compiler), + parameters.join_leaves_with(&lhs, &rhs, compiler), compiler, ) } @@ -1007,11 +1006,11 @@ pub mod constraint { ) -> impl 'd + FnMut( InnerDigest, - (&'d COM::Bool, &'d InnerDigest), + (&'d Bool, &'d InnerDigest), ) -> InnerDigest { move |acc, (b, d)| { - let (lhs, rhs) = compiler.conditional_swap(b, &acc, d); - parameters.join_in(&lhs, &rhs, compiler) + let (lhs, rhs) = ConditionalSwap::swap(b, &acc, d, compiler); + parameters.join_with(&lhs, &rhs, compiler) } } @@ -1025,7 +1024,7 @@ pub mod constraint { ) -> Root where InnerDigest: 'i, - I: IntoIterator)>, + I: IntoIterator, &'i InnerDigest)>, { iter.into_iter() .fold(base, Self::fold_fn(parameters, compiler)) @@ -1034,8 +1033,8 @@ pub mod constraint { impl Variable for InnerPathVar where - COM: ConstraintSystem, - COM::Bool: Variable, + COM: Has, + Bool: Variable, C: Configuration + Constant + ?Sized, C::Type: Configuration, InnerDigest: Variable>, @@ -1049,7 +1048,7 @@ pub mod constraint { inner_indices: this .leaf_index .parents() - .take(path_length_in::()) + .take(path_length::()) .map(|i| i.is_right().as_known(compiler)) .collect(), path: this.path.iter().map(|d| d.as_known(compiler)).collect(), @@ -1060,10 +1059,10 @@ pub mod constraint { fn new_unknown(compiler: &mut COM) -> Self { Self { leaf_index: compiler.allocate_unknown(), - inner_indices: (0..path_length_in::()) + inner_indices: (0..path_length::()) .map(|_| compiler.allocate_unknown()) .collect(), - path: (0..path_length_in::()) + path: (0..path_length::()) .map(|_| compiler.allocate_unknown()) .collect(), } @@ -1074,7 +1073,7 @@ pub mod constraint { pub struct PathVar where C: Configuration + ?Sized, - COM: ConstraintSystem, + COM: Has, { /// Sibling Digest pub sibling_digest: LeafDigest, @@ -1086,9 +1085,9 @@ pub mod constraint { impl PathVar where C: Configuration + ?Sized, - COM: ConstraintSystem, - InnerDigest: ConditionalSelect, - LeafDigest: ConditionalSelect, + COM: Has, + InnerDigest: ConditionalSwap, + LeafDigest: ConditionalSwap, { /// Computes the root of the merkle tree relative to `leaf_digest` using `parameters`. #[inline] @@ -1111,12 +1110,12 @@ pub mod constraint { root: &Root, leaf_digest: &LeafDigest, compiler: &mut COM, - ) -> COM::Bool + ) -> Bool where - Root: Equal, + Root: PartialEq, COM>, { let computed_root = self.root(parameters, leaf_digest, compiler); - compiler.eq(root, &computed_root) + root.eq(&computed_root, compiler) } /// Returns `true` if `self` is a witness to the fact that `leaf` is stored in a merkle tree @@ -1128,14 +1127,14 @@ pub mod constraint { root: &Root, leaf: &Leaf, compiler: &mut COM, - ) -> COM::Bool + ) -> Bool where - Root: Equal, + Root: PartialEq, COM>, { self.verify_digest( parameters, root, - ¶meters.digest_in(leaf, compiler), + ¶meters.digest_with(leaf, compiler), compiler, ) } @@ -1143,8 +1142,8 @@ pub mod constraint { impl Variable for PathVar where - COM: ConstraintSystem, - COM::Bool: Variable, + COM: Has, + Bool: Variable, C: Configuration + Constant + ?Sized, C::Type: Configuration, InnerDigest: Variable>, diff --git a/manta-crypto/src/merkle_tree/single_path.rs b/manta-crypto/src/merkle_tree/single_path.rs index 8aee4cf0e..eded49459 100644 --- a/manta-crypto/src/merkle_tree/single_path.rs +++ b/manta-crypto/src/merkle_tree/single_path.rs @@ -192,7 +192,7 @@ pub mod raw { { if leaf_digest.is_none() { Length::Empty - } else if current_path.leaf_index().0 < capacity::() - 1 { + } else if current_path.leaf_index().0 < capacity::() - 1 { Length::CanAccept } else { Length::Full diff --git a/manta-crypto/src/merkle_tree/test.rs b/manta-crypto/src/merkle_tree/test.rs index 13296d9de..ebe9a2193 100644 --- a/manta-crypto/src/merkle_tree/test.rs +++ b/manta-crypto/src/merkle_tree/test.rs @@ -213,7 +213,7 @@ where type Output = T; #[inline] - fn join_in( + fn join( parameters: &Self::Parameters, lhs: &Self::Output, rhs: &Self::Output, @@ -224,7 +224,7 @@ where } #[inline] - fn join_leaves_in( + fn join_leaves( parameters: &Self::Parameters, lhs: &Self::LeafDigest, rhs: &Self::LeafDigest, diff --git a/manta-crypto/src/merkle_tree/tree.rs b/manta-crypto/src/merkle_tree/tree.rs index ff42302b5..0f0ed005a 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::{ConditionalSelect, Constant, ConstraintSystem, Equal, Native, ValueSource}, + constraint::{self, Allocate, AssertEq, Bool, ConditionalSwap, Constant, Has}, merkle_tree::{ fork::{ForkedTree, Trunk}, inner_tree::InnerMap, @@ -57,21 +57,9 @@ pub trait LeafHash { /// Leaf Hash Output Type type Output; - /// Computes the digest of the `leaf` using `parameters` inside the given `compiler`. - fn digest_in( - parameters: &Self::Parameters, - leaf: &Self::Leaf, - compiler: &mut COM, - ) -> Self::Output; - /// Computes the digest of the `leaf` using `parameters`. - #[inline] - fn digest(parameters: &Self::Parameters, leaf: &Self::Leaf) -> Self::Output - where - COM: Native, - { - Self::digest_in(parameters, leaf, &mut COM::compiler()) - } + fn digest(parameters: &Self::Parameters, leaf: &Self::Leaf, compiler: &mut COM) + -> Self::Output; } /// Identity Leaf Hash @@ -100,7 +88,7 @@ where type Output = L; #[inline] - fn digest_in( + fn digest( parameters: &Self::Parameters, leaf: &Self::Leaf, compiler: &mut COM, @@ -121,45 +109,21 @@ pub trait InnerHash { /// Inner Hash Output Type type Output; - /// Combines two inner digests into a new inner digest using `parameters` inside the given - /// `compiler`. - fn join_in( + /// Combines two inner digests into a new inner digest using `parameters`. + fn join( parameters: &Self::Parameters, lhs: &Self::Output, rhs: &Self::Output, compiler: &mut COM, ) -> Self::Output; - /// Combines two inner digests into a new inner digest using `parameters`. - #[inline] - fn join(parameters: &Self::Parameters, lhs: &Self::Output, rhs: &Self::Output) -> Self::Output - where - COM: Native, - { - Self::join_in(parameters, lhs, rhs, &mut COM::compiler()) - } - - /// Combines two [`LeafDigest`](Self::LeafDigest) values into an inner digest inside the given - /// `compiler`. - fn join_leaves_in( - parameters: &Self::Parameters, - lhs: &Self::LeafDigest, - rhs: &Self::LeafDigest, - compiler: &mut COM, - ) -> Self::Output; - /// Combines two [`LeafDigest`](Self::LeafDigest) values into an inner digest. - #[inline] fn join_leaves( parameters: &Self::Parameters, lhs: &Self::LeafDigest, rhs: &Self::LeafDigest, - ) -> Self::Output - where - COM: Native, - { - Self::join_leaves_in(parameters, lhs, rhs, &mut COM::compiler()) - } + compiler: &mut COM, + ) -> Self::Output; } /// Merkle Tree Hash Configuration @@ -240,20 +204,7 @@ pub type InnerDigest = /// The capacity of a merkle tree with height `H` is `2^(H-1)`. #[inline] #[must_use] -pub fn capacity() -> usize -where - C: Configuration + ?Sized, -{ - capacity_in::() -} - -/// Returns the capacity of the merkle tree with the given [`C::HEIGHT`](Configuration::HEIGHT) -/// parameter. -/// -/// The capacity of a merkle tree with height `H` is `2^(H-1)`. -#[inline] -#[must_use] -pub fn capacity_in() -> usize +pub fn capacity() -> usize where C: Configuration + ?Sized, { @@ -266,20 +217,7 @@ where /// The path length of a merkle tree with height `H` is `H - 2`. #[inline] #[must_use] -pub fn path_length() -> usize -where - C: Configuration + ?Sized, -{ - path_length_in::() -} - -/// Returns the path length of the merkle tree with the given [`C::HEIGHT`](Configuration::HEIGHT) -/// parameter. -/// -/// The path length of a merkle tree with height `H` is `H - 2`. -#[inline] -#[must_use] -pub fn path_length_in() -> usize +pub fn path_length() -> usize where C: Configuration + ?Sized, { @@ -376,7 +314,8 @@ where L: IntoIterator>, { let mut leaf_digests = leaf_digests.into_iter(); - if matches!(leaf_digests.size_hint().1, Some(max) if max <= capacity::() - self.len()) { + if matches!(leaf_digests.size_hint().1, Some(max) if max <= capacity::() - self.len()) + { loop { match self.maybe_push_digest(parameters, || leaf_digests.next()) { Some(result) => assert!( @@ -577,47 +516,47 @@ where /// Computes the leaf digest of `leaf` using `self`. #[inline] - pub fn digest_in(&self, leaf: &Leaf, compiler: &mut COM) -> LeafDigest { - C::LeafHash::digest_in(&self.leaf, leaf, compiler) + pub fn digest_with(&self, leaf: &Leaf, compiler: &mut COM) -> LeafDigest { + C::LeafHash::digest(&self.leaf, leaf, compiler) } /// Combines two inner digests into a new inner digest using `self`. #[inline] - pub fn join_in( + pub fn join_with( &self, lhs: &InnerDigest, rhs: &InnerDigest, compiler: &mut COM, ) -> InnerDigest { - C::InnerHash::join_in(&self.inner, lhs, rhs, compiler) + C::InnerHash::join(&self.inner, lhs, rhs, compiler) } /// Combines two leaf digests into a new inner digest using `self`. #[inline] - pub fn join_leaves_in( + pub fn join_leaves_with( &self, lhs: &LeafDigest, rhs: &LeafDigest, compiler: &mut COM, ) -> InnerDigest { - C::InnerHash::join_leaves_in(&self.inner, lhs, rhs, compiler) + C::InnerHash::join_leaves(&self.inner, lhs, rhs, compiler) } /// Verify that `path` witnesses the fact that `leaf` is a member of a merkle tree with the /// given `root`. #[inline] - pub fn verify_path_in( + pub fn verify_path_with( &self, path: &PathVar, root: &Root, leaf: &Leaf, compiler: &mut COM, - ) -> COM::Bool + ) -> Bool where C: Configuration, - COM: ConstraintSystem, - InnerDigest: ConditionalSelect + Equal, - LeafDigest: ConditionalSelect, + COM: Has, + InnerDigest: ConditionalSwap + constraint::PartialEq, COM>, + LeafDigest: ConditionalSwap, { path.verify(self, root, leaf, compiler) } @@ -630,19 +569,19 @@ where /// Computes the leaf digest of `leaf` using `self`. #[inline] pub fn digest(&self, leaf: &Leaf) -> LeafDigest { - C::LeafHash::digest(&self.leaf, leaf) + C::LeafHash::digest(&self.leaf, leaf, &mut ()) } /// Combines two inner digests into a new inner digest using `self`. #[inline] pub fn join(&self, lhs: &InnerDigest, rhs: &InnerDigest) -> InnerDigest { - C::InnerHash::join(&self.inner, lhs, rhs) + C::InnerHash::join(&self.inner, lhs, rhs, &mut ()) } /// Combines two leaf digests into a new inner digest using `self`. #[inline] pub fn join_leaves(&self, lhs: &LeafDigest, rhs: &LeafDigest) -> InnerDigest { - C::InnerHash::join_leaves(&self.inner, lhs, rhs) + C::InnerHash::join_leaves(&self.inner, lhs, rhs, &mut ()) } /// Verify that `path` witnesses the fact that `leaf` is a member of a merkle tree with the @@ -742,7 +681,7 @@ where type Verification = bool; #[inline] - fn verify_in( + fn verify( &self, item: &Self::Item, witness: &Self::Witness, @@ -756,24 +695,44 @@ where impl accumulator::Model for Parameters where C: Configuration + ?Sized, - COM: ConstraintSystem, - InnerDigest: ConditionalSelect + Equal, - LeafDigest: ConditionalSelect, + COM: Has, + InnerDigest: ConditionalSwap + constraint::PartialEq, COM>, + LeafDigest: ConditionalSwap, { type Item = Leaf; type Witness = PathVar; type Output = Root; - type Verification = COM::Bool; + type Verification = Bool; #[inline] - fn verify_in( + fn verify( &self, item: &Self::Item, witness: &Self::Witness, output: &Self::Output, compiler: &mut COM, ) -> Self::Verification { - self.verify_path_in(witness, output, item, compiler) + self.verify_path_with(witness, output, item, compiler) + } +} + +impl accumulator::AssertValidVerification for Parameters +where + COM: AssertEq, + C: Configuration + ?Sized, + InnerDigest: ConditionalSwap + constraint::PartialEq, COM>, + LeafDigest: ConditionalSwap, +{ + #[inline] + fn assert_valid( + &self, + item: &Self::Item, + witness: &Self::Witness, + output: &Self::Output, + compiler: &mut COM, + ) { + let root = witness.root(self, &self.digest_with(item, compiler), compiler); + compiler.assert_eq(output, &root) } } @@ -880,7 +839,7 @@ where /// See [`capacity`] for more. #[inline] pub fn capacity(&self) -> usize { - capacity::() + capacity::() } /// Returns the number of items this merkle tree. @@ -1107,7 +1066,7 @@ where { #[inline] fn capacity() -> usize { - capacity::() + capacity::() } } diff --git a/manta-pay/Cargo.toml b/manta-pay/Cargo.toml index c49834ff0..e56781401 100644 --- a/manta-pay/Cargo.toml +++ b/manta-pay/Cargo.toml @@ -117,7 +117,7 @@ ark-std = { version = "0.3.0", optional = true, default-features = false } bip32 = { version = "0.3.0", optional = true, default-features = false, features = ["bip39", "secp256k1"] } blake2 = { version = "0.10.4", default-features = false } bs58 = { version = "0.4.0", optional = true, default-features = false, features = ["alloc"] } -clap = { version = "3.2.4", optional = true, default-features = false, features = ["color", "derive", "std", "suggestions", "unicode", "wrap_help"] } +clap = { version = "3.2.6", 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-pay/src/bin/measure.rs b/manta-pay/src/bin/measure.rs index 02226a13e..29189eb56 100644 --- a/manta-pay/src/bin/measure.rs +++ b/manta-pay/src/bin/measure.rs @@ -17,7 +17,7 @@ //! Manta Pay Circuit Measurements use manta_crypto::{ - constraint::{measure::Instrument, Allocator, Secret, ValueSource}, + constraint::{measure::Instrument, Allocate, Allocator, Secret}, hash::ArrayHashFunction, key::{KeyAgreementScheme as _, KeyDerivationFunction}, rand::{Sample, SeedableRng}, @@ -32,7 +32,7 @@ use rand_chacha::ChaCha20Rng; #[inline] pub fn main() { let mut rng = ChaCha20Rng::from_entropy(); - let mut compiler = Compiler::for_unknown(); + let mut compiler = Compiler::for_contexts(); let mut instrument = Instrument::new(&mut compiler); @@ -41,7 +41,7 @@ pub fn main() { let poseidon_rhs = instrument.base.allocate_unknown::(); let _ = instrument.measure("Poseidon ARITY-2", |compiler| { - hasher.hash_in([&poseidon_lhs, &poseidon_rhs], compiler) + hasher.hash([&poseidon_lhs, &poseidon_rhs], compiler) }); let hasher = Poseidon4::gen(&mut rng).as_constant::(&mut instrument); @@ -51,7 +51,7 @@ pub fn main() { let poseidon_3 = instrument.base.allocate_unknown::(); let _ = instrument.measure("Poseidon ARITY-4", |compiler| { - hasher.hash_in( + hasher.hash( [&poseidon_0, &poseidon_1, &poseidon_2, &poseidon_3], compiler, ) @@ -63,11 +63,11 @@ pub fn main() { let secret_key_1 = instrument.base.allocate_unknown::(); let public_key_0 = instrument.measure("DHKE `derive`", |compiler| { - key_agreement.derive_in(&secret_key_0, compiler) + key_agreement.derive(&secret_key_0, compiler) }); let _ = instrument.measure("DHKE `agree`", |compiler| { - key_agreement.agree_in(&secret_key_1, &public_key_0, compiler) + key_agreement.agree(&secret_key_1, &public_key_0, compiler) }); println!("{:#?}", instrument.measurements); diff --git a/manta-pay/src/config.rs b/manta-pay/src/config.rs index 136796a97..1641e8587 100644 --- a/manta-pay/src/config.rs +++ b/manta-pay/src/config.rs @@ -39,7 +39,7 @@ use manta_accounting::{ use manta_crypto::{ accumulator, constraint::{ - Add, Allocator, Constant, Equal, ProofSystemInput, Public, Secret, ValueSource, Variable, + self, Add, Allocate, Allocator, Constant, ProofSystemInput, Public, Secret, Variable, }, ecc::DiffieHellman, encryption, @@ -155,21 +155,24 @@ impl transfer::UtxoCommitmentScheme for UtxoCommitmentScheme { type Utxo = Utxo; #[inline] - fn commit_in( + fn commit( &self, ephemeral_secret_key: &Self::EphemeralSecretKey, public_spend_key: &Self::PublicSpendKey, asset: &Self::Asset, _: &mut (), ) -> Self::Utxo { - self.0.hash([ - // FIXME: This is the lift from inner scalar to outer scalar and only exists in some - // cases! We need a better abstraction for this. - &ecc::arkworks::lift_embedded_scalar::(ephemeral_secret_key), - &Fp(public_spend_key.0.x), // NOTE: Group is in affine form, so we can extract `x`. - &Fp(asset.id.0.into()), - &Fp(asset.value.0.into()), - ]) + self.0.hash( + [ + // FIXME: This is the lift from inner scalar to outer scalar and only exists in some + // cases! We need a better abstraction for this. + &ecc::arkworks::lift_embedded_scalar::(ephemeral_secret_key), + &Fp(public_spend_key.0.x), // NOTE: Group is in affine form, so we can extract `x`. + &Fp(asset.id.0.into()), + &Fp(asset.value.0.into()), + ], + &mut (), + ) } } @@ -219,14 +222,14 @@ impl transfer::UtxoCommitmentScheme for UtxoCommitmentSchemeVar { type Utxo = UtxoVar; #[inline] - fn commit_in( + fn commit( &self, ephemeral_secret_key: &Self::EphemeralSecretKey, public_spend_key: &Self::PublicSpendKey, asset: &Self::Asset, compiler: &mut Compiler, ) -> Self::Utxo { - self.0.hash_in( + self.0.hash( [ &ephemeral_secret_key.0, &public_spend_key.0.x, // NOTE: Group is in affine form, so we can extract `x`. @@ -260,18 +263,21 @@ impl transfer::VoidNumberCommitmentScheme for VoidNumberCommitmentScheme { type VoidNumber = VoidNumber; #[inline] - fn commit_in( + fn commit( &self, secret_spend_key: &Self::SecretSpendKey, utxo: &Self::Utxo, _: &mut (), ) -> Self::VoidNumber { - self.0.hash([ - // FIXME: This is the lift from inner scalar to outer scalar and only exists in some - // cases! We need a better abstraction for this. - &ecc::arkworks::lift_embedded_scalar::(secret_spend_key), - utxo, - ]) + self.0.hash( + [ + // FIXME: This is the lift from inner scalar to outer scalar and only exists in some + // cases! We need a better abstraction for this. + &ecc::arkworks::lift_embedded_scalar::(secret_spend_key), + utxo, + ], + &mut (), + ) } } @@ -320,13 +326,13 @@ impl transfer::VoidNumberCommitmentScheme for VoidNumberCommitmentSche type VoidNumber = ConstraintFieldVar; #[inline] - fn commit_in( + fn commit( &self, secret_spend_key: &Self::SecretSpendKey, utxo: &Self::Utxo, compiler: &mut Compiler, ) -> Self::VoidNumber { - self.0.hash_in([&secret_spend_key.0, utxo], compiler) + self.0.hash([&secret_spend_key.0, utxo], compiler) } } @@ -342,10 +348,10 @@ impl Constant for VoidNumberCommitmentSchemeVar { /// Asset ID Variable pub struct AssetIdVar(ConstraintFieldVar); -impl Equal for AssetIdVar { +impl constraint::PartialEq for AssetIdVar { #[inline] - fn eq(lhs: &Self, rhs: &Self, compiler: &mut Compiler) -> Boolean { - ConstraintFieldVar::eq(&lhs.0, &rhs.0, compiler) + fn eq(&self, rhs: &Self, compiler: &mut Compiler) -> Boolean { + ConstraintFieldVar::eq(&self.0, &rhs.0, compiler) } } @@ -380,17 +386,19 @@ impl Variable for AssetIdVar { /// Asset Value Variable pub struct AssetValueVar(ConstraintFieldVar); -impl Add for AssetValueVar { +impl Add for AssetValueVar { + type Output = Self; + #[inline] - fn add(lhs: Self, rhs: Self, compiler: &mut Compiler) -> Self { - Self(ConstraintFieldVar::add(lhs.0, rhs.0, compiler)) + fn add(self, rhs: Self, compiler: &mut Compiler) -> Self::Output { + Self(ConstraintFieldVar::add(self.0, rhs.0, compiler)) } } -impl Equal for AssetValueVar { +impl constraint::PartialEq for AssetValueVar { #[inline] - fn eq(lhs: &Self, rhs: &Self, compiler: &mut Compiler) -> Boolean { - ConstraintFieldVar::eq(&lhs.0, &rhs.0, compiler) + fn eq(&self, rhs: &Self, compiler: &mut Compiler) -> Boolean { + ConstraintFieldVar::eq(&self.0, &rhs.0, compiler) } } @@ -437,23 +445,23 @@ impl merkle_tree::InnerHash for InnerHash { type Output = Fp; #[inline] - fn join_in( + fn join( parameters: &Self::Parameters, lhs: &Self::Output, rhs: &Self::Output, - _: &mut (), + compiler: &mut (), ) -> Self::Output { - parameters.hash([lhs, rhs]) + parameters.hash([lhs, rhs], compiler) } #[inline] - fn join_leaves_in( + fn join_leaves( parameters: &Self::Parameters, lhs: &Self::LeafDigest, rhs: &Self::LeafDigest, - _: &mut (), + compiler: &mut (), ) -> Self::Output { - parameters.hash([lhs, rhs]) + parameters.hash([lhs, rhs], compiler) } } @@ -466,23 +474,23 @@ impl merkle_tree::InnerHash for InnerHashVar { type Output = ConstraintFieldVar; #[inline] - fn join_in( + fn join( parameters: &Self::Parameters, lhs: &Self::Output, rhs: &Self::Output, compiler: &mut Compiler, ) -> Self::Output { - parameters.hash_in([lhs, rhs], compiler) + parameters.hash([lhs, rhs], compiler) } #[inline] - fn join_leaves_in( + fn join_leaves( parameters: &Self::Parameters, lhs: &Self::LeafDigest, rhs: &Self::LeafDigest, compiler: &mut Compiler, ) -> Self::Output { - parameters.hash_in([lhs, rhs], compiler) + parameters.hash([lhs, rhs], compiler) } } diff --git a/manta-pay/src/crypto/constraint/arkworks/groth16.rs b/manta-pay/src/crypto/constraint/arkworks/groth16.rs index 416aaac97..4772ec424 100644 --- a/manta-pay/src/crypto/constraint/arkworks/groth16.rs +++ b/manta-pay/src/crypto/constraint/arkworks/groth16.rs @@ -449,7 +449,7 @@ impl ProofSystem for Groth16 where E: PairingEngine, { - type ConstraintSystem = R1CS; + type Compiler = R1CS; type PublicParameters = (); type ProvingContext = ProvingContext; type VerifyingContext = VerifyingContext; @@ -458,19 +458,19 @@ where type Error = Error; #[inline] - fn for_unknown() -> Self::ConstraintSystem { - Self::ConstraintSystem::for_unknown() + fn context_compiler() -> Self::Compiler { + Self::Compiler::for_contexts() } #[inline] - fn for_known() -> Self::ConstraintSystem { - Self::ConstraintSystem::for_known() + fn proof_compiler() -> Self::Compiler { + Self::Compiler::for_proofs() } #[inline] - fn generate_context( + fn compile( public_parameters: &Self::PublicParameters, - cs: Self::ConstraintSystem, + compiler: Self::Compiler, rng: &mut R, ) -> Result<(Self::ProvingContext, Self::VerifyingContext), Self::Error> where @@ -478,7 +478,7 @@ where { let _ = public_parameters; let (proving_key, verifying_key) = - ArkGroth16::circuit_specific_setup(cs, &mut SizedRng(rng)).map_err(|_| Error)?; + ArkGroth16::circuit_specific_setup(compiler, &mut SizedRng(rng)).map_err(|_| Error)?; Ok(( ProvingContext(proving_key), VerifyingContext(ArkGroth16::process_vk(&verifying_key).map_err(|_| Error)?), @@ -488,13 +488,13 @@ where #[inline] fn prove( context: &Self::ProvingContext, - cs: Self::ConstraintSystem, + compiler: Self::Compiler, rng: &mut R, ) -> Result where R: CryptoRng + RngCore + ?Sized, { - ArkGroth16::prove(&context.0, cs, &mut SizedRng(rng)) + ArkGroth16::prove(&context.0, compiler, &mut SizedRng(rng)) .map(Proof) .map_err(|_| Error) } diff --git a/manta-pay/src/crypto/constraint/arkworks/mod.rs b/manta-pay/src/crypto/constraint/arkworks/mod.rs index 20d9b51a9..b51982ca9 100644 --- a/manta-pay/src/crypto/constraint/arkworks/mod.rs +++ b/manta-pay/src/crypto/constraint/arkworks/mod.rs @@ -25,10 +25,11 @@ use ark_relations::{ }; use manta_crypto::{ constraint::{ - measure::Measure, Add, ConditionalSelect, Constant, ConstraintSystem, Equal, Public, - Secret, Variable, + self, + measure::{Count, Measure}, + mode, Add, Assert, AssertEq, ConditionalSwap, Constant, Has, Public, Secret, Variable, }, - rand::{CryptoRng, RngCore, Sample}, + rand::{RngCore, Sample}, }; use manta_util::{ byte_count, @@ -181,7 +182,7 @@ where #[inline] fn sample(_: (), rng: &mut R) -> Self where - R: CryptoRng + RngCore + ?Sized, + R: RngCore + ?Sized, { Self(F::rand(rng)) } @@ -266,7 +267,7 @@ where { /// Constructs a new constraint system which is ready for unknown variables. #[inline] - pub fn for_unknown() -> Self { + pub fn for_contexts() -> Self { // FIXME: This might not be the right setup for all proof systems. let cs = ark_r1cs::ConstraintSystem::new_ref(); cs.set_optimization_goal(ark_r1cs::OptimizationGoal::Constraints); @@ -276,7 +277,7 @@ where /// Constructs a new constraint system which is ready for known variables. #[inline] - pub fn for_known() -> Self { + pub fn for_proofs() -> Self { // FIXME: This might not be the right setup for all proof systems. let cs = ark_r1cs::ConstraintSystem::new_ref(); cs.set_optimization_goal(ark_r1cs::OptimizationGoal::Constraints); @@ -292,39 +293,63 @@ where } } -impl ConstraintSystem for R1CS +impl Has for R1CS where F: PrimeField, { - type Bool = Boolean; + type Type = Boolean; +} +impl Assert for R1CS +where + F: PrimeField, +{ #[inline] - fn assert(&mut self, b: Self::Bool) { + fn assert(&mut self, b: &Boolean) { b.enforce_equal(&Boolean::TRUE) .expect("Enforcing equality is not allowed to fail."); } } -impl Measure for R1CS +impl AssertEq for R1CS where F: PrimeField, { - #[inline] - fn constraint_count(&self) -> usize { - self.cs.num_constraints() - } + // TODO: Implement these optimizations. +} + +impl Count for R1CS where F: PrimeField {} +impl Count for R1CS +where + F: PrimeField, +{ #[inline] - fn public_variable_count(&self) -> Option { + fn count(&self) -> Option { Some(self.cs.num_instance_variables()) } +} +impl Count for R1CS +where + F: PrimeField, +{ #[inline] - fn secret_variable_count(&self) -> Option { + fn count(&self) -> Option { Some(self.cs.num_witness_variables()) } } +impl Measure for R1CS +where + F: PrimeField, +{ + #[inline] + fn constraint_count(&self) -> usize { + self.cs.num_constraints() + } +} + impl ConstraintSynthesizer for R1CS where F: PrimeField, @@ -396,14 +421,14 @@ where } } -impl Equal> for Boolean +impl constraint::PartialEq> for Boolean where F: PrimeField, { #[inline] - fn eq(lhs: &Self, rhs: &Self, compiler: &mut R1CS) -> Boolean { + fn eq(&self, rhs: &Self, compiler: &mut R1CS) -> Boolean { let _ = compiler; - lhs.is_eq(rhs) + self.is_eq(rhs) .expect("Equality checking is not allowed to fail.") } } @@ -459,42 +484,51 @@ where } } -impl Equal> for FpVar +impl constraint::PartialEq> for FpVar where F: PrimeField, { #[inline] - fn eq(lhs: &Self, rhs: &Self, compiler: &mut R1CS) -> Boolean { + fn eq(&self, rhs: &Self, compiler: &mut R1CS) -> Boolean { let _ = compiler; - lhs.is_eq(rhs) + self.is_eq(rhs) .expect("Equality checking is not allowed to fail.") } } -impl ConditionalSelect> for FpVar +/// Conditionally select from `lhs` and `rhs` depending on the value of `bit`. +#[inline] +fn conditionally_select(bit: &Boolean, lhs: &FpVar, rhs: &FpVar) -> FpVar +where + F: PrimeField, +{ + FpVar::conditionally_select(bit, lhs, rhs) + .expect("Conditionally selecting from two values is not allowed to fail.") +} + +impl ConditionalSwap> for FpVar where F: PrimeField, { #[inline] - fn select( - bit: &Boolean, - true_value: &Self, - false_value: &Self, - compiler: &mut R1CS, - ) -> Self { + fn swap(bit: &Boolean, lhs: &Self, rhs: &Self, compiler: &mut R1CS) -> (Self, Self) { let _ = compiler; - Self::conditionally_select(bit, true_value, false_value) - .expect("Conditionally selecting from two values is not allowed to fail.") + ( + conditionally_select(bit, rhs, lhs), + conditionally_select(bit, lhs, rhs), + ) } } -impl Add> for FpVar +impl Add> for FpVar where F: PrimeField, { + type Output = Self; + #[inline] - fn add(lhs: Self, rhs: Self, compiler: &mut R1CS) -> Self { + fn add(self, rhs: Self, compiler: &mut R1CS) -> Self { let _ = compiler; - lhs + rhs + self + rhs } } diff --git a/manta-pay/src/crypto/ecc/arkworks.rs b/manta-pay/src/crypto/ecc/arkworks.rs index 53bc7a892..c638cce1a 100644 --- a/manta-pay/src/crypto/ecc/arkworks.rs +++ b/manta-pay/src/crypto/ecc/arkworks.rs @@ -24,7 +24,7 @@ use ark_relations::ns; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError}; use core::marker::PhantomData; use manta_crypto::{ - constraint::{Allocator, Constant, Equal, Public, Secret, ValueSource, Variable}, + constraint::{self, Allocate, Allocator, Constant, Public, Secret, Variable}, ecc::{self, PointAdd, PointDouble}, key::kdf, rand::{CryptoRng, RngCore, Sample}, @@ -451,15 +451,15 @@ macro_rules! impl_processed_scalar_mul { impl_processed_scalar_mul!(ark_ed_on_bls12_381::EdwardsProjective); -impl Equal> for GroupVar +impl constraint::PartialEq> for GroupVar where C: ProjectiveCurve, CV: CurveVar>, { #[inline] - fn eq(lhs: &Self, rhs: &Self, compiler: &mut Compiler) -> Boolean> { + fn eq(&self, rhs: &Self, compiler: &mut Compiler) -> Boolean> { let _ = compiler; - lhs.0 + self.0 .is_eq(&rhs.0) .expect("Equality checking is not allowed to fail.") } @@ -578,7 +578,7 @@ mod test { use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective}; use ecc::PreprocessedScalarMul; use manta_crypto::{ - constraint::ConstraintSystem, + constraint::AssertEq, ecc::{PreprocessedScalarMulTable, ScalarMul}, rand::OsRng, }; @@ -597,7 +597,7 @@ mod test { >, { const NUM_TRIALS: usize = 5; - let mut cs = R1CS::for_known(); + let mut cs = R1CS::for_proofs(); for _ in 0..NUM_TRIALS { let base = Group::gen(rng).as_known::>(&mut cs); let scalar = Scalar::::gen(rng).as_known::(&mut cs); diff --git a/manta-pay/src/crypto/hash/poseidon/compat.rs b/manta-pay/src/crypto/hash/poseidon/compat.rs index 6540e0ac4..bb8b0bf66 100644 --- a/manta-pay/src/crypto/hash/poseidon/compat.rs +++ b/manta-pay/src/crypto/hash/poseidon/compat.rs @@ -226,7 +226,7 @@ where type Output = S::Field; #[inline] - fn hash_in(&self, input: [&Self::Input; ARITY], compiler: &mut COM) -> Self::Output { + fn hash(&self, input: [&Self::Input; ARITY], compiler: &mut COM) -> Self::Output { let mut state = self.first_round(input, compiler); for round in 1..S::FULL_ROUNDS { self.full_round(round, &mut state, compiler); @@ -330,7 +330,7 @@ pub mod arkworks { use crate::crypto::constraint::arkworks::{Fp, FpVar, R1CS}; use ark_ff::{Field, PrimeField}; use ark_r1cs_std::fields::FieldVar; - use manta_crypto::constraint::{Constant, ValueSource}; + use manta_crypto::constraint::{Allocate, Constant}; /// Compiler Type type Compiler = R1CS<::Field>; diff --git a/manta-pay/src/crypto/hash/poseidon/mod.rs b/manta-pay/src/crypto/hash/poseidon/mod.rs index 7c6b13aa5..0ec8e0771 100644 --- a/manta-pay/src/crypto/hash/poseidon/mod.rs +++ b/manta-pay/src/crypto/hash/poseidon/mod.rs @@ -333,7 +333,7 @@ where type Output = S::Field; #[inline] - fn hash_in(&self, input: [&Self::Input; ARITY], compiler: &mut COM) -> Self::Output { + fn hash(&self, input: [&Self::Input; ARITY], compiler: &mut COM) -> Self::Output { self.hash_untruncated(input, compiler).take_first() } } diff --git a/manta-pay/src/crypto/key.rs b/manta-pay/src/crypto/key.rs index 473ab9919..d79ae1435 100644 --- a/manta-pay/src/crypto/key.rs +++ b/manta-pay/src/crypto/key.rs @@ -32,7 +32,7 @@ impl KeyDerivationFunction for Blake2sKdf { type Output = [u8; 32]; #[inline] - fn derive_in(&self, key: &Self::Key, _: &mut ()) -> Self::Output { + fn derive(&self, key: &Self::Key, _: &mut ()) -> Self::Output { let mut hasher = Blake2s::new(); hasher.update(key); hasher.update(b"manta kdf instantiated with blake2s hash function"); diff --git a/manta-pay/src/signer/base.rs b/manta-pay/src/signer/base.rs index bafe9f2df..89cb13d4d 100644 --- a/manta-pay/src/signer/base.rs +++ b/manta-pay/src/signer/base.rs @@ -59,7 +59,7 @@ where type Output = SecretKey; #[inline] - fn derive_in(&self, key: &Self::Key, _: &mut ()) -> Self::Output { + fn derive(&self, key: &Self::Key, _: &mut ()) -> Self::Output { // FIXME: Check that this conversion is logical/safe. let bytes: [u8; 32] = key .private_key() diff --git a/manta-pay/src/test/payment.rs b/manta-pay/src/test/payment.rs index 13dc63823..e15ec7b59 100644 --- a/manta-pay/src/test/payment.rs +++ b/manta-pay/src/test/payment.rs @@ -30,8 +30,8 @@ use manta_crypto::{ rand::{CryptoRng, Rand, RngCore, Sample}, }; -/// UTXO Accumulator for Building Circuits -type UtxoAccumulator = +/// UTXO Accumulator for Building Test Circuits +pub type UtxoAccumulator = TreeArrayMerkleForest, 256>; /// Generates a proof for a [`Mint`] transaction. @@ -55,16 +55,13 @@ where .expect("Unable to build MINT proof.") } -/// Samples context of [`Mint`]s for individual assets. -/// The context is used in `prove_private_transfer` function and -/// `prove_reclaim` for benchmarking. -/// Note that the mint proof is not included in the context, since it -/// is not used when proving private transfer or reclaim. -/// The generation of mint proof is also not included so that this function -/// is lightweight and we can precisely profile the performance of -/// `prove_priate_transfer` and `prove_reclaim`. +/// Samples a [`Mint`] spender. +/// +/// The spender is used in the [`prove_private_transfer`] and [`prove_reclaim`] functions for +/// benchmarking. Note that the [`Mint`] proof is not returned since it is not used when proving a +/// [`PrivateTransfer`] or [`Reclaim`]. #[inline] -pub fn sample_mint_context( +pub fn sample_mint_spender( parameters: &Parameters, utxo_accumulator: &mut UtxoAccumulator, asset: Asset, @@ -81,7 +78,7 @@ where (spending_key, sender) } -/// Generates a proof for a [`PrivateTransfer`] transaction +/// Generates a proof for a [`PrivateTransfer`] transaction. #[inline] pub fn prove_private_transfer( proving_context: &MultiProvingContext, @@ -97,9 +94,9 @@ where let asset_1 = asset_id.value(20_000); let mut utxo_accumulator = UtxoAccumulator::new(utxo_accumulator_model.clone()); let (spending_key_0, sender_0) = - sample_mint_context(parameters, &mut utxo_accumulator, asset_0, rng); + sample_mint_spender(parameters, &mut utxo_accumulator, asset_0, rng); let (spending_key_1, sender_1) = - sample_mint_context(parameters, &mut utxo_accumulator, asset_1, rng); + sample_mint_spender(parameters, &mut utxo_accumulator, asset_1, rng); PrivateTransfer::build( [sender_0, sender_1], [ @@ -115,7 +112,7 @@ where .expect("Unable to build PRIVATE_TRANSFER proof.") } -/// Generates a proof for a ['Reclaim'] transaction +/// Generates a proof for a [`Reclaim`] transaction. #[inline] pub fn prove_reclaim( proving_context: &MultiProvingContext, @@ -131,8 +128,8 @@ where let asset_1 = asset_id.value(20_000); let mut utxo_accumulator = UtxoAccumulator::new(utxo_accumulator_model.clone()); let (spending_key_0, sender_0) = - sample_mint_context(parameters, &mut utxo_accumulator, asset_0, rng); - let (_, sender_1) = sample_mint_context(parameters, &mut utxo_accumulator, asset_1, rng); + sample_mint_spender(parameters, &mut utxo_accumulator, asset_0, rng); + let (_, sender_1) = sample_mint_spender(parameters, &mut utxo_accumulator, asset_1, rng); Reclaim::build( [sender_0, sender_1], [spending_key_0.receiver(parameters, rng.gen(), asset_1)], diff --git a/manta-pay/src/test/transfer.rs b/manta-pay/src/test/transfer.rs index df3275a3d..c1835cbf7 100644 --- a/manta-pay/src/test/transfer.rs +++ b/manta-pay/src/test/transfer.rs @@ -17,28 +17,24 @@ //! Manta Pay Transfer Testing use crate::{ - config::{ - FullParameters, MerkleTreeConfiguration, Mint, PrivateTransfer, Proof, ProofSystem, Reclaim, - }, + config::{FullParameters, Mint, PrivateTransfer, Proof, ProofSystem, Reclaim}, + test::payment::UtxoAccumulator, util::scale::{assert_valid_codec, assert_valid_io_codec}, }; use manta_crypto::{ accumulator::Accumulator, constraint::{measure::Measure, ProofSystem as _}, - merkle_tree, rand::{OsRng, Rand}, }; use std::io::Cursor; -type UtxoAccumulator = merkle_tree::full::FullMerkleTree; - /// Tests the generation of proving/verifying contexts for [`Mint`]. #[test] fn sample_mint_context() { let mut rng = OsRng; let cs = Mint::unknown_constraints(FullParameters::new(&rng.gen(), &rng.gen())); println!("Mint: {:?}", cs.measure()); - ProofSystem::generate_context(&(), cs, &mut rng).expect("Unable to generate Mint context."); + ProofSystem::compile(&(), cs, &mut rng).expect("Unable to generate Mint context."); } /// Tests the generation of proving/verifying contexts for [`PrivateTransfer`]. @@ -47,8 +43,7 @@ fn sample_private_transfer_context() { let mut rng = OsRng; let cs = PrivateTransfer::unknown_constraints(FullParameters::new(&rng.gen(), &rng.gen())); println!("PrivateTransfer: {:?}", cs.measure()); - ProofSystem::generate_context(&(), cs, &mut rng) - .expect("Unable to generate PrivateTransfer context."); + ProofSystem::compile(&(), cs, &mut rng).expect("Unable to generate PrivateTransfer context."); } /// Tests the generation of proving/verifying contexts for [`Reclaim`]. @@ -57,7 +52,7 @@ fn sample_reclaim_context() { let mut rng = OsRng; let cs = Reclaim::unknown_constraints(FullParameters::new(&rng.gen(), &rng.gen())); println!("Reclaim: {:?}", cs.measure()); - ProofSystem::generate_context(&(), cs, &mut rng).expect("Unable to generate Reclaim context."); + ProofSystem::compile(&(), cs, &mut rng).expect("Unable to generate Reclaim context."); } /// Tests the generation of a [`Mint`].