From 8bb9c4e7baac236e14d306037750b85aa90fc1b9 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 3 Nov 2023 06:15:37 +0000 Subject: [PATCH 1/4] Move Sapling proof verifiers from `zcash_proofs` to `zcash_primitives` --- Cargo.lock | 2 ++ zcash_primitives/CHANGELOG.md | 2 ++ zcash_primitives/Cargo.toml | 4 +++- zcash_primitives/src/sapling.rs | 2 ++ {zcash_proofs => zcash_primitives}/src/sapling/verifier.rs | 3 ++- .../src/sapling/verifier/batch.rs | 2 +- .../src/sapling/verifier/single.rs | 6 +++--- zcash_proofs/CHANGELOG.md | 5 ++++- zcash_proofs/src/sapling/mod.rs | 3 --- 9 files changed, 19 insertions(+), 10 deletions(-) rename {zcash_proofs => zcash_primitives}/src/sapling/verifier.rs (99%) rename {zcash_proofs => zcash_primitives}/src/sapling/verifier/batch.rs (98%) rename {zcash_proofs => zcash_primitives}/src/sapling/verifier/single.rs (99%) diff --git a/Cargo.lock b/Cargo.lock index 314ffd5ef..466ffd2ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3105,10 +3105,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..d8d94f23d 100644 --- a/zcash_primitives/CHANGELOG.md +++ b/zcash_primitives/CHANGELOG.md @@ -9,6 +9,8 @@ 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`). - `constants` module. - `prover::{SpendProver, OutputProver}` 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_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 98% rename from zcash_proofs/src/sapling/verifier/batch.rs rename to zcash_primitives/src/sapling/verifier/batch.rs index 2a87c5868..40eb68665 100644 --- a/zcash_proofs/src/sapling/verifier/batch.rs +++ b/zcash_primitives/src/sapling/verifier/batch.rs @@ -2,9 +2,9 @@ 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::transaction::components::sapling::{Authorized, Bundle}; /// Batch validation context for Sapling. /// diff --git a/zcash_proofs/src/sapling/verifier/single.rs b/zcash_primitives/src/sapling/verifier/single.rs similarity index 99% rename from zcash_proofs/src/sapling/verifier/single.rs rename to zcash_primitives/src/sapling/verifier/single.rs index 94938374e..a4bfbcc32 100644 --- a/zcash_proofs/src/sapling/verifier/single.rs +++ b/zcash_primitives/src/sapling/verifier/single.rs @@ -1,6 +1,8 @@ use bellman::groth16::{verify_proof, PreparedVerifyingKey, Proof}; use bls12_381::Bls12; -use zcash_primitives::{ + +use super::SaplingVerificationContextInner; +use crate::{ sapling::{ constants::{SPENDING_KEY_GENERATOR, VALUE_COMMITMENT_RANDOMNESS_GENERATOR}, note::ExtractedNoteCommitment, @@ -10,8 +12,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, diff --git a/zcash_proofs/CHANGELOG.md b/zcash_proofs/CHANGELOG.md index d95bcf422..8fd4e5504 100644 --- a/zcash_proofs/CHANGELOG.md +++ b/zcash_proofs/CHANGELOG.md @@ -19,7 +19,10 @@ and this library adheres to Rust's notion of - `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/sapling/mod.rs b/zcash_proofs/src/sapling/mod.rs index 1faf0ab09..ad1bb4566 100644 --- a/zcash_proofs/src/sapling/mod.rs +++ b/zcash_proofs/src/sapling/mod.rs @@ -1,6 +1,3 @@ //! Helpers for creating Sapling proofs. mod prover; -mod verifier; - -pub use self::verifier::{BatchValidator, SaplingVerificationContext}; From 1b9f26c984257bc5f49c748703a672d8a44d8896 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 3 Nov 2023 06:38:27 +0000 Subject: [PATCH 2/4] Move `{Spend,Output}Parameters` from `zcash_proofs` to `zcash_primitives` --- zcash_primitives/CHANGELOG.md | 1 + zcash_primitives/src/sapling/circuit.rs | 40 ++++++++- zcash_primitives/src/sapling/prover.rs | 105 +++++++++++++++++++++- zcash_proofs/CHANGELOG.md | 4 +- zcash_proofs/src/lib.rs | 31 +++---- zcash_proofs/src/sapling/mod.rs | 3 - zcash_proofs/src/sapling/prover.rs | 110 ------------------------ 7 files changed, 159 insertions(+), 135 deletions(-) delete mode 100644 zcash_proofs/src/sapling/mod.rs delete mode 100644 zcash_proofs/src/sapling/prover.rs diff --git a/zcash_primitives/CHANGELOG.md b/zcash_primitives/CHANGELOG.md index d8d94f23d..6c4e47417 100644 --- a/zcash_primitives/CHANGELOG.md +++ b/zcash_primitives/CHANGELOG.md @@ -12,6 +12,7 @@ and this library adheres to Rust's notion of - `BatchValidator` (moved from `zcash_proofs::sapling`). - `SaplingVerificationContext` (moved from `zcash_proofs::sapling`). - `circuit` module (moved from `zcash_proofs::circuit::sapling`). + - `circuit::{SpendParameters, OutputParameters}` - `constants` module. - `prover::{SpendProver, OutputProver}` - `value`: diff --git a/zcash_primitives/src/sapling/circuit.rs b/zcash_primitives/src/sapling/circuit.rs index a2fece4d6..74556d95f 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,42 @@ 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) -> &groth16::VerifyingKey { + &self.0.vk + } +} + +/// 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) -> &groth16::VerifyingKey { + &self.0.vk + } +} + #[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/CHANGELOG.md b/zcash_proofs/CHANGELOG.md index 8fd4e5504..327d5e9b8 100644 --- a/zcash_proofs/CHANGELOG.md +++ b/zcash_proofs/CHANGELOG.md @@ -7,13 +7,13 @@ 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. + now have types `zcash_primitives::sapling::circuit::SpendParameters` and + `zcash_primitives::sapling::circuit::OutputParameters` respectively. ### Removed - `zcash_proofs::circuit::sapling` (moved to `zcash_primitives::sapling::circuit`). diff --git a/zcash_proofs/src/lib.rs b/zcash_proofs/src/lib.rs index bdd452bd4..c3fb0fdd6 100644 --- a/zcash_proofs/src/lib.rs +++ b/zcash_proofs/src/lib.rs @@ -9,8 +9,10 @@ // 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, SpendParameters}; + use std::fs::File; use std::io::{self, BufReader}; use std::path::Path; @@ -20,7 +22,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,12 +284,6 @@ 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, @@ -355,9 +350,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 +365,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 +427,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 = prepare_verifying_key(spend_params.verifying_key()); + let output_vk = prepare_verifying_key(output_params.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/sapling/mod.rs b/zcash_proofs/src/sapling/mod.rs deleted file mode 100644 index ad1bb4566..000000000 --- a/zcash_proofs/src/sapling/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! Helpers for creating Sapling proofs. - -mod prover; 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 - } -} From 82535112c2d4de9c31824eb6e8afe3724990cd17 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 3 Nov 2023 07:10:32 +0000 Subject: [PATCH 3/4] zcash_primitives: Add Sapling verification key newtypes --- zcash_primitives/CHANGELOG.md | 7 +++ zcash_primitives/src/sapling/circuit.rs | 48 +++++++++++++++++-- .../src/sapling/verifier/batch.rs | 13 +++-- .../src/sapling/verifier/single.rs | 11 +++-- zcash_proofs/CHANGELOG.md | 5 +- zcash_proofs/src/lib.rs | 12 +++-- zcash_proofs/src/prover.rs | 9 +--- 7 files changed, 75 insertions(+), 30 deletions(-) diff --git a/zcash_primitives/CHANGELOG.md b/zcash_primitives/CHANGELOG.md index 6c4e47417..52c64dc4d 100644 --- a/zcash_primitives/CHANGELOG.md +++ b/zcash_primitives/CHANGELOG.md @@ -13,6 +13,8 @@ and this library adheres to Rust's notion of - `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`: @@ -61,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/src/sapling/circuit.rs b/zcash_primitives/src/sapling/circuit.rs index 74556d95f..d1fe6bfcf 100644 --- a/zcash_primitives/src/sapling/circuit.rs +++ b/zcash_primitives/src/sapling/circuit.rs @@ -566,11 +566,31 @@ impl SpendParameters { } /// Returns the verifying key for the Sapling Spend circuit. - pub fn verifying_key(&self) -> &groth16::VerifyingKey { - &self.0.vk + 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); @@ -584,11 +604,31 @@ impl OutputParameters { } /// Returns the verifying key for the Sapling Output circuit. - pub fn verifying_key(&self) -> &groth16::VerifyingKey { - &self.0.vk + 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/verifier/batch.rs b/zcash_primitives/src/sapling/verifier/batch.rs index 40eb68665..929675f05 100644 --- a/zcash_primitives/src/sapling/verifier/batch.rs +++ b/zcash_primitives/src/sapling/verifier/batch.rs @@ -4,7 +4,10 @@ use group::GroupEncoding; use rand_core::{CryptoRng, RngCore}; use super::SaplingVerificationContextInner; -use crate::transaction::components::sapling::{Authorized, Bundle}; +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_primitives/src/sapling/verifier/single.rs b/zcash_primitives/src/sapling/verifier/single.rs index a4bfbcc32..6c9ec9259 100644 --- a/zcash_primitives/src/sapling/verifier/single.rs +++ b/zcash_primitives/src/sapling/verifier/single.rs @@ -1,9 +1,10 @@ -use bellman::groth16::{verify_proof, PreparedVerifyingKey, Proof}; +use bellman::groth16::{verify_proof, Proof}; use bls12_381::Bls12; use super::SaplingVerificationContextInner; use crate::{ sapling::{ + circuit::{PreparedOutputVerifyingKey, PreparedSpendVerifyingKey}, constants::{SPENDING_KEY_GENERATOR, VALUE_COMMITMENT_RANDOMNESS_GENERATOR}, note::ExtractedNoteCommitment, redjubjub::{PublicKey, Signature}, @@ -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 327d5e9b8..2d3dbd2e2 100644 --- a/zcash_proofs/CHANGELOG.md +++ b/zcash_proofs/CHANGELOG.md @@ -11,9 +11,8 @@ and this library adheres to Rust's notion of `zcash_proofs::prover::LocalTxProver` ### Changed -- The `zcash_proofs::ZcashParameters::{spend_params, output_params}` fields - now have types `zcash_primitives::sapling::circuit::SpendParameters` and - `zcash_primitives::sapling::circuit::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`). diff --git a/zcash_proofs/src/lib.rs b/zcash_proofs/src/lib.rs index c3fb0fdd6..8a9d85d67 100644 --- a/zcash_proofs/src/lib.rs +++ b/zcash_proofs/src/lib.rs @@ -11,7 +11,9 @@ use bellman::groth16::{prepare_verifying_key, PreparedVerifyingKey, VerifyingKey}; use bls12_381::Bls12; -use zcash_primitives::sapling::circuit::{OutputParameters, SpendParameters}; +use zcash_primitives::sapling::circuit::{ + OutputParameters, PreparedOutputVerifyingKey, PreparedSpendVerifyingKey, SpendParameters, +}; use std::fs::File; use std::io::{self, BufReader}; @@ -287,9 +289,9 @@ fn stream_params_downloads_to_disk( /// 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>, } @@ -427,8 +429,8 @@ pub fn parse_parameters( } // Prepare verifying keys - let spend_vk = prepare_verifying_key(spend_params.verifying_key()); - let output_vk = prepare_verifying_key(output_params.verifying_key()); + 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 { diff --git a/zcash_proofs/src/prover.rs b/zcash_proofs/src/prover.rs index 18fad71cf..75f42607b 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::{ @@ -22,10 +22,6 @@ use crate::{default_params_folder, SAPLING_OUTPUT_NAME, SAPLING_SPEND_NAME}; /// 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, } } From c56ab0001ebe43ccf0a22e8f2597a674ec18a6ef Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 3 Nov 2023 22:40:32 +0000 Subject: [PATCH 4/4] Fix intra-doc link --- zcash_proofs/src/prover.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zcash_proofs/src/prover.rs b/zcash_proofs/src/prover.rs index 75f42607b..27eb3aeed 100644 --- a/zcash_proofs/src/prover.rs +++ b/zcash_proofs/src/prover.rs @@ -18,8 +18,8 @@ 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, output_params: OutputParameters,