From d471aa3d53678cf91ec68d13e4f0f7135e9cbd85 Mon Sep 17 00:00:00 2001 From: redshiftzero Date: Thu, 4 Jan 2024 19:34:31 -0500 Subject: [PATCH] refactor: define public, private structs for spend, nullifier derivation and delegator vote circuits (#3571) * refactor: define `NullifierDerivationProof` public and private data * refactor: define `SpendProof` public and private data * refactor: define `DelegatorVoteProof` public and private data * refactor: make new methods private, use DummyWitness in benches and remove no longer needed clippy exceptions --- crates/bench/benches/delegator_vote.rs | 90 ++---- crates/bench/benches/nullifier_derivation.rs | 28 +- crates/bench/benches/spend.rs | 83 ++--- crates/bin/pcli/tests/proof.rs | 75 +++-- .../src/action_handler/delegator_vote.rs | 18 +- .../governance/src/delegator_vote.rs | 4 +- .../governance/src/delegator_vote/plan.rs | 29 +- .../governance/src/delegator_vote/proof.rs | 192 ++++++------ crates/core/component/governance/src/lib.rs | 2 +- .../src/component/action_handler/spend.rs | 16 +- .../core/component/shielded-pool/src/lib.rs | 9 +- .../shielded-pool/src/nullifier_derivation.rs | 105 ++++--- .../core/component/shielded-pool/src/spend.rs | 2 +- .../component/shielded-pool/src/spend/plan.rs | 28 +- .../shielded-pool/src/spend/proof.rs | 296 +++++++++++------- 15 files changed, 520 insertions(+), 457 deletions(-) diff --git a/crates/bench/benches/delegator_vote.rs b/crates/bench/benches/delegator_vote.rs index b15b7ac0d7..7517a5128c 100644 --- a/crates/bench/benches/delegator_vote.rs +++ b/crates/bench/benches/delegator_vote.rs @@ -6,10 +6,12 @@ use ark_relations::r1cs::{ }; use decaf377::{Fq, Fr}; use decaf377_rdsa::{SpendAuth, VerificationKey}; -use penumbra_asset::{balance, Value}; -use penumbra_governance::{DelegatorVoteCircuit, DelegatorVoteProof}; -use penumbra_keys::keys::{Bip44Path, NullifierKey, SeedPhrase, SpendKey}; -use penumbra_proof_params::DELEGATOR_VOTE_PROOF_PROVING_KEY; +use penumbra_asset::Value; +use penumbra_governance::{ + DelegatorVoteCircuit, DelegatorVoteProof, DelegatorVoteProofPrivate, DelegatorVoteProofPublic, +}; +use penumbra_keys::keys::{Bip44Path, SeedPhrase, SpendKey}; +use penumbra_proof_params::{DummyWitness, DELEGATOR_VOTE_PROOF_PROVING_KEY}; use penumbra_sct::Nullifier; use penumbra_shielded_pool::Note; use penumbra_tct as tct; @@ -18,36 +20,10 @@ use criterion::{criterion_group, criterion_main, Criterion}; use rand_core::OsRng; #[allow(clippy::too_many_arguments)] -fn prove( - r: Fq, - s: Fq, - state_commitment_proof: tct::Proof, - note: Note, - spend_auth_randomizer: Fr, - ak: VerificationKey, - nk: NullifierKey, - anchor: tct::Root, - balance_commitment: balance::Commitment, - nullifier: Nullifier, - rk: VerificationKey, - start_position: tct::Position, -) { - let _proof = DelegatorVoteProof::prove( - r, - s, - &DELEGATOR_VOTE_PROOF_PROVING_KEY, - state_commitment_proof, - note, - spend_auth_randomizer, - ak, - nk, - anchor, - balance_commitment, - nullifier, - rk, - start_position, - ) - .expect("can create proof"); +fn prove(r: Fq, s: Fq, public: DelegatorVoteProofPublic, private: DelegatorVoteProofPrivate) { + let _proof = + DelegatorVoteProof::prove(r, s, &DELEGATOR_VOTE_PROOF_PROVING_KEY, public, private) + .expect("can create proof"); } fn delegator_vote_proving_time(c: &mut Criterion) { @@ -73,7 +49,7 @@ fn delegator_vote_proving_time(c: &mut Criterion) { let v_blinding = Fr::from(0i32); let balance_commitment = value_to_send.commit(v_blinding); let rk: VerificationKey = rsk.into(); - let nf = Nullifier::derive(&nk, state_commitment_proof.position(), ¬e_commitment); + let nullifier = Nullifier::derive(&nk, state_commitment_proof.position(), ¬e_commitment); sct.end_epoch().unwrap(); let first_note_commitment = Note::generate(&mut OsRng, &sender, value_to_send).commit(); @@ -83,40 +59,28 @@ fn delegator_vote_proving_time(c: &mut Criterion) { let r = Fq::rand(&mut OsRng); let s = Fq::rand(&mut OsRng); - - c.bench_function("delegator proving", |b| { - b.iter(|| { - prove( - r, - s, - state_commitment_proof.clone(), - note.clone(), - spend_auth_randomizer, - ak, - nk, - anchor, - balance_commitment, - nf, - rk, - start_position, - ) - }) - }); - - // Also print out the number of constraints. - let circuit = DelegatorVoteCircuit::new( + let public = DelegatorVoteProofPublic { + anchor, + balance_commitment, + nullifier, + rk, + start_position, + }; + let private = DelegatorVoteProofPrivate { state_commitment_proof, note, v_blinding, spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, - start_position, - ); + }; + + c.bench_function("delegator proving", |b| { + b.iter(|| prove(r, s, public.clone(), private.clone())) + }); + + // Also print out the number of constraints. + let circuit = DelegatorVoteCircuit::with_dummy_witness(); let cs = ConstraintSystem::new_ref(); cs.set_optimization_goal(OptimizationGoal::Constraints); diff --git a/crates/bench/benches/nullifier_derivation.rs b/crates/bench/benches/nullifier_derivation.rs index 713961125b..52ece2ac7a 100644 --- a/crates/bench/benches/nullifier_derivation.rs +++ b/crates/bench/benches/nullifier_derivation.rs @@ -5,24 +5,24 @@ use ark_relations::r1cs::{ }; use decaf377::Fq; use penumbra_asset::Value; -use penumbra_keys::keys::{Bip44Path, NullifierKey, SeedPhrase, SpendKey}; -use penumbra_proof_params::NULLIFIER_DERIVATION_PROOF_PROVING_KEY; +use penumbra_keys::keys::{Bip44Path, SeedPhrase, SpendKey}; +use penumbra_proof_params::{DummyWitness, NULLIFIER_DERIVATION_PROOF_PROVING_KEY}; use penumbra_sct::Nullifier; -use penumbra_shielded_pool::{Note, Rseed}; +use penumbra_shielded_pool::{ + Note, NullifierDerivationProofPrivate, NullifierDerivationProofPublic, Rseed, +}; use penumbra_shielded_pool::{NullifierDerivationCircuit, NullifierDerivationProof}; use penumbra_tct as tct; use criterion::{criterion_group, criterion_main, Criterion}; use rand_core::OsRng; -fn prove(position: tct::Position, note: Note, nk: NullifierKey, nullifier: Nullifier) { +fn prove(public: NullifierDerivationProofPublic, private: NullifierDerivationProofPrivate) { let _proof = NullifierDerivationProof::prove( &mut OsRng, &NULLIFIER_DERIVATION_PROOF_PROVING_KEY, - position, - note, - nk, - nullifier, + public, + private, ) .expect("Can generate proof"); } @@ -47,14 +47,18 @@ fn nullifier_derivation_proving_time(c: &mut Criterion) { sct.insert(tct::Witness::Keep, note_commitment).unwrap(); let state_commitment_proof = sct.witness(note_commitment).unwrap(); let position = state_commitment_proof.position(); + let public = NullifierDerivationProofPublic { + position, + note_commitment, + nullifier, + }; + let private = NullifierDerivationProofPrivate { nk }; c.bench_function("nullifier derivation proving", |b| { - b.iter(|| prove(position, note.clone(), nk, nullifier)) + b.iter(|| prove(public.clone(), private.clone())) }); - // Also print out the number of constraints. - let circuit = NullifierDerivationCircuit::new(position, note.commit(), nk, nullifier); - + let circuit = NullifierDerivationCircuit::with_dummy_witness(); let cs = ConstraintSystem::new_ref(); cs.set_optimization_goal(OptimizationGoal::Constraints); cs.set_mode(SynthesisMode::Setup); diff --git a/crates/bench/benches/spend.rs b/crates/bench/benches/spend.rs index b6a9cbdd2b..474f1101ef 100644 --- a/crates/bench/benches/spend.rs +++ b/crates/bench/benches/spend.rs @@ -6,47 +6,20 @@ use ark_relations::r1cs::{ }; use decaf377::{Fq, Fr}; use decaf377_rdsa::{SpendAuth, VerificationKey}; -use penumbra_asset::{balance, Value}; -use penumbra_keys::keys::{Bip44Path, NullifierKey, SeedPhrase, SpendKey}; -use penumbra_proof_params::SPEND_PROOF_PROVING_KEY; +use penumbra_asset::Value; +use penumbra_keys::keys::{Bip44Path, SeedPhrase, SpendKey}; +use penumbra_proof_params::{DummyWitness, SPEND_PROOF_PROVING_KEY}; use penumbra_sct::Nullifier; -use penumbra_shielded_pool::{Note, SpendCircuit, SpendProof}; +use penumbra_shielded_pool::{Note, SpendCircuit, SpendProof, SpendProofPrivate, SpendProofPublic}; use penumbra_tct as tct; use criterion::{criterion_group, criterion_main, Criterion}; use rand_core::OsRng; #[allow(clippy::too_many_arguments)] -fn prove( - r: Fq, - s: Fq, - state_commitment_proof: tct::Proof, - note: Note, - v_blinding: Fr, - spend_auth_randomizer: Fr, - ak: VerificationKey, - nk: NullifierKey, - anchor: tct::Root, - balance_commitment: balance::Commitment, - nullifier: Nullifier, - rk: VerificationKey, -) { - let _proof = SpendProof::prove( - r, - s, - &SPEND_PROOF_PROVING_KEY, - state_commitment_proof, - note, - v_blinding, - spend_auth_randomizer, - ak, - nk, - anchor, - balance_commitment, - nullifier, - rk, - ) - .expect("can create proof"); +fn prove(r: Fq, s: Fq, public: SpendProofPublic, private: SpendProofPrivate) { + let _proof = SpendProof::prove(r, s, &SPEND_PROOF_PROVING_KEY, public, private) + .expect("can create proof"); } fn spend_proving_time(c: &mut Criterion) { @@ -76,39 +49,27 @@ fn spend_proving_time(c: &mut Criterion) { let r = Fq::rand(&mut OsRng); let s = Fq::rand(&mut OsRng); - - c.bench_function("spend proving", |b| { - b.iter(|| { - prove( - r, - s, - state_commitment_proof.clone(), - note.clone(), - v_blinding, - spend_auth_randomizer, - ak, - nk, - anchor, - balance_commitment, - nf, - rk, - ) - }) - }); - - // Also print out the number of constraints. - let circuit = SpendCircuit::new( + let public = SpendProofPublic { + anchor, + balance_commitment, + nullifier: nf, + rk, + }; + let private = SpendProofPrivate { state_commitment_proof, note, v_blinding, spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, - ); + }; + + c.bench_function("spend proving", |b| { + b.iter(|| prove(r, s, public.clone(), private.clone())) + }); + + // Also print out the number of constraints. + let circuit = SpendCircuit::with_dummy_witness(); let cs = ConstraintSystem::new_ref(); cs.set_optimization_goal(OptimizationGoal::Constraints); diff --git a/crates/bin/pcli/tests/proof.rs b/crates/bin/pcli/tests/proof.rs index 67f295ee87..f931160f49 100644 --- a/crates/bin/pcli/tests/proof.rs +++ b/crates/bin/pcli/tests/proof.rs @@ -10,7 +10,9 @@ use penumbra_dex::{ BatchSwapOutputData, TradingPair, }; use penumbra_fee::Fee; -use penumbra_governance::DelegatorVoteProof; +use penumbra_governance::{ + DelegatorVoteProof, DelegatorVoteProofPrivate, DelegatorVoteProofPublic, +}; use penumbra_keys::keys::{Bip44Path, SeedPhrase, SpendKey}; use penumbra_num::Amount; use penumbra_proof_params::{ @@ -23,7 +25,10 @@ use penumbra_proof_params::{ }; use penumbra_sct::Nullifier; use penumbra_shielded_pool::Note; -use penumbra_shielded_pool::{NullifierDerivationProof, OutputProof, SpendProof}; +use penumbra_shielded_pool::{ + NullifierDerivationProof, NullifierDerivationProofPrivate, NullifierDerivationProofPublic, + OutputProof, SpendProof, SpendProofPrivate, SpendProofPublic, +}; use penumbra_stake::{IdentityKey, Penalty, UnbondingToken, UndelegateClaimProof}; use penumbra_tct as tct; use rand_core::OsRng; @@ -56,33 +61,33 @@ fn spend_proof_parameters_vs_current_spend_circuit() { let mut sct = tct::Tree::new(); sct.insert(tct::Witness::Keep, note_commitment).unwrap(); let anchor = sct.root(); - let note_commitment_proof = sct.witness(note_commitment).unwrap(); + let state_commitment_proof = sct.witness(note_commitment).unwrap(); let v_blinding = Fr::rand(&mut OsRng); let balance_commitment = value_to_send.commit(v_blinding); let rk: VerificationKey = rsk.into(); - let nf = Nullifier::derive(&nk, 0.into(), ¬e_commitment); + let nullifier = Nullifier::derive(&nk, 0.into(), ¬e_commitment); // Random elements to provide ZK (see Section 3.2 Groth16 paper, bottom of page 17) let blinding_r = Fq::rand(&mut OsRng); let blinding_s = Fq::rand(&mut OsRng); - let proof = SpendProof::prove( - blinding_r, - blinding_s, - pk, - note_commitment_proof, + let public = SpendProofPublic { + anchor, + balance_commitment, + nullifier, + rk, + }; + let private = SpendProofPrivate { + state_commitment_proof, note, v_blinding, spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, - ) - .expect("can create proof"); + }; + let proof = SpendProof::prove(blinding_r, blinding_s, pk, public.clone(), private) + .expect("can create proof"); - let proof_result = proof.verify(vk, anchor, balance_commitment, nf, rk); + let proof_result = proof.verify(vk, public); assert!(proof_result.is_ok()); } @@ -130,24 +135,25 @@ fn delegator_vote_proof_parameters_vs_current_delegator_vote_circuit() { let blinding_r = Fq::rand(&mut OsRng); let blinding_s = Fq::rand(&mut OsRng); - let proof = DelegatorVoteProof::prove( - blinding_r, - blinding_s, - pk, + let public = DelegatorVoteProofPublic { + anchor, + balance_commitment, + nullifier: nf, + rk, + start_position, + }; + let private = DelegatorVoteProofPrivate { state_commitment_proof, note, + v_blinding: Fr::from(0u64), spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, - start_position, - ) - .expect("can create proof"); + }; + let proof = DelegatorVoteProof::prove(blinding_r, blinding_s, pk, public.clone(), private) + .expect("can create proof"); - let proof_result = proof.verify(vk, anchor, balance_commitment, nf, rk, start_position); + let proof_result = proof.verify(vk, public); assert!(proof_result.is_ok()); } @@ -387,11 +393,16 @@ fn nullifier_derivation_parameters_vs_current_nullifier_derivation_circuit() { let position = state_commitment_proof.position(); let nullifier = Nullifier::derive(&nk, state_commitment_proof.position(), ¬e_commitment); - let proof = - NullifierDerivationProof::prove(&mut rng, pk, position, note.clone(), nk, nullifier) - .expect("can create proof"); + let public = NullifierDerivationProofPublic { + position, + note_commitment, + nullifier, + }; + let private = NullifierDerivationProofPrivate { nk }; + let proof = NullifierDerivationProof::prove(&mut rng, pk, public.clone(), private) + .expect("can create proof"); - let proof_result = proof.verify(vk, position, note.commit(), nullifier); + let proof_result = proof.verify(vk, public); assert!(proof_result.is_ok()); } diff --git a/crates/core/component/governance/src/action_handler/delegator_vote.rs b/crates/core/component/governance/src/action_handler/delegator_vote.rs index bcd978ad16..aa63c2af36 100644 --- a/crates/core/component/governance/src/action_handler/delegator_vote.rs +++ b/crates/core/component/governance/src/action_handler/delegator_vote.rs @@ -9,7 +9,7 @@ use penumbra_proof_params::DELEGATOR_VOTE_PROOF_VERIFICATION_KEY; use penumbra_txhash::TransactionContext; use crate::{ - DelegatorVote, DelegatorVoteBody, + DelegatorVote, DelegatorVoteBody, DelegatorVoteProofPublic, {component::StateWriteExt, StateReadExt}, }; use cnidarium_component::ActionHandler; @@ -40,15 +40,15 @@ impl ActionHandler for DelegatorVote { .context("delegator vote auth signature failed to verify")?; // 2. Verify the proof against the provided anchor and start position: + let public = DelegatorVoteProofPublic { + anchor: context.anchor, + balance_commitment: value.commit(Fr::zero()), + nullifier: *nullifier, + rk: *rk, + start_position: *start_position, + }; proof - .verify( - &DELEGATOR_VOTE_PROOF_VERIFICATION_KEY, - context.anchor, - value.commit(Fr::zero()), - *nullifier, - *rk, - *start_position, - ) + .verify(&DELEGATOR_VOTE_PROOF_VERIFICATION_KEY, public) .context("a delegator vote proof did not verify")?; Ok(()) diff --git a/crates/core/component/governance/src/delegator_vote.rs b/crates/core/component/governance/src/delegator_vote.rs index 3c164c1550..758d327f83 100644 --- a/crates/core/component/governance/src/delegator_vote.rs +++ b/crates/core/component/governance/src/delegator_vote.rs @@ -5,5 +5,7 @@ pub mod view; pub use action::{DelegatorVote, DelegatorVoteBody}; pub use plan::DelegatorVotePlan; -pub use proof::{DelegatorVoteCircuit, DelegatorVoteProof}; +pub use proof::{ + DelegatorVoteCircuit, DelegatorVoteProof, DelegatorVoteProofPrivate, DelegatorVoteProofPublic, +}; pub use view::DelegatorVoteView; diff --git a/crates/core/component/governance/src/delegator_vote/plan.rs b/crates/core/component/governance/src/delegator_vote/plan.rs index 11e3331789..79fa89485f 100644 --- a/crates/core/component/governance/src/delegator_vote/plan.rs +++ b/crates/core/component/governance/src/delegator_vote/plan.rs @@ -15,6 +15,8 @@ use serde::{Deserialize, Serialize}; use crate::delegator_vote::action::{DelegatorVote, DelegatorVoteBody}; use crate::delegator_vote::proof::DelegatorVoteProof; +use crate::DelegatorVoteProofPrivate; +use crate::DelegatorVoteProofPublic; use crate::{vote::Vote, VotingReceiptToken}; /// A plan to vote as a delegator. @@ -103,20 +105,27 @@ impl DelegatorVotePlan { fvk: &FullViewingKey, state_commitment_proof: tct::Proof, ) -> DelegatorVoteProof { + let public = DelegatorVoteProofPublic { + anchor: state_commitment_proof.root(), + balance_commitment: self.staked_note.value().commit(Fr::zero()), + nullifier: self.nullifier(fvk), + rk: self.rk(fvk), + start_position: self.start_position, + }; + let private = DelegatorVoteProofPrivate { + state_commitment_proof, + note: self.staked_note.clone(), + v_blinding: Fr::from(0), + spend_auth_randomizer: self.randomizer, + ak: *fvk.spend_verification_key(), + nk: *fvk.nullifier_key(), + }; DelegatorVoteProof::prove( self.proof_blinding_r, self.proof_blinding_s, &DELEGATOR_VOTE_PROOF_PROVING_KEY, - state_commitment_proof.clone(), - self.staked_note.clone(), - self.randomizer, - *fvk.spend_verification_key(), - *fvk.nullifier_key(), - state_commitment_proof.root(), - self.staked_note.value().commit(Fr::zero()), - self.nullifier(fvk), - self.rk(fvk), - self.start_position, + public, + private, ) .expect("can generate ZK delegator vote proof") } diff --git a/crates/core/component/governance/src/delegator_vote/proof.rs b/crates/core/component/governance/src/delegator_vote/proof.rs index debf4ba310..8a51a4d277 100644 --- a/crates/core/component/governance/src/delegator_vote/proof.rs +++ b/crates/core/component/governance/src/delegator_vote/proof.rs @@ -28,10 +28,41 @@ use penumbra_proof_params::{DummyWitness, VerifyingKeyExt, GROTH16_PROOF_LENGTH_ use penumbra_sct::{Nullifier, NullifierVar}; use penumbra_shielded_pool::{note, Note, Rseed}; +/// The public input for a [`DelegatorVoteProof`]. +#[derive(Clone, Debug)] +pub struct DelegatorVoteProofPublic { + /// the merkle root of the state commitment tree. + pub anchor: tct::Root, + /// value commitment of the note to be spent. + pub balance_commitment: balance::Commitment, + /// nullifier of the note to be spent. + pub nullifier: Nullifier, + /// the randomized verification spend key. + pub rk: VerificationKey, + /// the start position of the proposal being voted on. + pub start_position: tct::Position, +} + +/// The private input for a [`DelegatorVoteProof`]. +#[derive(Clone, Debug)] +pub struct DelegatorVoteProofPrivate { + /// Inclusion proof for the note commitment. + pub state_commitment_proof: tct::Proof, + /// The note being spent. + pub note: Note, + /// The blinding factor used for generating the value commitment. + pub v_blinding: Fr, + /// The randomizer used for generating the randomized spend auth key. + pub spend_auth_randomizer: Fr, + /// The spend authorization key. + pub ak: VerificationKey, + /// The nullifier deriving key. + pub nk: NullifierKey, +} + /// Groth16 proof for delegator voting. #[derive(Clone, Debug)] pub struct DelegatorVoteCircuit { - // Witnesses /// Inclusion proof for the note commitment. state_commitment_proof: tct::Proof, /// The note being spent. @@ -45,33 +76,35 @@ pub struct DelegatorVoteCircuit { /// The nullifier deriving key. nk: NullifierKey, - // Public inputs /// the merkle root of the state commitment tree. - pub anchor: tct::Root, + anchor: tct::Root, /// value commitment of the note to be spent. - pub balance_commitment: balance::Commitment, + balance_commitment: balance::Commitment, /// nullifier of the note to be spent. - pub nullifier: Nullifier, + nullifier: Nullifier, /// the randomized verification spend key. - pub rk: VerificationKey, + rk: VerificationKey, /// the start position of the proposal being voted on. - pub start_position: tct::Position, + start_position: tct::Position, } impl DelegatorVoteCircuit { - #[allow(clippy::too_many_arguments)] - pub fn new( - state_commitment_proof: tct::Proof, - note: Note, - v_blinding: Fr, - spend_auth_randomizer: Fr, - ak: VerificationKey, - nk: NullifierKey, - anchor: tct::Root, - balance_commitment: balance::Commitment, - nullifier: Nullifier, - rk: VerificationKey, - start_position: tct::Position, + fn new( + DelegatorVoteProofPublic { + anchor, + balance_commitment, + nullifier, + rk, + start_position, + }: DelegatorVoteProofPublic, + DelegatorVoteProofPrivate { + state_commitment_proof, + note, + v_blinding, + spend_auth_randomizer, + ak, + nk, + }: DelegatorVoteProofPrivate, ) -> Self { Self { state_commitment_proof, @@ -235,51 +268,14 @@ impl DummyWitness for DelegatorVoteCircuit { pub struct DelegatorVoteProof([u8; GROTH16_PROOF_LENGTH_BYTES]); impl DelegatorVoteProof { - #![allow(clippy::too_many_arguments)] pub fn prove( blinding_r: Fq, blinding_s: Fq, pk: &ProvingKey, - state_commitment_proof: tct::Proof, - note: Note, - spend_auth_randomizer: Fr, - ak: VerificationKey, - nk: NullifierKey, - anchor: tct::Root, - balance_commitment: balance::Commitment, - nullifier: Nullifier, - rk: VerificationKey, - start_position: tct::Position, + public: DelegatorVoteProofPublic, + private: DelegatorVoteProofPrivate, ) -> anyhow::Result { - // The blinding factor for the value commitment is zero since it - // is not blinded. - let zero_blinding = Fr::from(0); - tracing::debug!( - ?state_commitment_proof, - ?note, - ?spend_auth_randomizer, - ?ak, - ?nk, - ?anchor, - ?balance_commitment, - ?nullifier, - ?rk, - ?start_position, - "generating delegator vote proof" - ); - let circuit = DelegatorVoteCircuit { - state_commitment_proof, - note, - v_blinding: zero_blinding, - spend_auth_randomizer, - ak, - nk, - anchor, - balance_commitment, - nullifier, - rk, - start_position, - }; + let circuit = DelegatorVoteCircuit::new(public, private); let proof = Groth16::::create_proof_with_reduction( circuit, pk, blinding_r, blinding_s, ) @@ -296,39 +292,38 @@ impl DelegatorVoteProof { pub fn verify( &self, vk: &PreparedVerifyingKey, - anchor: tct::Root, - balance_commitment: balance::Commitment, - nullifier: Nullifier, - rk: VerificationKey, - start_position: tct::Position, + public: DelegatorVoteProofPublic, ) -> anyhow::Result<()> { let proof = Proof::deserialize_compressed_unchecked(&self.0[..]).map_err(|e| anyhow::anyhow!(e))?; let mut public_inputs = Vec::new(); public_inputs.extend( - Fq::from(anchor.0) + Fq::from(public.anchor.0) .to_field_elements() .expect("valid field element"), ); public_inputs.extend( - balance_commitment + public + .balance_commitment .0 .to_field_elements() .expect("valid field element"), ); public_inputs.extend( - nullifier + public + .nullifier .0 .to_field_elements() .expect("valid field element"), ); - let element_rk = decaf377::Encoding(rk.to_bytes()) + let element_rk = decaf377::Encoding(public.rk.to_bytes()) .vartime_decompress() .expect("expect only valid element points"); public_inputs.extend(element_rk.to_field_elements().expect("valid field element")); public_inputs.extend( - start_position + public + .start_position .to_field_elements() .expect("valid field element"), ); @@ -435,25 +430,31 @@ mod tests { let blinding_r = Fq::rand(&mut OsRng); let blinding_s = Fq::rand(&mut OsRng); - - let proof = DelegatorVoteProof::prove( - blinding_r, - blinding_s, - &pk, + let public = DelegatorVoteProofPublic { + anchor, + balance_commitment, + nullifier: nf, + rk, + start_position, + }; + let private = DelegatorVoteProofPrivate { state_commitment_proof, note, + v_blinding: Fr::from(0u64), spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, - start_position, + }; + + let proof = DelegatorVoteProof::prove( + blinding_r, + blinding_s, + &pk, + public.clone(), private ) .expect("can create proof"); - let proof_result = proof.verify(&vk, anchor, balance_commitment, nf, rk, start_position); + let proof_result = proof.verify(&vk, public); assert!(proof_result.is_ok()); } } @@ -505,21 +506,28 @@ mod tests { let blinding_r = Fq::rand(&mut OsRng); let blinding_s = Fq::rand(&mut OsRng); - - let proof = DelegatorVoteProof::prove( - blinding_r, - blinding_s, - &pk, + let public = DelegatorVoteProofPublic { + anchor, + balance_commitment, + nullifier: nf, + rk, + start_position, + }; + let private = DelegatorVoteProofPrivate { state_commitment_proof, note, + v_blinding: Fr::from(0u64), spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, - start_position, + }; + + + let proof = DelegatorVoteProof::prove( + blinding_r, + blinding_s, + &pk, + public.clone(), private ).expect("can form proof in release mode, but it should not verify"); // In debug mode, we won't be able to construct a valid proof if the start position @@ -528,7 +536,7 @@ mod tests { // generation (upstream) where we panic in debug mode if the circuit is not satisifiable, // but not in release mode. To ensure the same behavior in this test for both modes, // we panic if we get here and the proof does not verify (expected). - let proof_result = proof.verify(&vk, anchor, balance_commitment, nf, rk, start_position); + let proof_result = proof.verify(&vk, public); proof_result.expect("we expect this proof _not_ to verify, so this will cause a panic"); } } diff --git a/crates/core/component/governance/src/lib.rs b/crates/core/component/governance/src/lib.rs index 019a870d32..7d66052326 100644 --- a/crates/core/component/governance/src/lib.rs +++ b/crates/core/component/governance/src/lib.rs @@ -5,7 +5,7 @@ pub mod delegator_vote; pub use delegator_vote::{ DelegatorVote, DelegatorVoteBody, DelegatorVoteCircuit, DelegatorVotePlan, DelegatorVoteProof, - DelegatorVoteView, + DelegatorVoteProofPrivate, DelegatorVoteProofPublic, DelegatorVoteView, }; pub mod proposal_deposit_claim; diff --git a/crates/core/component/shielded-pool/src/component/action_handler/spend.rs b/crates/core/component/shielded-pool/src/component/action_handler/spend.rs index b4b9c3d7c1..a75375c54c 100644 --- a/crates/core/component/shielded-pool/src/component/action_handler/spend.rs +++ b/crates/core/component/shielded-pool/src/component/action_handler/spend.rs @@ -9,7 +9,7 @@ use penumbra_proto::StateWriteProto as _; use penumbra_sct::component::{SctManager, SourceContext, StateReadExt as _}; use penumbra_txhash::TransactionContext; -use crate::{event, Spend}; +use crate::{event, Spend, SpendProofPublic}; #[async_trait] impl ActionHandler for Spend { @@ -24,15 +24,15 @@ impl ActionHandler for Spend { .context("spend auth signature failed to verify")?; // 3. Check that the proof verifies. + let public = SpendProofPublic { + anchor: context.anchor, + balance_commitment: spend.body.balance_commitment, + nullifier: spend.body.nullifier, + rk: spend.body.rk, + }; spend .proof - .verify( - &SPEND_PROOF_VERIFICATION_KEY, - context.anchor, - spend.body.balance_commitment, - spend.body.nullifier, - spend.body.rk, - ) + .verify(&SPEND_PROOF_VERIFICATION_KEY, public) .context("a spend proof did not verify")?; Ok(()) diff --git a/crates/core/component/shielded-pool/src/lib.rs b/crates/core/component/shielded-pool/src/lib.rs index cf28c19d19..1361210945 100644 --- a/crates/core/component/shielded-pool/src/lib.rs +++ b/crates/core/component/shielded-pool/src/lib.rs @@ -26,6 +26,11 @@ pub mod output; pub mod spend; pub use convert::{ConvertCircuit, ConvertProof, ConvertProofPrivate, ConvertProofPublic}; -pub use nullifier_derivation::{NullifierDerivationCircuit, NullifierDerivationProof}; +pub use nullifier_derivation::{ + NullifierDerivationCircuit, NullifierDerivationProof, NullifierDerivationProofPrivate, + NullifierDerivationProofPublic, +}; pub use output::{Output, OutputCircuit, OutputPlan, OutputProof, OutputView}; -pub use spend::{Spend, SpendCircuit, SpendPlan, SpendProof, SpendView}; +pub use spend::{ + Spend, SpendCircuit, SpendPlan, SpendProof, SpendProofPrivate, SpendProofPublic, SpendView, +}; diff --git a/crates/core/component/shielded-pool/src/nullifier_derivation.rs b/crates/core/component/shielded-pool/src/nullifier_derivation.rs index f5af7ee9eb..63b81d1cd3 100644 --- a/crates/core/component/shielded-pool/src/nullifier_derivation.rs +++ b/crates/core/component/shielded-pool/src/nullifier_derivation.rs @@ -21,27 +21,45 @@ use penumbra_keys::keys::{Bip44Path, NullifierKey, NullifierKeyVar, SeedPhrase, use penumbra_proof_params::{DummyWitness, VerifyingKeyExt, GROTH16_PROOF_LENGTH_BYTES}; use penumbra_sct::{Nullifier, NullifierVar}; +/// The public input for a ['NullifierDerivationProof']. +#[derive(Clone, Debug)] +pub struct NullifierDerivationProofPublic { + /// The position of the spent note. + pub position: tct::Position, + /// A commitment to the spent note. + pub note_commitment: StateCommitment, + /// nullifier of the spent note. + pub nullifier: Nullifier, +} + +/// The private input for a ['NullifierDerivationProof']. +#[derive(Clone, Debug)] +pub struct NullifierDerivationProofPrivate { + /// The nullifier deriving key. + pub nk: NullifierKey, +} + /// Groth16 proof for correct nullifier derivation. #[derive(Clone, Debug)] pub struct NullifierDerivationCircuit { - // Witnesses /// The nullifier deriving key. nk: NullifierKey, - // Public inputs /// the position of the spent note. - pub position: tct::Position, + position: tct::Position, /// A commitment to the spent note. - pub note_commitment: StateCommitment, + note_commitment: StateCommitment, /// nullifier of the spent note. - pub nullifier: Nullifier, + nullifier: Nullifier, } impl NullifierDerivationCircuit { - pub fn new( - position: tct::Position, - note_commitment: StateCommitment, - nk: NullifierKey, - nullifier: Nullifier, + fn new( + NullifierDerivationProofPublic { + position, + note_commitment, + nullifier, + }: NullifierDerivationProofPublic, + NullifierDerivationProofPrivate { nk }: NullifierDerivationProofPrivate, ) -> Self { Self { nk, @@ -109,22 +127,13 @@ impl DummyWitness for NullifierDerivationCircuit { pub struct NullifierDerivationProof([u8; GROTH16_PROOF_LENGTH_BYTES]); impl NullifierDerivationProof { - #![allow(clippy::too_many_arguments)] pub fn prove( rng: &mut R, pk: &ProvingKey, - position: tct::Position, - note: Note, - nk: NullifierKey, - nullifier: Nullifier, + public: NullifierDerivationProofPublic, + private: NullifierDerivationProofPrivate, ) -> anyhow::Result { - let note_commitment = note.commit(); - let circuit = NullifierDerivationCircuit { - note_commitment, - position, - nk, - nullifier, - }; + let circuit = NullifierDerivationCircuit::new(public, private); let proof = Groth16::::prove(pk, circuit, rng) .map_err(|err| anyhow::anyhow!(err))?; let mut proof_bytes = [0u8; GROTH16_PROOF_LENGTH_BYTES]; @@ -133,29 +142,35 @@ impl NullifierDerivationProof { } /// Called to verify the proof using the provided public inputs. - #[tracing::instrument(level="debug", skip(self, vk), fields(self = ?base64::encode(self.clone().encode_to_vec()), vk = ?vk.debug_id()))] + #[tracing::instrument(level="debug", skip(self, vk), fields(self = ?base64::encode(&self.0), vk = ?vk.debug_id()))] pub fn verify( &self, vk: &PreparedVerifyingKey, - position: tct::Position, - note_commitment: StateCommitment, - nullifier: Nullifier, + public: NullifierDerivationProofPublic, ) -> anyhow::Result<()> { let proof = Proof::deserialize_compressed_unchecked(&self.0[..]).map_err(|e| anyhow::anyhow!(e))?; let mut public_inputs = Vec::new(); public_inputs.extend( - nullifier + public + .nullifier .0 .to_field_elements() .ok_or_else(|| anyhow::anyhow!("could not convert nullifier to field elements"))?, ); - public_inputs.extend(note_commitment.0.to_field_elements().ok_or_else(|| { - anyhow::anyhow!("could not convert note commitment to field elements") - })?); public_inputs.extend( - position + public + .note_commitment + .0 + .to_field_elements() + .ok_or_else(|| { + anyhow::anyhow!("could not convert note commitment to field elements") + })?, + ); + public_inputs.extend( + public + .position .to_field_elements() .ok_or_else(|| anyhow::anyhow!("could not convert position to field elements"))?, ); @@ -171,7 +186,7 @@ impl NullifierDerivationProof { tracing::debug!(?proof_result, elapsed = ?start.elapsed()); proof_result .then_some(()) - .ok_or_else(|| anyhow::anyhow!("spend proof did not verify")) + .ok_or_else(|| anyhow::anyhow!("nullifier derivation proof did not verify")) } } @@ -235,20 +250,26 @@ mod tests { let state_commitment_proof = sct.witness(note_commitment).unwrap(); let position = state_commitment_proof.position(); let nullifier = Nullifier::derive(&nk, state_commitment_proof.position(), ¬e_commitment); - - let proof = NullifierDerivationProof::prove( - &mut rng, - &pk, + let public = NullifierDerivationProofPublic { position, - note, - nk, + note_commitment, nullifier, - ) - .expect("can create proof"); + }; + + let private = NullifierDerivationProofPrivate { + nk, + }; + + let proof = NullifierDerivationProof::prove( + &mut rng, + &pk, + public.clone(), private + ) + .expect("can create proof"); - let proof_result = proof.verify(&vk, position, note_commitment, nullifier); + let proof_result = proof.verify(&vk, public); - assert!(proof_result.is_ok()); + assert!(proof_result.is_ok()); } } } diff --git a/crates/core/component/shielded-pool/src/spend.rs b/crates/core/component/shielded-pool/src/spend.rs index 0fdb17f111..10c4aa69d9 100644 --- a/crates/core/component/shielded-pool/src/spend.rs +++ b/crates/core/component/shielded-pool/src/spend.rs @@ -5,5 +5,5 @@ mod view; pub use action::{Body, Spend}; pub use plan::SpendPlan; -pub use proof::{SpendCircuit, SpendProof}; +pub use proof::{SpendCircuit, SpendProof, SpendProofPrivate, SpendProofPublic}; pub use view::SpendView; diff --git a/crates/core/component/shielded-pool/src/spend/plan.rs b/crates/core/component/shielded-pool/src/spend/plan.rs index a78606bb40..4a1e2fe177 100644 --- a/crates/core/component/shielded-pool/src/spend/plan.rs +++ b/crates/core/component/shielded-pool/src/spend/plan.rs @@ -10,7 +10,7 @@ use rand_core::{CryptoRng, RngCore}; use serde::{Deserialize, Serialize}; use super::{Body, Spend, SpendProof}; -use crate::{Note, Rseed}; +use crate::{Note, Rseed, SpendProofPrivate, SpendProofPublic}; /// A planned [`Spend`](Spend). #[derive(Clone, Debug, Deserialize, Serialize)] @@ -100,20 +100,26 @@ impl SpendPlan { state_commitment_proof: tct::Proof, anchor: tct::Root, ) -> SpendProof { + let public = SpendProofPublic { + anchor, + balance_commitment: self.balance().commit(self.value_blinding), + nullifier: self.nullifier(fvk), + rk: self.rk(fvk), + }; + let private = SpendProofPrivate { + state_commitment_proof, + note: self.note.clone(), + v_blinding: self.value_blinding, + spend_auth_randomizer: self.randomizer, + ak: *fvk.spend_verification_key(), + nk: *fvk.nullifier_key(), + }; SpendProof::prove( self.proof_blinding_r, self.proof_blinding_s, &penumbra_proof_params::SPEND_PROOF_PROVING_KEY, - state_commitment_proof.clone(), - self.note.clone(), - self.value_blinding, - self.randomizer, - *fvk.spend_verification_key(), - *fvk.nullifier_key(), - anchor, - self.balance().commit(self.value_blinding), - self.nullifier(fvk), - self.rk(fvk), + public, + private, ) .expect("can generate ZKSpendProof") } diff --git a/crates/core/component/shielded-pool/src/spend/proof.rs b/crates/core/component/shielded-pool/src/spend/proof.rs index 8528bbf81f..945883589a 100644 --- a/crates/core/component/shielded-pool/src/spend/proof.rs +++ b/crates/core/component/shielded-pool/src/spend/proof.rs @@ -30,10 +30,39 @@ use penumbra_keys::keys::{ use penumbra_proof_params::{DummyWitness, VerifyingKeyExt, GROTH16_PROOF_LENGTH_BYTES}; use penumbra_sct::{Nullifier, NullifierVar}; +/// The public input for a [`SpendProof`]. +#[derive(Clone, Debug)] +pub struct SpendProofPublic { + /// the merkle root of the state commitment tree. + pub anchor: tct::Root, + /// value commitment of the note to be spent. + pub balance_commitment: balance::Commitment, + /// nullifier of the note to be spent. + pub nullifier: Nullifier, + /// the randomized verification spend key. + pub rk: VerificationKey, +} + +/// The private input for a [`SpendProof`]. +#[derive(Clone, Debug)] +pub struct SpendProofPrivate { + /// Inclusion proof for the note commitment. + pub state_commitment_proof: tct::Proof, + /// The note being spent. + pub note: Note, + /// The blinding factor used for generating the value commitment. + pub v_blinding: Fr, + /// The randomizer used for generating the randomized spend auth key. + pub spend_auth_randomizer: Fr, + /// The spend authorization key. + pub ak: VerificationKey, + /// The nullifier deriving key. + pub nk: NullifierKey, +} + /// Groth16 proof for spending existing notes. #[derive(Clone, Debug)] pub struct SpendCircuit { - // Witnesses /// Inclusion proof for the note commitment. state_commitment_proof: tct::Proof, /// The note being spent. @@ -47,30 +76,32 @@ pub struct SpendCircuit { /// The nullifier deriving key. nk: NullifierKey, - // Public inputs /// the merkle root of the state commitment tree. - pub anchor: tct::Root, + anchor: tct::Root, /// value commitment of the note to be spent. - pub balance_commitment: balance::Commitment, + balance_commitment: balance::Commitment, /// nullifier of the note to be spent. - pub nullifier: Nullifier, + nullifier: Nullifier, /// the randomized verification spend key. - pub rk: VerificationKey, + rk: VerificationKey, } impl SpendCircuit { - #[allow(clippy::too_many_arguments)] - pub fn new( - state_commitment_proof: tct::Proof, - note: Note, - v_blinding: Fr, - spend_auth_randomizer: Fr, - ak: VerificationKey, - nk: NullifierKey, - anchor: tct::Root, - balance_commitment: balance::Commitment, - nullifier: Nullifier, - rk: VerificationKey, + fn new( + SpendProofPublic { + anchor, + balance_commitment, + nullifier, + rk, + }: SpendProofPublic, + SpendProofPrivate { + state_commitment_proof, + note, + v_blinding, + spend_auth_randomizer, + ak, + nk, + }: SpendProofPrivate, ) -> Self { Self { state_commitment_proof, @@ -217,36 +248,16 @@ impl DummyWitness for SpendCircuit { pub struct SpendProof([u8; GROTH16_PROOF_LENGTH_BYTES]); impl SpendProof { - #![allow(clippy::too_many_arguments)] /// Generate a `SpendProof` given the proving key, public inputs, /// witness data, and two random elements `blinding_r` and `blinding_s`. pub fn prove( blinding_r: Fq, blinding_s: Fq, pk: &ProvingKey, - state_commitment_proof: tct::Proof, - note: Note, - v_blinding: Fr, - spend_auth_randomizer: Fr, - ak: VerificationKey, - nk: NullifierKey, - anchor: tct::Root, - balance_commitment: balance::Commitment, - nullifier: Nullifier, - rk: VerificationKey, + public: SpendProofPublic, + private: SpendProofPrivate, ) -> anyhow::Result { - let circuit = SpendCircuit { - state_commitment_proof, - note, - v_blinding, - spend_auth_randomizer, - ak, - nk, - anchor, - balance_commitment, - nullifier, - rk, - }; + let circuit = SpendCircuit::new(public, private); let proof = Groth16::::create_proof_with_reduction( circuit, pk, blinding_r, blinding_s, ) @@ -263,29 +274,28 @@ impl SpendProof { pub fn verify( &self, vk: &PreparedVerifyingKey, - anchor: tct::Root, - balance_commitment: balance::Commitment, - nullifier: Nullifier, - rk: VerificationKey, + public: SpendProofPublic, ) -> anyhow::Result<()> { let proof = Proof::deserialize_compressed_unchecked(&self.0[..]).map_err(|e| anyhow::anyhow!(e))?; let mut public_inputs = Vec::new(); - public_inputs.extend([Fq::from(anchor.0)]); + public_inputs.extend([Fq::from(public.anchor.0)]); public_inputs.extend( - balance_commitment + public + .balance_commitment .0 .to_field_elements() .ok_or_else(|| anyhow::anyhow!("balance commitment is not a valid element"))?, ); public_inputs.extend( - nullifier + public + .nullifier .0 .to_field_elements() .ok_or_else(|| anyhow::anyhow!("nullifier is not a valid element"))?, ); - let element_rk = decaf377::Encoding(rk.to_bytes()) + let element_rk = decaf377::Encoding(public.rk.to_bytes()) .vartime_decompress() .expect("expect only valid element points"); public_inputs.extend( @@ -401,24 +411,29 @@ mod tests { let blinding_r = Fq::rand(&mut OsRng); let blinding_s = Fq::rand(&mut OsRng); - let proof = SpendProof::prove( - blinding_r, - blinding_s, - &pk, + let public = SpendProofPublic { + anchor, + balance_commitment, + nullifier: nf, + rk, + }; + let private = SpendProofPrivate { state_commitment_proof, note, v_blinding, spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, + }; + let proof = SpendProof::prove( + blinding_r, + blinding_s, + &pk, + public.clone(), private ) .expect("can create proof"); - let proof_result = proof.verify(&vk, anchor, balance_commitment, nf, rk); + let proof_result = proof.verify(&vk, public); assert!(proof_result.is_ok()); } } @@ -459,24 +474,36 @@ mod tests { let blinding_r = Fq::rand(&mut OsRng); let blinding_s = Fq::rand(&mut OsRng); - let proof = SpendProof::prove( - blinding_r, - blinding_s, - &pk, + let public = SpendProofPublic { + anchor, + balance_commitment, + nullifier: nf, + rk, + }; + let private = SpendProofPrivate { state_commitment_proof, note, v_blinding, spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, + }; + let proof = SpendProof::prove( + blinding_r, + blinding_s, + &pk, + public, + private ) .expect("can create proof"); - let proof_result = proof.verify(&vk, incorrect_anchor, balance_commitment, nf, rk); + let incorrect_public = SpendProofPublic { + anchor: incorrect_anchor, + balance_commitment, + nullifier: nf, + rk, + }; + let proof_result = proof.verify(&vk, incorrect_public); assert!(proof_result.is_err()); } } @@ -523,23 +550,29 @@ mod tests { // In release mode the proof will be created, but will fail to verify. let blinding_r = Fq::rand(&mut OsRng); let blinding_s = Fq::rand(&mut OsRng); - let proof = SpendProof::prove( - blinding_r, - blinding_s, - &pk, + let public = SpendProofPublic { + anchor, + balance_commitment, + nullifier: nf, + rk, + }; + let private = SpendProofPrivate { state_commitment_proof, note, v_blinding, spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, + }; + let proof = SpendProof::prove( + blinding_r, + blinding_s, + &pk, + public.clone(), + private ).expect("can create proof in release mode"); - proof.verify(&vk, anchor, balance_commitment, nf, rk).expect("boom"); + proof.verify(&vk, public).expect("boom"); } } @@ -580,24 +613,35 @@ mod tests { let blinding_r = Fq::rand(&mut OsRng); let blinding_s = Fq::rand(&mut OsRng); - let proof = SpendProof::prove( - blinding_r, - blinding_s, - &pk, + let public = SpendProofPublic { + anchor, + balance_commitment, + nullifier: nf, + rk, + }; + let private = SpendProofPrivate { state_commitment_proof, note, v_blinding, spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, + }; + let proof = SpendProof::prove( + blinding_r, + blinding_s, + &pk, + public, private ) .expect("can create proof"); - let proof_result = proof.verify(&vk, anchor, balance_commitment, incorrect_nf, rk); + let incorrect_public = SpendProofPublic { + anchor, + balance_commitment, + nullifier: incorrect_nf, + rk, + }; + let proof_result = proof.verify(&vk, incorrect_public); assert!(proof_result.is_err()); } } @@ -637,26 +681,38 @@ mod tests { let blinding_r = Fq::rand(&mut OsRng); let blinding_s = Fq::rand(&mut OsRng); - let proof = SpendProof::prove( - blinding_r, - blinding_s, - &pk, + let public = SpendProofPublic { + anchor, + balance_commitment, + nullifier: nf, + rk, + }; + let private = SpendProofPrivate { state_commitment_proof, note, v_blinding, spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, + }; + let proof = SpendProof::prove( + blinding_r, + blinding_s, + &pk, + public, private + ) .expect("can create proof"); let incorrect_balance_commitment = value_to_send.commit(incorrect_blinding_factor); + let incorrect_public = SpendProofPublic { + anchor, + balance_commitment: incorrect_balance_commitment, + nullifier: nf, + rk, + }; - let proof_result = proof.verify(&vk, anchor, incorrect_balance_commitment, nf, rk); + let proof_result = proof.verify(&vk, incorrect_public); assert!(proof_result.is_err()); } } @@ -700,24 +756,35 @@ mod tests { let blinding_r = Fq::rand(&mut OsRng); let blinding_s = Fq::rand(&mut OsRng); - let proof = SpendProof::prove( - blinding_r, - blinding_s, - &pk, + let public = SpendProofPublic { + anchor, + balance_commitment, + nullifier: nf, + rk, + }; + let private = SpendProofPrivate { state_commitment_proof, note, v_blinding, spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, + }; + let proof = SpendProof::prove( + blinding_r, + blinding_s, + &pk, + public, private ) .expect("should be able to form proof"); - let proof_result = proof.verify(&vk, anchor, balance_commitment, nf, incorrect_rk); + let incorrect_public = SpendProofPublic { + anchor, + balance_commitment, + nullifier: nf, + rk: incorrect_rk, + }; + let proof_result = proof.verify(&vk, incorrect_public); assert!(proof_result.is_err()); } } @@ -758,24 +825,29 @@ mod tests { let blinding_r = Fq::rand(&mut OsRng); let blinding_s = Fq::rand(&mut OsRng); - let proof = SpendProof::prove( - blinding_r, - blinding_s, - &pk, + let public = SpendProofPublic { + anchor, + balance_commitment, + nullifier: nf, + rk, + }; + let private = SpendProofPrivate { state_commitment_proof, note, v_blinding, spend_auth_randomizer, ak, nk, - anchor, - balance_commitment, - nf, - rk, + }; + let proof = SpendProof::prove( + blinding_r, + blinding_s, + &pk, + public.clone(), private ) .expect("should be able to form proof"); - let proof_result = proof.verify(&vk, anchor, balance_commitment, nf, rk); + let proof_result = proof.verify(&vk, public); assert!(proof_result.is_ok()); } }