From 0a26c812e051065269a8bff2175ee8d815f9da04 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 6 Jan 2023 11:11:46 +0000 Subject: [PATCH] Split `sapling::Authorization::Proof` type into Spend and Output types While the Groth16 proofs have identical encodings, they are technically for different circuits, and we need the ability to differentiate them during bundle building. --- zcash_primitives/CHANGELOG.md | 4 ++ .../src/transaction/components/sapling.rs | 42 ++++++++++++------- .../transaction/components/sapling/builder.rs | 3 +- zcash_primitives/src/transaction/sighash.rs | 2 +- .../src/transaction/sighash_v4.rs | 6 ++- 5 files changed, 39 insertions(+), 18 deletions(-) diff --git a/zcash_primitives/CHANGELOG.md b/zcash_primitives/CHANGELOG.md index d893cc7b0..783920779 100644 --- a/zcash_primitives/CHANGELOG.md +++ b/zcash_primitives/CHANGELOG.md @@ -30,6 +30,10 @@ and this library adheres to Rust's notion of - `zcash_primitives::transaction::components`: - `sapling::{Bundle, SpendDescription, OutputDescription}` have had their fields replaced by getter methods. + - The associated type `sapling::Authorization::Proof` has been replaced by + `Authorization::{SpendProof, OutputProof}`. + - `sapling::MapAuth::map_proof` has been replaced by + `MapAuth::{map_spend_proof, map_output_proof}`. ### Removed - `zcash_primitives::sapling`: diff --git a/zcash_primitives/src/transaction/components/sapling.rs b/zcash_primitives/src/transaction/components/sapling.rs index 15c57cbfc..d867f5939 100644 --- a/zcash_primitives/src/transaction/components/sapling.rs +++ b/zcash_primitives/src/transaction/components/sapling.rs @@ -26,8 +26,10 @@ pub type GrothProofBytes = [u8; GROTH_PROOF_SIZE]; pub mod builder; pub mod fees; +/// Defines the authorization type of a Sapling bundle. pub trait Authorization: Debug { - type Proof: Clone + Debug; + type SpendProof: Clone + Debug; + type OutputProof: Clone + Debug; type AuthSig: Clone + Debug; } @@ -35,22 +37,27 @@ pub trait Authorization: Debug { pub struct Unproven; impl Authorization for Unproven { - type Proof = (); + type SpendProof = (); + type OutputProof = (); type AuthSig = (); } +/// Authorizing data for a bundle of Sapling spends and outputs, ready to be committed to +/// the ledger. #[derive(Debug, Copy, Clone)] pub struct Authorized { pub binding_sig: redjubjub::Signature, } impl Authorization for Authorized { - type Proof = GrothProofBytes; + type SpendProof = GrothProofBytes; + type OutputProof = GrothProofBytes; type AuthSig = redjubjub::Signature; } pub trait MapAuth { - fn map_proof(&self, p: A::Proof) -> B::Proof; + fn map_spend_proof(&self, p: A::SpendProof) -> B::SpendProof; + fn map_output_proof(&self, p: A::OutputProof) -> B::OutputProof; fn map_auth_sig(&self, s: A::AuthSig) -> B::AuthSig; fn map_authorization(&self, a: A) -> B; } @@ -62,10 +69,17 @@ pub trait MapAuth { /// /// [`TransactionData::map_authorization`]: crate::transaction::TransactionData::map_authorization impl MapAuth for () { - fn map_proof( + fn map_spend_proof( &self, - p: ::Proof, - ) -> ::Proof { + p: ::SpendProof, + ) -> ::SpendProof { + p + } + + fn map_output_proof( + &self, + p: ::OutputProof, + ) -> ::OutputProof { p } @@ -84,7 +98,7 @@ impl MapAuth for () { #[derive(Debug, Clone)] pub struct Bundle { shielded_spends: Vec>, - shielded_outputs: Vec>, + shielded_outputs: Vec>, value_balance: Amount, authorization: A, } @@ -93,7 +107,7 @@ impl Bundle { /// Constructs a `Bundle` from its constituent parts. pub(crate) fn from_parts( shielded_spends: Vec>, - shielded_outputs: Vec>, + shielded_outputs: Vec>, value_balance: Amount, authorization: A, ) -> Self { @@ -111,7 +125,7 @@ impl Bundle { } /// Returns the list of outputs in this bundle. - pub fn shielded_outputs(&self) -> &[OutputDescription] { + pub fn shielded_outputs(&self) -> &[OutputDescription] { &self.shielded_outputs } @@ -139,7 +153,7 @@ impl Bundle { anchor: d.anchor, nullifier: d.nullifier, rk: d.rk, - zkproof: f.map_proof(d.zkproof), + zkproof: f.map_spend_proof(d.zkproof), spend_auth_sig: f.map_auth_sig(d.spend_auth_sig), }) .collect(), @@ -152,7 +166,7 @@ impl Bundle { ephemeral_key: o.ephemeral_key, enc_ciphertext: o.enc_ciphertext, out_ciphertext: o.out_ciphertext, - zkproof: f.map_proof(o.zkproof), + zkproof: f.map_output_proof(o.zkproof), }) .collect(), value_balance: self.value_balance, @@ -167,7 +181,7 @@ pub struct SpendDescription { anchor: bls12_381::Scalar, nullifier: Nullifier, rk: PublicKey, - zkproof: A::Proof, + zkproof: A::SpendProof, spend_auth_sig: A::AuthSig, } @@ -203,7 +217,7 @@ impl SpendDescription { } /// Returns the proof for this spend. - pub fn zkproof(&self) -> &A::Proof { + pub fn zkproof(&self) -> &A::SpendProof { &self.zkproof } diff --git a/zcash_primitives/src/transaction/components/sapling/builder.rs b/zcash_primitives/src/transaction/components/sapling/builder.rs index e4a252110..83671d8ad 100644 --- a/zcash_primitives/src/transaction/components/sapling/builder.rs +++ b/zcash_primitives/src/transaction/components/sapling/builder.rs @@ -227,7 +227,8 @@ impl std::fmt::Debug for Unauthorized { } impl Authorization for Unauthorized { - type Proof = GrothProofBytes; + type SpendProof = GrothProofBytes; + type OutputProof = GrothProofBytes; type AuthSig = SpendDescriptionInfo; } diff --git a/zcash_primitives/src/transaction/sighash.rs b/zcash_primitives/src/transaction/sighash.rs index 4de02c63f..3fd9b8b2e 100644 --- a/zcash_primitives/src/transaction/sighash.rs +++ b/zcash_primitives/src/transaction/sighash.rs @@ -78,7 +78,7 @@ pub trait TransparentAuthorizingContext: transparent::Authorization { pub fn signature_hash< 'a, TA: TransparentAuthorizingContext, - SA: sapling::Authorization, + SA: sapling::Authorization, A: Authorization, >( tx: &TransactionData, diff --git a/zcash_primitives/src/transaction/sighash_v4.rs b/zcash_primitives/src/transaction/sighash_v4.rs index 42ba4976b..b5eeed7b1 100644 --- a/zcash_primitives/src/transaction/sighash_v4.rs +++ b/zcash_primitives/src/transaction/sighash_v4.rs @@ -104,7 +104,9 @@ fn joinsplits_hash( .hash(&data) } -fn shielded_spends_hash>( +fn shielded_spends_hash< + A: sapling::Authorization, +>( shielded_spends: &[SpendDescription], ) -> Blake2bHash { let mut data = Vec::with_capacity(shielded_spends.len() * 384); @@ -133,7 +135,7 @@ fn shielded_outputs_hash(shielded_outputs: &[OutputDescription] } pub fn v4_signature_hash< - SA: sapling::Authorization, + SA: sapling::Authorization, A: Authorization, >( tx: &TransactionData,