Merge pull request #1033 from zcash/sapling-params-refactor
Introduce newtypes for Sapling circuit parameters
This commit is contained in:
commit
64d657ed31
|
@ -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)",
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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<R: RngCore + CryptoRng>(
|
||||
|
|
|
@ -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<bls12_381::Scalar> for Output {
|
|||
}
|
||||
}
|
||||
|
||||
/// The parameters for the Sapling Spend circuit.
|
||||
pub struct SpendParameters(pub(crate) groth16::Parameters<Bls12>);
|
||||
|
||||
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<R: io::Read>(reader: R, verify_point_encodings: bool) -> io::Result<Self> {
|
||||
groth16::Parameters::<Bls12>::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<Bls12>);
|
||||
|
||||
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<Bls12>);
|
||||
|
||||
/// The parameters for the Sapling Output circuit.
|
||||
pub struct OutputParameters(pub(crate) groth16::Parameters<Bls12>);
|
||||
|
||||
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<R: io::Read>(reader: R, verify_point_encodings: bool) -> io::Result<Self> {
|
||||
groth16::Parameters::<Bls12>::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<Bls12>);
|
||||
|
||||
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<Bls12>);
|
||||
|
||||
#[test]
|
||||
fn test_input_circuit_with_bls12_381() {
|
||||
use crate::sapling::{pedersen_hash, Diversifier, Note, ProofGenerationKey, Rseed};
|
||||
|
|
|
@ -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<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<Spend> {
|
||||
// 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<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 {
|
||||
type Proof = Proof<Bls12>;
|
||||
|
||||
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<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
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-dependencies"))]
|
||||
pub mod mock {
|
||||
use ff::Field;
|
||||
|
|
|
@ -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},
|
|
@ -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<R: RngCore + CryptoRng>(
|
||||
self,
|
||||
spend_vk: &groth16::VerifyingKey<Bls12>,
|
||||
output_vk: &groth16::VerifyingKey<Bls12>,
|
||||
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<Bls12>, 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;
|
||||
}
|
|
@ -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<Bls12>,
|
||||
verifying_key: &PreparedVerifyingKey<Bls12>,
|
||||
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<Bls12>,
|
||||
verifying_key: &PreparedVerifyingKey<Bls12>,
|
||||
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()
|
||||
})
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -9,8 +9,12 @@
|
|||
// Temporary until we have addressed all Result<T, ()> 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<Bls12>);
|
||||
|
||||
/// The parameters for the Sapling Output circuit.
|
||||
pub struct OutputParameters(Parameters<Bls12>);
|
||||
|
||||
/// Zcash Sprout and Sapling groth16 circuit parameters.
|
||||
pub struct ZcashParameters {
|
||||
pub spend_params: SpendParameters,
|
||||
pub spend_vk: PreparedVerifyingKey<Bls12>,
|
||||
pub spend_vk: PreparedSpendVerifyingKey,
|
||||
pub output_params: OutputParameters,
|
||||
pub output_vk: PreparedVerifyingKey<Bls12>,
|
||||
pub output_vk: PreparedOutputVerifyingKey,
|
||||
pub sprout_vk: Option<PreparedVerifyingKey<Bls12>>,
|
||||
}
|
||||
|
||||
|
@ -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<R: io::Read>(
|
||||
spend_fs: R,
|
||||
output_fs: R,
|
||||
|
@ -368,10 +367,10 @@ pub fn parse_parameters<R: io::Read>(
|
|||
let mut sprout_fs = sprout_fs.map(hashreader::HashReader::new);
|
||||
|
||||
// Deserialize params
|
||||
let spend_params = Parameters::<Bls12>::read(&mut spend_fs, false)
|
||||
.expect("couldn't deserialize Sapling spend parameters file");
|
||||
let output_params = Parameters::<Bls12>::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<R: io::Read>(
|
|||
}
|
||||
|
||||
// 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,
|
||||
}
|
||||
|
|
|
@ -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<Bls12>,
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
//! Helpers for creating Sapling proofs.
|
||||
|
||||
mod prover;
|
||||
mod verifier;
|
||||
|
||||
pub use self::verifier::{BatchValidator, SaplingVerificationContext};
|
|
@ -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<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<Spend> {
|
||||
// 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<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 {
|
||||
type Proof = Proof<Bls12>;
|
||||
|
||||
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<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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue