Skip to content

Commit

Permalink
Merge pull request #1006 from zcash/spend-output-prover-updates
Browse files Browse the repository at this point in the history
Updates to `SpendProver` and `OutputProver` traits and impls
  • Loading branch information
str4d authored Oct 6, 2023
2 parents e6fa567 + 04aa5a0 commit 4737839
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 9 deletions.
2 changes: 2 additions & 0 deletions zcash_primitives/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`:
Expand Down
100 changes: 97 additions & 3 deletions zcash_primitives/src/sapling/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -123,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<sapling::circuit::Spend> {
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<R: rand_core::RngCore>(
&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<R: rand_core::RngCore>(
&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 {
Expand Down
4 changes: 3 additions & 1 deletion zcash_proofs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
81 changes: 77 additions & 4 deletions zcash_proofs/src/prover.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down Expand Up @@ -143,6 +144,78 @@ impl LocalTxProver {
}
}

impl SpendProver for LocalTxProver {
type Proof = Proof<Bls12>;

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<sapling::circuit::Spend> {
SpendParameters::prepare_circuit(
proof_generation_key,
diversifier,
rseed,
value,
alpha,
rcv,
anchor,
merkle_path,
)
}

fn create_proof<R: rand_core::RngCore>(
&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<Bls12>;

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<R: rand_core::RngCore>(
&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;

Expand Down
18 changes: 17 additions & 1 deletion zcash_proofs/src/sapling/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -64,6 +64,14 @@ impl SpendProver for SpendParameters {
fn create_proof<R: RngCore>(&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 {
Expand Down Expand Up @@ -94,6 +102,14 @@ impl OutputProver for OutputParameters {
fn create_proof<R: RngCore>(&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.
Expand Down

0 comments on commit 4737839

Please sign in to comment.