From 296f75954bc693d372cd6fd1bd8cccbb9fa6c5c3 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 6 Oct 2023 20:19:41 +0000 Subject: [PATCH 1/3] Add `SpendProver::encode_proof` and `OutputProver::encode_proof` --- zcash_primitives/src/sapling/prover.rs | 12 +++++++++++- zcash_proofs/src/sapling/prover.rs | 18 +++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/zcash_primitives/src/sapling/prover.rs b/zcash_primitives/src/sapling/prover.rs index 4f1d32ebe..50af2e1db 100644 --- a/zcash_primitives/src/sapling/prover.rs +++ b/zcash_primitives/src/sapling/prover.rs @@ -9,7 +9,7 @@ use crate::{ value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, MerklePath, }, - transaction::components::{Amount, GROTH_PROOF_SIZE}, + transaction::components::{sapling::GrothProofBytes, Amount, GROTH_PROOF_SIZE}, }; use super::{Diversifier, PaymentAddress, ProofGenerationKey, Rseed}; @@ -42,6 +42,11 @@ pub trait SpendProver { circuit: sapling::circuit::Spend, rng: &mut R, ) -> Self::Proof; + + /// Encodes the given Sapling [`SpendDescription`] proof, erasing its type. + /// + /// [`SpendDescription`]: crate::transaction::components::SpendDescription + fn encode_proof(proof: Self::Proof) -> GrothProofBytes; } /// Interface for creating Sapling Output proofs. @@ -68,6 +73,11 @@ pub trait OutputProver { circuit: sapling::circuit::Output, rng: &mut R, ) -> Self::Proof; + + /// Encodes the given Sapling [`OutputDescription`] proof, erasing its type. + /// + /// [`OutputDescription`]: crate::transaction::components::OutputDescription + fn encode_proof(proof: Self::Proof) -> GrothProofBytes; } /// Interface for creating zero-knowledge proofs for shielded transactions. diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index faac73e99..7255783c7 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -11,7 +11,7 @@ use zcash_primitives::{ value::{CommitmentSum, NoteValue, TrapdoorSum, ValueCommitTrapdoor, ValueCommitment}, Diversifier, MerklePath, Note, PaymentAddress, ProofGenerationKey, Rseed, }, - transaction::components::Amount, + transaction::components::{sapling::GrothProofBytes, Amount, GROTH_PROOF_SIZE}, }; use crate::{OutputParameters, SpendParameters}; @@ -64,6 +64,14 @@ impl SpendProver for SpendParameters { 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 { @@ -94,6 +102,14 @@ impl OutputProver for OutputParameters { 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 + } } /// A context object for creating the Sapling components of a Zcash transaction. From 46903fabf5061403baecf8fb88942f1482690e5a Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 6 Oct 2023 20:25:07 +0000 Subject: [PATCH 2/3] zcash_proofs: `impl {SpendProver, OutputProver} for LocalTxProver` --- zcash_proofs/CHANGELOG.md | 4 +- zcash_proofs/src/prover.rs | 81 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 5 deletions(-) diff --git a/zcash_proofs/CHANGELOG.md b/zcash_proofs/CHANGELOG.md index f544343b6..1971f9359 100644 --- a/zcash_proofs/CHANGELOG.md +++ b/zcash_proofs/CHANGELOG.md @@ -8,6 +8,8 @@ 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 new `SpendParameters` and `OutputParameters` types are used in the @@ -110,7 +112,7 @@ and this library adheres to Rust's notion of ### Added - `zcash_proofs::ZcashParameters` - `zcash_proofs::parse_parameters` -- `zcash_proofs::prover::LocalProver::from_bytes` +- `zcash_proofs::prover::LocalTxProver::from_bytes` - The `zcash_proofs::constants` module, containing constants and helpers used by the `zcash_proofs::circuit::ecc::fixed_base_multiplication` gadget: - The `FixedGeneratorOwned` type alias. diff --git a/zcash_proofs/src/prover.rs b/zcash_proofs/src/prover.rs index 8bbd1abff..3ddbcfcd4 100644 --- a/zcash_proofs/src/prover.rs +++ b/zcash_proofs/src/prover.rs @@ -1,16 +1,17 @@ //! Abstractions over the proving system and parameters for ease of use. -use bellman::groth16::PreparedVerifyingKey; +use bellman::groth16::{PreparedVerifyingKey, Proof}; use bls12_381::Bls12; use std::path::Path; use zcash_primitives::{ sapling::{ - prover::TxProver, + self, + prover::{OutputProver, SpendProver, TxProver}, redjubjub::{PublicKey, Signature}, - value::ValueCommitment, + value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, Diversifier, MerklePath, PaymentAddress, ProofGenerationKey, Rseed, }, - transaction::components::{Amount, GROTH_PROOF_SIZE}, + transaction::components::{sapling::GrothProofBytes, Amount, GROTH_PROOF_SIZE}, }; use crate::{ @@ -143,6 +144,78 @@ impl LocalTxProver { } } +impl SpendProver for LocalTxProver { + 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 { + SpendParameters::prepare_circuit( + proof_generation_key, + diversifier, + rseed, + value, + alpha, + rcv, + anchor, + merkle_path, + ) + } + + fn create_proof( + &self, + circuit: sapling::circuit::Spend, + rng: &mut R, + ) -> Self::Proof { + self.spend_params.create_proof(circuit, rng) + } + + 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 LocalTxProver { + type Proof = Proof; + + fn prepare_circuit( + esk: jubjub::Fr, + payment_address: PaymentAddress, + rcm: jubjub::Fr, + value: NoteValue, + rcv: ValueCommitTrapdoor, + ) -> sapling::circuit::Output { + OutputParameters::prepare_circuit(esk, payment_address, rcm, value, rcv) + } + + fn create_proof( + &self, + circuit: sapling::circuit::Output, + rng: &mut R, + ) -> Self::Proof { + self.output_params.create_proof(circuit, rng) + } + + 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 TxProver for LocalTxProver { type SaplingProvingContext = SaplingProvingContext; From 04aa5a044b7c3623b62f0b5642b2b3ff4b6216bd Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 6 Oct 2023 20:31:31 +0000 Subject: [PATCH 3/3] zcash_primitives: Add `MockSpendProver` and `MockOutputProver` These are analogues of `MockTxProver` in that they implement the corresponding Sapling prover traits. --- zcash_primitives/CHANGELOG.md | 2 + zcash_primitives/src/sapling/prover.rs | 88 +++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/zcash_primitives/CHANGELOG.md b/zcash_primitives/CHANGELOG.md index 5db0809c4..0cc06dc31 100644 --- a/zcash_primitives/CHANGELOG.md +++ b/zcash_primitives/CHANGELOG.md @@ -12,6 +12,8 @@ and this library adheres to Rust's notion of - `circuit` module (moved from `zcash_proofs::circuit::sapling`). - `constants` module. - `prover::{SpendProver, OutputProver}` +- Test helpers, behind the `test-dependencies` feature flag: + - `zcash_primitives::prover::mock::{MockSpendProver, MockOutputProver}` ### Removed - `zcash_primitives::constants`: diff --git a/zcash_primitives/src/sapling/prover.rs b/zcash_primitives/src/sapling/prover.rs index 50af2e1db..e047d2dcc 100644 --- a/zcash_primitives/src/sapling/prover.rs +++ b/zcash_primitives/src/sapling/prover.rs @@ -133,20 +133,104 @@ pub trait TxProver { #[cfg(any(test, feature = "test-dependencies"))] pub mod mock { + use ff::Field; use rand_core::OsRng; - use super::TxProver; + use super::{OutputProver, SpendProver, TxProver}; use crate::{ sapling::{ self, + circuit::ValueCommitmentOpening, constants::SPENDING_KEY_GENERATOR, redjubjub::{PublicKey, Signature}, value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, Diversifier, PaymentAddress, ProofGenerationKey, Rseed, }, - transaction::components::{Amount, GROTH_PROOF_SIZE}, + transaction::components::{sapling::GrothProofBytes, Amount, GROTH_PROOF_SIZE}, }; + pub struct MockSpendProver; + + impl SpendProver for MockSpendProver { + type Proof = GrothProofBytes; + + fn prepare_circuit( + proof_generation_key: ProofGenerationKey, + diversifier: Diversifier, + _rseed: Rseed, + value: NoteValue, + alpha: jubjub::Fr, + rcv: ValueCommitTrapdoor, + anchor: bls12_381::Scalar, + _merkle_path: sapling::MerklePath, + ) -> Option { + let payment_address = proof_generation_key + .to_viewing_key() + .ivk() + .to_payment_address(diversifier); + Some(sapling::circuit::Spend { + value_commitment_opening: Some(ValueCommitmentOpening { + value: value.inner(), + randomness: rcv.inner(), + }), + proof_generation_key: Some(proof_generation_key), + payment_address, + commitment_randomness: Some(jubjub::Scalar::ZERO), + ar: Some(alpha), + auth_path: vec![], + anchor: Some(anchor), + }) + } + + fn create_proof( + &self, + _circuit: sapling::circuit::Spend, + _rng: &mut R, + ) -> Self::Proof { + [0u8; GROTH_PROOF_SIZE] + } + + fn encode_proof(proof: Self::Proof) -> GrothProofBytes { + proof + } + } + + pub struct MockOutputProver; + + impl OutputProver for MockOutputProver { + type Proof = GrothProofBytes; + + fn prepare_circuit( + esk: jubjub::Fr, + payment_address: PaymentAddress, + rcm: jubjub::Fr, + value: NoteValue, + rcv: ValueCommitTrapdoor, + ) -> sapling::circuit::Output { + sapling::circuit::Output { + value_commitment_opening: Some(ValueCommitmentOpening { + value: value.inner(), + randomness: rcv.inner(), + }), + payment_address: Some(payment_address), + commitment_randomness: Some(rcm), + esk: Some(esk), + } + } + + fn create_proof( + &self, + _circuit: sapling::circuit::Output, + _rng: &mut R, + ) -> Self::Proof { + [0u8; GROTH_PROOF_SIZE] + } + + fn encode_proof(proof: Self::Proof) -> GrothProofBytes { + proof + } + } + pub struct MockTxProver; impl TxProver for MockTxProver {