diff --git a/Cargo.lock b/Cargo.lock index 6794c1254..97360b750 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3106,10 +3106,12 @@ dependencies = [ "rand", "rand_core", "rand_xorshift", + "redjubjub", "ripemd", "secp256k1", "sha2", "subtle", + "tracing", "zcash_address", "zcash_encoding", "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/zcash_primitives/CHANGELOG.md b/zcash_primitives/CHANGELOG.md index f0e89b1d8..52c64dc4d 100644 --- a/zcash_primitives/CHANGELOG.md +++ b/zcash_primitives/CHANGELOG.md @@ -9,7 +9,12 @@ and this library adheres to Rust's notion of ### Added - Dependency on `bellman 0.14`. - `zcash_primitives::sapling`: + - `BatchValidator` (moved from `zcash_proofs::sapling`). + - `SaplingVerificationContext` (moved from `zcash_proofs::sapling`). - `circuit` module (moved from `zcash_proofs::circuit::sapling`). + - `circuit::{SpendParameters, OutputParameters}` + - `circuit::{SpendVerifyingKey, PreparedSpendVerifyingKey}` + - `circuit::{OutputVerifyingKey, PreparedOutputVerifyingKey}` - `constants` module. - `prover::{SpendProver, OutputProver}` - `value`: @@ -58,6 +63,11 @@ and this library adheres to Rust's notion of ### Changed - `zcash_primitives::sapling`: + - `BatchValidator::validate` now takes the `SpendVerifyingKey` and + `OutputVerifyingKey` newtypes. + - `SaplingVerificationContext::{check_spend, check_output}` now take + the `PreparedSpendVerifyingKey` and `PreparedOutputVerifyingKey` + newtypes. - `address::PaymentAddress::create_note` now takes its `value` argument as a `NoteValue` instead of as a bare `u64`. - `circuit::ValueCommitmentOpening::value` is now represented as a `NoteValue` diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index f976ba3bb..a4101e433 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -32,8 +32,9 @@ rand_core.workspace = true blake2b_simd.workspace = true sha2.workspace = true -# - Metrics +# - Logging and metrics memuse.workspace = true +tracing.workspace = true # - Secret management subtle.workspace = true @@ -74,6 +75,7 @@ hex.workspace = true # - Shielded protocols bitvec.workspace = true blake2s_simd.workspace = true +redjubjub = "0.7" # - Transparent inputs ripemd = { workspace = true, optional = true } diff --git a/zcash_primitives/src/sapling.rs b/zcash_primitives/src/sapling.rs index 82c18e3bb..15a7ff04b 100644 --- a/zcash_primitives/src/sapling.rs +++ b/zcash_primitives/src/sapling.rs @@ -14,6 +14,7 @@ mod spec; mod tree; pub mod util; pub mod value; +mod verifier; use group::GroupEncoding; use rand_core::{CryptoRng, RngCore}; @@ -28,6 +29,7 @@ pub use note::{nullifier::Nullifier, Note, Rseed}; pub use tree::{ merkle_hash, CommitmentTree, IncrementalWitness, MerklePath, Node, NOTE_COMMITMENT_TREE_DEPTH, }; +pub use verifier::{BatchValidator, SaplingVerificationContext}; /// Create the spendAuthSig for a Sapling SpendDescription. pub fn spend_sig( diff --git a/zcash_primitives/src/sapling/circuit.rs b/zcash_primitives/src/sapling/circuit.rs index a2fece4d6..d1fe6bfcf 100644 --- a/zcash_primitives/src/sapling/circuit.rs +++ b/zcash_primitives/src/sapling/circuit.rs @@ -1,10 +1,12 @@ //! The Sapling circuits. use core::fmt; +use std::io; use group::{ff::PrimeField, Curve}; -use bellman::{Circuit, ConstraintSystem, SynthesisError}; +use bellman::{groth16, Circuit, ConstraintSystem, SynthesisError}; +use bls12_381::Bls12; use super::{value::NoteValue, PaymentAddress, ProofGenerationKey}; @@ -551,6 +553,82 @@ impl Circuit for Output { } } +/// The parameters for the Sapling Spend circuit. +pub struct SpendParameters(pub(crate) groth16::Parameters); + +impl SpendParameters { + /// Reads the parameters from their encoding. + /// + /// Only set `verify_point_encodings` to false if you are verifying the parameters in + /// another way (such as checking the hash of the parameters file on disk). + pub fn read(reader: R, verify_point_encodings: bool) -> io::Result { + groth16::Parameters::::read(reader, verify_point_encodings).map(Self) + } + + /// Returns the verifying key for the Sapling Spend circuit. + pub fn verifying_key(&self) -> SpendVerifyingKey { + SpendVerifyingKey(self.0.vk.clone()) + } + + /// Returns the verifying key for the Sapling Spend circuit, with precomputations + /// optimized for verifying individual proofs. + pub fn prepared_verifying_key(&self) -> PreparedSpendVerifyingKey { + PreparedSpendVerifyingKey(groth16::prepare_verifying_key(&self.0.vk)) + } +} + +/// The verifying key for the Sapling Spend circuit. +pub struct SpendVerifyingKey(pub(crate) groth16::VerifyingKey); + +impl SpendVerifyingKey { + /// Performs precomputations optimized for verifying individual proofs. + pub fn prepare(&self) -> PreparedSpendVerifyingKey { + PreparedSpendVerifyingKey(groth16::prepare_verifying_key(&self.0)) + } +} + +/// The verifying key for the Sapling Spend circuit, with precomputations optimized for +/// verifying individual proofs. +pub struct PreparedSpendVerifyingKey(pub(crate) groth16::PreparedVerifyingKey); + +/// The parameters for the Sapling Output circuit. +pub struct OutputParameters(pub(crate) groth16::Parameters); + +impl OutputParameters { + /// Reads the parameters from their encoding. + /// + /// Only set `verify_point_encodings` to false if you are verifying the parameters in + /// another way (such as checking the hash of the parameters file on disk). + pub fn read(reader: R, verify_point_encodings: bool) -> io::Result { + groth16::Parameters::::read(reader, verify_point_encodings).map(Self) + } + + /// Returns the verifying key for the Sapling Output circuit. + pub fn verifying_key(&self) -> OutputVerifyingKey { + OutputVerifyingKey(self.0.vk.clone()) + } + + /// Returns the verifying key for the Sapling Output circuit, with precomputations + /// optimized for verifying individual proofs. + pub fn prepared_verifying_key(&self) -> PreparedOutputVerifyingKey { + PreparedOutputVerifyingKey(groth16::prepare_verifying_key(&self.0.vk)) + } +} + +/// The verifying key for the Sapling Output circuit. +pub struct OutputVerifyingKey(pub(crate) groth16::VerifyingKey); + +impl OutputVerifyingKey { + /// Performs precomputations optimized for verifying individual proofs. + pub fn prepare(&self) -> PreparedOutputVerifyingKey { + PreparedOutputVerifyingKey(groth16::prepare_verifying_key(&self.0)) + } +} + +/// The verifying key for the Sapling Output circuit, with precomputations optimized for +/// verifying individual proofs. +pub struct PreparedOutputVerifyingKey(pub(crate) groth16::PreparedVerifyingKey); + #[test] fn test_input_circuit_with_bls12_381() { use crate::sapling::{pedersen_hash, Diversifier, Note, ProofGenerationKey, Rseed}; diff --git a/zcash_primitives/src/sapling/prover.rs b/zcash_primitives/src/sapling/prover.rs index 0933e8c20..e130e1d68 100644 --- a/zcash_primitives/src/sapling/prover.rs +++ b/zcash_primitives/src/sapling/prover.rs @@ -1,5 +1,7 @@ //! Abstractions over the proving system and parameters. +use bellman::groth16::{create_random_proof, Proof}; +use bls12_381::Bls12; use rand_core::RngCore; use crate::{ @@ -8,10 +10,13 @@ use crate::{ value::{NoteValue, ValueCommitTrapdoor}, MerklePath, }, - transaction::components::sapling::GrothProofBytes, + transaction::components::{sapling::GrothProofBytes, GROTH_PROOF_SIZE}, }; -use super::{Diversifier, PaymentAddress, ProofGenerationKey, Rseed}; +use super::{ + circuit::{Output, OutputParameters, Spend, SpendParameters, ValueCommitmentOpening}, + Diversifier, Note, PaymentAddress, ProofGenerationKey, Rseed, +}; /// Interface for creating Sapling Spend proofs. pub trait SpendProver { @@ -79,6 +84,102 @@ pub trait OutputProver { fn encode_proof(proof: Self::Proof) -> GrothProofBytes; } +impl SpendProver for SpendParameters { + type Proof = Proof; + + fn prepare_circuit( + proof_generation_key: ProofGenerationKey, + diversifier: Diversifier, + rseed: Rseed, + value: NoteValue, + alpha: jubjub::Fr, + rcv: ValueCommitTrapdoor, + anchor: bls12_381::Scalar, + merkle_path: MerklePath, + ) -> Option { + // Construct the value commitment + let value_commitment_opening = ValueCommitmentOpening { + value, + randomness: rcv.inner(), + }; + + // Construct the viewing key + let viewing_key = proof_generation_key.to_viewing_key(); + + // Construct the payment address with the viewing key / diversifier + let payment_address = viewing_key.to_payment_address(diversifier)?; + + let note = Note::from_parts(payment_address, value, rseed); + + // We now have the full witness for our circuit + let pos: u64 = merkle_path.position().into(); + Some(Spend { + value_commitment_opening: Some(value_commitment_opening), + proof_generation_key: Some(proof_generation_key), + payment_address: Some(payment_address), + commitment_randomness: Some(note.rcm()), + ar: Some(alpha), + auth_path: merkle_path + .path_elems() + .iter() + .enumerate() + .map(|(i, node)| Some(((*node).into(), pos >> i & 0x1 == 1))) + .collect(), + anchor: Some(anchor), + }) + } + + fn create_proof(&self, circuit: Spend, rng: &mut R) -> Self::Proof { + create_random_proof(circuit, &self.0, rng).expect("proving should not fail") + } + + fn encode_proof(proof: Self::Proof) -> GrothProofBytes { + let mut zkproof = [0u8; GROTH_PROOF_SIZE]; + proof + .write(&mut zkproof[..]) + .expect("should be able to serialize a proof"); + zkproof + } +} + +impl OutputProver for OutputParameters { + type Proof = Proof; + + fn prepare_circuit( + esk: jubjub::Fr, + payment_address: PaymentAddress, + rcm: jubjub::Fr, + value: NoteValue, + rcv: ValueCommitTrapdoor, + ) -> Output { + // Construct the value commitment for the proof instance + let value_commitment_opening = ValueCommitmentOpening { + value, + randomness: rcv.inner(), + }; + + // We now have a full witness for the output proof. + Output { + value_commitment_opening: Some(value_commitment_opening), + payment_address: Some(payment_address), + commitment_randomness: Some(rcm), + esk: Some(esk), + } + } + + fn create_proof(&self, circuit: Output, rng: &mut R) -> Self::Proof { + create_random_proof(circuit, &self.0, rng).expect("proving should not fail") + } + + fn encode_proof(proof: Self::Proof) -> GrothProofBytes { + let mut zkproof = [0u8; GROTH_PROOF_SIZE]; + proof + .write(&mut zkproof[..]) + .expect("should be able to serialize a proof"); + zkproof + } +} + #[cfg(any(test, feature = "test-dependencies"))] pub mod mock { use ff::Field; diff --git a/zcash_proofs/src/sapling/verifier.rs b/zcash_primitives/src/sapling/verifier.rs similarity index 99% rename from zcash_proofs/src/sapling/verifier.rs rename to zcash_primitives/src/sapling/verifier.rs index be7a9a0a2..36d1ffd49 100644 --- a/zcash_proofs/src/sapling/verifier.rs +++ b/zcash_primitives/src/sapling/verifier.rs @@ -1,7 +1,8 @@ use bellman::{gadgets::multipack, groth16::Proof}; use bls12_381::Bls12; use group::{ff::PrimeField, Curve, GroupEncoding}; -use zcash_primitives::{ + +use crate::{ sapling::{ note::ExtractedNoteCommitment, redjubjub::{PublicKey, Signature}, diff --git a/zcash_proofs/src/sapling/verifier/batch.rs b/zcash_primitives/src/sapling/verifier/batch.rs similarity index 94% rename from zcash_proofs/src/sapling/verifier/batch.rs rename to zcash_primitives/src/sapling/verifier/batch.rs index 2a87c5868..929675f05 100644 --- a/zcash_proofs/src/sapling/verifier/batch.rs +++ b/zcash_primitives/src/sapling/verifier/batch.rs @@ -2,9 +2,12 @@ use bellman::groth16; use bls12_381::Bls12; use group::GroupEncoding; use rand_core::{CryptoRng, RngCore}; -use zcash_primitives::transaction::components::sapling::{Authorized, Bundle}; use super::SaplingVerificationContextInner; +use crate::{ + sapling::circuit::{OutputVerifyingKey, SpendVerifyingKey}, + transaction::components::sapling::{Authorized, Bundle}, +}; /// Batch validation context for Sapling. /// @@ -145,8 +148,8 @@ impl BatchValidator { /// is desired, construct separate [`BatchValidator`]s for sub-batches of the bundles. pub fn validate( self, - spend_vk: &groth16::VerifyingKey, - output_vk: &groth16::VerifyingKey, + spend_vk: &SpendVerifyingKey, + output_vk: &OutputVerifyingKey, mut rng: R, ) -> bool { if !self.bundles_added { @@ -166,12 +169,12 @@ impl BatchValidator { let mut verify_proofs = |batch: groth16::batch::Verifier, vk| batch.verify(&mut rng, vk); - if verify_proofs(self.spend_proofs, spend_vk).is_err() { + if verify_proofs(self.spend_proofs, &spend_vk.0).is_err() { tracing::debug!("Spend proof batch validation failed"); return false; } - if verify_proofs(self.output_proofs, output_vk).is_err() { + if verify_proofs(self.output_proofs, &output_vk.0).is_err() { tracing::debug!("Output proof batch validation failed"); return false; } diff --git a/zcash_proofs/src/sapling/verifier/single.rs b/zcash_primitives/src/sapling/verifier/single.rs similarity index 88% rename from zcash_proofs/src/sapling/verifier/single.rs rename to zcash_primitives/src/sapling/verifier/single.rs index 94938374e..6c9ec9259 100644 --- a/zcash_proofs/src/sapling/verifier/single.rs +++ b/zcash_primitives/src/sapling/verifier/single.rs @@ -1,7 +1,10 @@ -use bellman::groth16::{verify_proof, PreparedVerifyingKey, Proof}; +use bellman::groth16::{verify_proof, Proof}; use bls12_381::Bls12; -use zcash_primitives::{ + +use super::SaplingVerificationContextInner; +use crate::{ sapling::{ + circuit::{PreparedOutputVerifyingKey, PreparedSpendVerifyingKey}, constants::{SPENDING_KEY_GENERATOR, VALUE_COMMITMENT_RANDOMNESS_GENERATOR}, note::ExtractedNoteCommitment, redjubjub::{PublicKey, Signature}, @@ -10,8 +13,6 @@ use zcash_primitives::{ transaction::components::Amount, }; -use super::SaplingVerificationContextInner; - /// A context object for verifying the Sapling components of a single Zcash transaction. pub struct SaplingVerificationContext { inner: SaplingVerificationContextInner, @@ -39,7 +40,7 @@ impl SaplingVerificationContext { sighash_value: &[u8; 32], spend_auth_sig: Signature, zkproof: Proof, - verifying_key: &PreparedVerifyingKey, + verifying_key: &PreparedSpendVerifyingKey, ) -> bool { let zip216_enabled = self.zip216_enabled; self.inner.check_spend( @@ -55,7 +56,7 @@ impl SaplingVerificationContext { rk.verify_with_zip216(&msg, spend_auth_sig, SPENDING_KEY_GENERATOR, zip216_enabled) }, |_, proof, public_inputs| { - verify_proof(verifying_key, &proof, &public_inputs[..]).is_ok() + verify_proof(&verifying_key.0, &proof, &public_inputs[..]).is_ok() }, ) } @@ -68,11 +69,11 @@ impl SaplingVerificationContext { cmu: ExtractedNoteCommitment, epk: jubjub::ExtendedPoint, zkproof: Proof, - verifying_key: &PreparedVerifyingKey, + verifying_key: &PreparedOutputVerifyingKey, ) -> bool { self.inner .check_output(cv, cmu, epk, zkproof, |proof, public_inputs| { - verify_proof(verifying_key, &proof, &public_inputs[..]).is_ok() + verify_proof(&verifying_key.0, &proof, &public_inputs[..]).is_ok() }) } diff --git a/zcash_proofs/CHANGELOG.md b/zcash_proofs/CHANGELOG.md index d95bcf422..2d3dbd2e2 100644 --- a/zcash_proofs/CHANGELOG.md +++ b/zcash_proofs/CHANGELOG.md @@ -7,19 +7,21 @@ and this library adheres to Rust's notion of ## [Unreleased] ### Added -- `zcash_proofs::{SpendParameters, OutputParameters}` - `impl zcash_primitives::sapling::prover::{SpendProver, OutputProver}` for `zcash_proofs::prover::LocalTxProver` ### Changed -- The `zcash_proofs::ZcashParameters::{spend_params, output_params}` fields - now have types `SpendParameters` and `OutputParameters` respectively. +- The `zcash_proofs::ZcashParameters` Sapling fields now use the parameter and + viewing key newtypes defined in `zcash_primitives::sapling::circuit`. ### Removed - `zcash_proofs::circuit::sapling` (moved to `zcash_primitives::sapling::circuit`). - `zcash_proofs::circuit::{ecc, pedersen_hash}` - `zcash_proofs::constants` -- `zcash_proofs::sapling::SaplingProvingContext` +- `zcash_proofs::sapling`: + - `BatchValidator` (moved to `zcash_primitives::sapling`). + - `SaplingProvingContext` + - `SaplingVerificationContext` (moved to `zcash_primitives::sapling`). ## [0.13.0] - 2023-09-25 ### Changed diff --git a/zcash_proofs/src/lib.rs b/zcash_proofs/src/lib.rs index bdd452bd4..8a9d85d67 100644 --- a/zcash_proofs/src/lib.rs +++ b/zcash_proofs/src/lib.rs @@ -9,8 +9,12 @@ // Temporary until we have addressed all Result cases. #![allow(clippy::result_unit_err)] -use bellman::groth16::{prepare_verifying_key, Parameters, PreparedVerifyingKey, VerifyingKey}; +use bellman::groth16::{prepare_verifying_key, PreparedVerifyingKey, VerifyingKey}; use bls12_381::Bls12; +use zcash_primitives::sapling::circuit::{ + OutputParameters, PreparedOutputVerifyingKey, PreparedSpendVerifyingKey, SpendParameters, +}; + use std::fs::File; use std::io::{self, BufReader}; use std::path::Path; @@ -20,7 +24,6 @@ use std::path::PathBuf; pub mod circuit; mod hashreader; -pub mod sapling; pub mod sprout; #[cfg(any(feature = "local-prover", feature = "bundled-prover"))] @@ -283,18 +286,12 @@ fn stream_params_downloads_to_disk( Ok(()) } -/// The parameters for the Sapling Spend circuit. -pub struct SpendParameters(Parameters); - -/// The parameters for the Sapling Output circuit. -pub struct OutputParameters(Parameters); - /// Zcash Sprout and Sapling groth16 circuit parameters. pub struct ZcashParameters { pub spend_params: SpendParameters, - pub spend_vk: PreparedVerifyingKey, + pub spend_vk: PreparedSpendVerifyingKey, pub output_params: OutputParameters, - pub output_vk: PreparedVerifyingKey, + pub output_vk: PreparedOutputVerifyingKey, pub sprout_vk: Option>, } @@ -355,9 +352,11 @@ pub fn load_parameters( ) } -/// Parse Bls12 keys from bytes as serialized by [`Parameters::write`]. +/// Parse Bls12 keys from bytes as serialized by [`groth16::Parameters::write`]. /// /// This function will panic if it encounters unparsable data. +/// +/// [`groth16::Parameters::write`]: bellman::groth16::Parameters::write pub fn parse_parameters( spend_fs: R, output_fs: R, @@ -368,10 +367,10 @@ pub fn parse_parameters( let mut sprout_fs = sprout_fs.map(hashreader::HashReader::new); // Deserialize params - let spend_params = Parameters::::read(&mut spend_fs, false) - .expect("couldn't deserialize Sapling spend parameters file"); - let output_params = Parameters::::read(&mut output_fs, false) - .expect("couldn't deserialize Sapling spend parameters file"); + let spend_params = SpendParameters::read(&mut spend_fs, false) + .expect("couldn't deserialize Sapling spend parameters"); + let output_params = OutputParameters::read(&mut output_fs, false) + .expect("couldn't deserialize Sapling spend parameters"); // We only deserialize the verifying key for the Sprout parameters, which // appears at the beginning of the parameter file. The rest is loaded @@ -430,14 +429,14 @@ pub fn parse_parameters( } // Prepare verifying keys - let spend_vk = prepare_verifying_key(&spend_params.vk); - let output_vk = prepare_verifying_key(&output_params.vk); + let spend_vk = spend_params.prepared_verifying_key(); + let output_vk = output_params.prepared_verifying_key(); let sprout_vk = sprout_vk.map(|vk| prepare_verifying_key(&vk)); ZcashParameters { - spend_params: SpendParameters(spend_params), + spend_params, spend_vk, - output_params: OutputParameters(output_params), + output_params, output_vk, sprout_vk, } diff --git a/zcash_proofs/src/prover.rs b/zcash_proofs/src/prover.rs index 18fad71cf..27eb3aeed 100644 --- a/zcash_proofs/src/prover.rs +++ b/zcash_proofs/src/prover.rs @@ -1,6 +1,6 @@ //! Abstractions over the proving system and parameters for ease of use. -use bellman::groth16::{PreparedVerifyingKey, Proof}; +use bellman::groth16::Proof; use bls12_381::Bls12; use std::path::Path; use zcash_primitives::{ @@ -18,14 +18,10 @@ use crate::{load_parameters, parse_parameters, OutputParameters, SpendParameters #[cfg(feature = "local-prover")] use crate::{default_params_folder, SAPLING_OUTPUT_NAME, SAPLING_SPEND_NAME}; -/// An implementation of [`TxProver`] using Sapling Spend and Output parameters from -/// locally-accessible paths. +/// An implementation of [`SpendProver`] and [`OutputProver`] using Sapling Spend and +/// Output parameters from locally-accessible paths. pub struct LocalTxProver { spend_params: SpendParameters, - // TODO: Either re-introduce verification-after-proving (once the verifier is - // refactored), or remove this. - #[allow(unused)] - spend_vk: PreparedVerifyingKey, output_params: OutputParameters, } @@ -52,7 +48,6 @@ impl LocalTxProver { let p = load_parameters(spend_path, output_path, None); LocalTxProver { spend_params: p.spend_params, - spend_vk: p.spend_vk, output_params: p.output_params, } } @@ -77,7 +72,6 @@ impl LocalTxProver { LocalTxProver { spend_params: p.spend_params, - spend_vk: p.spend_vk, output_params: p.output_params, } } @@ -134,7 +128,6 @@ impl LocalTxProver { LocalTxProver { spend_params: p.spend_params, - spend_vk: p.spend_vk, output_params: p.output_params, } } diff --git a/zcash_proofs/src/sapling/mod.rs b/zcash_proofs/src/sapling/mod.rs deleted file mode 100644 index 1faf0ab09..000000000 --- a/zcash_proofs/src/sapling/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! Helpers for creating Sapling proofs. - -mod prover; -mod verifier; - -pub use self::verifier::{BatchValidator, SaplingVerificationContext}; diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs deleted file mode 100644 index f7c1d59dd..000000000 --- a/zcash_proofs/src/sapling/prover.rs +++ /dev/null @@ -1,110 +0,0 @@ -use bellman::groth16::{create_random_proof, Proof}; -use bls12_381::Bls12; -use rand_core::RngCore; -use zcash_primitives::{ - sapling::{ - circuit::{Output, Spend, ValueCommitmentOpening}, - prover::{OutputProver, SpendProver}, - value::{NoteValue, ValueCommitTrapdoor}, - Diversifier, MerklePath, Note, PaymentAddress, ProofGenerationKey, Rseed, - }, - transaction::components::{sapling::GrothProofBytes, GROTH_PROOF_SIZE}, -}; - -use crate::{OutputParameters, SpendParameters}; - -impl SpendProver for SpendParameters { - type Proof = Proof; - - fn prepare_circuit( - proof_generation_key: ProofGenerationKey, - diversifier: Diversifier, - rseed: Rseed, - value: NoteValue, - alpha: jubjub::Fr, - rcv: ValueCommitTrapdoor, - anchor: bls12_381::Scalar, - merkle_path: MerklePath, - ) -> Option { - // Construct the value commitment - let value_commitment_opening = ValueCommitmentOpening { - value, - randomness: rcv.inner(), - }; - - // Construct the viewing key - let viewing_key = proof_generation_key.to_viewing_key(); - - // Construct the payment address with the viewing key / diversifier - let payment_address = viewing_key.to_payment_address(diversifier)?; - - let note = Note::from_parts(payment_address, value, rseed); - - // We now have the full witness for our circuit - let pos: u64 = merkle_path.position().into(); - Some(Spend { - value_commitment_opening: Some(value_commitment_opening), - proof_generation_key: Some(proof_generation_key), - payment_address: Some(payment_address), - commitment_randomness: Some(note.rcm()), - ar: Some(alpha), - auth_path: merkle_path - .path_elems() - .iter() - .enumerate() - .map(|(i, node)| Some(((*node).into(), pos >> i & 0x1 == 1))) - .collect(), - anchor: Some(anchor), - }) - } - - fn create_proof(&self, circuit: Spend, rng: &mut R) -> Self::Proof { - create_random_proof(circuit, &self.0, rng).expect("proving should not fail") - } - - fn encode_proof(proof: Self::Proof) -> GrothProofBytes { - let mut zkproof = [0u8; GROTH_PROOF_SIZE]; - proof - .write(&mut zkproof[..]) - .expect("should be able to serialize a proof"); - zkproof - } -} - -impl OutputProver for OutputParameters { - type Proof = Proof; - - fn prepare_circuit( - esk: jubjub::Fr, - payment_address: PaymentAddress, - rcm: jubjub::Fr, - value: NoteValue, - rcv: ValueCommitTrapdoor, - ) -> Output { - // Construct the value commitment for the proof instance - let value_commitment_opening = ValueCommitmentOpening { - value, - randomness: rcv.inner(), - }; - - // We now have a full witness for the output proof. - Output { - value_commitment_opening: Some(value_commitment_opening), - payment_address: Some(payment_address), - commitment_randomness: Some(rcm), - esk: Some(esk), - } - } - - fn create_proof(&self, circuit: Output, rng: &mut R) -> Self::Proof { - create_random_proof(circuit, &self.0, rng).expect("proving should not fail") - } - - fn encode_proof(proof: Self::Proof) -> GrothProofBytes { - let mut zkproof = [0u8; GROTH_PROOF_SIZE]; - proof - .write(&mut zkproof[..]) - .expect("should be able to serialize a proof"); - zkproof - } -}