Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::{
},
note::ExtractedNoteCommitment,
note_encryption::{sapling_note_encryption, Zip212Enforcement},
sapling_sighash_versioning::{SaplingSighashVersion, VerBindingSig, VerSpendAuthSig},
util::generate_random_rseed_internal,
value::{NoteValue, ValueCommitTrapdoor, ValueCommitment, ValueSum},
Anchor, Diversifier, MerklePath, Node, Note, Nullifier, PaymentAddress, SaplingIvk,
Expand Down Expand Up @@ -1124,7 +1125,7 @@ pub struct SigningParts {
/// Marker for a partially-authorized bundle, in the process of being signed.
#[derive(Clone, Debug)]
pub struct PartiallyAuthorized {
binding_signature: redjubjub::Signature<Binding>,
binding_signature: VerBindingSig,
sighash: [u8; 32],
}

Expand Down Expand Up @@ -1152,11 +1153,11 @@ pub enum MaybeSigned {
/// The information needed to sign this [`SpendDescription`].
SigningParts(SigningParts),
/// The signature for this [`SpendDescription`].
Signature(redjubjub::Signature<SpendAuth>),
Signature(VerSpendAuthSig),
}

impl MaybeSigned {
fn finalize(self) -> Result<redjubjub::Signature<SpendAuth>, Error> {
fn finalize(self) -> Result<VerSpendAuthSig, Error> {
match self {
Self::Signature(sig) => Ok(sig),
_ => Err(Error::MissingSignatures),
Expand All @@ -1179,13 +1180,17 @@ impl<P: InProgressProofs, V> Bundle<InProgress<P, Unsigned>, V> {
|_, proof| proof,
|rng, SigningMetadata { dummy_ask, parts }| match dummy_ask {
None => MaybeSigned::SigningParts(parts),
Some(ask) => {
MaybeSigned::Signature(ask.randomize(&parts.alpha).sign(rng, &sighash))
}
Some(ask) => MaybeSigned::Signature(VerSpendAuthSig::new(
SaplingSighashVersion::V0,
ask.randomize(&parts.alpha).sign(rng, &sighash),
)),
},
|rng, auth: InProgress<P, Unsigned>| InProgress {
sigs: PartiallyAuthorized {
binding_signature: auth.sigs.bsk.sign(rng, &sighash),
binding_signature: VerBindingSig::new(
SaplingSighashVersion::V0,
auth.sigs.bsk.sign(rng, &sighash),
),
sighash,
},
_proof_state: PhantomData,
Expand Down Expand Up @@ -1227,7 +1232,10 @@ impl<P: InProgressProofs, V> Bundle<InProgress<P, PartiallyAuthorized>, V> {
|_, proof| proof,
|rng, maybe| match maybe {
MaybeSigned::SigningParts(parts) if parts.ak == expected_ak => {
MaybeSigned::Signature(ask.randomize(&parts.alpha).sign(rng, &sighash))
MaybeSigned::Signature(VerSpendAuthSig::new(
SaplingSighashVersion::V0,
ask.randomize(&parts.alpha).sign(rng, &sighash),
))
}
s => s,
},
Expand All @@ -1240,14 +1248,11 @@ impl<P: InProgressProofs, V> Bundle<InProgress<P, PartiallyAuthorized>, V> {
/// Each signature will be applied to the one input for which it is valid. An error
/// will be returned if the signature is not valid for any inputs, or if it is valid
/// for more than one input.
pub fn append_signatures(
self,
signatures: &[redjubjub::Signature<SpendAuth>],
) -> Result<Self, Error> {
pub fn append_signatures(self, signatures: &[VerSpendAuthSig]) -> Result<Self, Error> {
signatures.iter().try_fold(self, Self::append_signature)
}

fn append_signature(self, signature: &redjubjub::Signature<SpendAuth>) -> Result<Self, Error> {
fn append_signature(self, signature: &VerSpendAuthSig) -> Result<Self, Error> {
let sighash = self.authorization().sigs.sighash;
let mut signature_valid_for = 0usize;
let bundle = self.map_authorization(
Expand All @@ -1257,9 +1262,9 @@ impl<P: InProgressProofs, V> Bundle<InProgress<P, PartiallyAuthorized>, V> {
|ctx, maybe| match maybe {
MaybeSigned::SigningParts(parts) => {
let rk = parts.ak.randomize(&parts.alpha);
if rk.verify(&sighash, signature).is_ok() {
if rk.verify(&sighash, signature.sig()).is_ok() {
**ctx += 1;
MaybeSigned::Signature(*signature)
MaybeSigned::Signature(signature.clone())
} else {
// Signature isn't for this input.
MaybeSigned::SigningParts(parts)
Expand Down
41 changes: 23 additions & 18 deletions src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::fmt::Debug;

use memuse::DynamicUsage;

use redjubjub::{Binding, SpendAuth};
use redjubjub::SpendAuth;

use zcash_note_encryption::{
note_bytes::NoteBytesData, EphemeralKeyBytes, ShieldedOutput, OUT_CIPHERTEXT_SIZE,
Expand All @@ -15,6 +15,7 @@ use crate::{
note_encryption::{
CompactOutputDescription, SaplingDomain, COMPACT_NOTE_SIZE, ENC_CIPHERTEXT_SIZE,
},
sapling_sighash_versioning::{VerBindingSig, VerSpendAuthSig},
value::ValueCommitment,
Nullifier,
};
Expand All @@ -40,16 +41,16 @@ impl Authorization for EffectsOnly {

/// Authorizing data for a bundle of Sapling spends and outputs, ready to be committed to
/// the ledger.
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Clone)]
pub struct Authorized {
// TODO: Make this private.
pub binding_sig: redjubjub::Signature<Binding>,
pub binding_sig: VerBindingSig,
}

impl Authorization for Authorized {
type SpendProof = GrothProofBytes;
type OutputProof = GrothProofBytes;
type AuthSig = redjubjub::Signature<SpendAuth>;
type AuthSig = VerSpendAuthSig;
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -123,7 +124,7 @@ impl<A: Authorization, V> Bundle<A, V> {
nullifier: d.nullifier,
rk: d.rk,
zkproof: spend_proof(&mut context, d.zkproof),
spend_auth_sig: auth_sig(&mut context, d.spend_auth_sig),
spend_auth: auth_sig(&mut context, d.spend_auth),
})
.collect(),
shielded_outputs: self
Expand Down Expand Up @@ -163,7 +164,7 @@ impl<A: Authorization, V> Bundle<A, V> {
nullifier: d.nullifier,
rk: d.rk,
zkproof: spend_proof(&mut context, d.zkproof)?,
spend_auth_sig: auth_sig(&mut context, d.spend_auth_sig)?,
spend_auth: auth_sig(&mut context, d.spend_auth)?,
})
})
.collect::<Result<_, _>>()?,
Expand Down Expand Up @@ -220,15 +221,15 @@ pub struct SpendDescription<A: Authorization> {
nullifier: Nullifier,
rk: redjubjub::VerificationKey<SpendAuth>,
zkproof: A::SpendProof,
spend_auth_sig: A::AuthSig,
spend_auth: A::AuthSig,
}

impl<A: Authorization> core::fmt::Debug for SpendDescription<A> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(
f,
"SpendDescription(cv = {:?}, anchor = {:?}, nullifier = {:?}, rk = {:?}, spend_auth_sig = {:?})",
self.cv, self.anchor, self.nullifier, self.rk, self.spend_auth_sig
"SpendDescription(cv = {:?}, anchor = {:?}, nullifier = {:?}, rk = {:?}, spend_auth = {:?})",
self.cv, self.anchor, self.nullifier, self.rk, self.spend_auth
)
}
}
Expand All @@ -241,15 +242,15 @@ impl<A: Authorization> SpendDescription<A> {
nullifier: Nullifier,
rk: redjubjub::VerificationKey<SpendAuth>,
zkproof: A::SpendProof,
spend_auth_sig: A::AuthSig,
spend_auth: A::AuthSig,
) -> Self {
Self {
cv,
anchor,
nullifier,
rk,
zkproof,
spend_auth_sig,
spend_auth,
}
}

Expand Down Expand Up @@ -279,8 +280,8 @@ impl<A: Authorization> SpendDescription<A> {
}

/// Returns the authorization signature for this spend.
pub fn spend_auth_sig(&self) -> &A::AuthSig {
&self.spend_auth_sig
pub fn spend_auth(&self) -> &A::AuthSig {
&self.spend_auth
}
}

Expand Down Expand Up @@ -315,18 +316,18 @@ impl SpendDescriptionV5 {
self,
anchor: bls12_381::Scalar,
zkproof: GrothProofBytes,
spend_auth_sig: redjubjub::Signature<SpendAuth>,
spend_auth: VerSpendAuthSig,
) -> SpendDescription<A>
where
A: Authorization<SpendProof = GrothProofBytes, AuthSig = redjubjub::Signature<SpendAuth>>,
A: Authorization<SpendProof = GrothProofBytes, AuthSig = VerSpendAuthSig>,
{
SpendDescription {
cv: self.cv,
anchor,
nullifier: self.nullifier,
rk: self.rk,
zkproof,
spend_auth_sig,
spend_auth,
}
}
}
Expand Down Expand Up @@ -522,6 +523,7 @@ pub mod testing {
use crate::{
constants::GROTH_PROOF_SIZE,
note::testing::arb_cmu,
sapling_sighash_versioning::{SaplingSighashVersion, VerBindingSig, VerSpendAuthSig},
value::{
testing::{arb_note_value_bounded, arb_trapdoor},
ValueCommitment, MAX_NOTE_VALUE,
Expand Down Expand Up @@ -568,7 +570,7 @@ pub mod testing {
nullifier,
rk,
zkproof,
spend_auth_sig: sk1.sign(&mut rng, &fake_sighash_bytes),
spend_auth: VerSpendAuthSig::new(SaplingSighashVersion::V0, sk1.sign(&mut rng, &fake_sighash_bytes)),
}
}
}
Expand Down Expand Up @@ -625,7 +627,10 @@ pub mod testing {
shielded_outputs,
value_balance,
authorization: Authorized {
binding_sig: bsk.sign(&mut rng, &fake_bvk_bytes),
binding_sig: VerBindingSig::new(
SaplingSighashVersion::V0,
bsk.sign(&mut rng, &fake_bvk_bytes),
),
},
})
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub mod pczt;
pub mod pedersen_hash;
#[cfg(feature = "circuit")]
pub mod prover;
pub mod sapling_sighash_versioning;
mod spec;
mod tree;
pub mod util;
Expand Down
3 changes: 2 additions & 1 deletion src/pczt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
bundle::GrothProofBytes,
keys::SpendAuthorizingKey,
note::ExtractedNoteCommitment,
sapling_sighash_versioning::VerSpendAuthSig,
value::{NoteValue, ValueCommitTrapdoor, ValueCommitment, ValueSum},
Anchor, MerklePath, Nullifier, PaymentAddress, ProofGenerationKey, Rseed,
};
Expand Down Expand Up @@ -117,7 +118,7 @@ pub struct Spend {
/// The spend authorization signature.
///
/// This is set by the Signer.
pub(crate) spend_auth_sig: Option<redjubjub::Signature<SpendAuth>>,
pub(crate) spend_auth_sig: Option<VerSpendAuthSig>,

/// The address that received the note being spent.
///
Expand Down
24 changes: 22 additions & 2 deletions src/pczt/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
bundle::GrothProofBytes,
keys::{SpendAuthorizingKey, SpendValidatingKey},
note::ExtractedNoteCommitment,
sapling_sighash_versioning::{SaplingSighashVersion, VerSpendAuthSig},
value::{NoteValue, ValueCommitTrapdoor, ValueCommitment, ValueSum},
Anchor, MerklePath, Node, Nullifier, PaymentAddress, ProofGenerationKey, Rseed,
};
Expand Down Expand Up @@ -45,6 +46,15 @@ impl Bundle {
}
}

/// Converts an unsigned 8-bit integer into an `Option<SaplingSighashVersion>`.
fn sapling_sighash_version_from_u8(n: u8) -> Option<SaplingSighashVersion> {
match n {
0 => Some(SaplingSighashVersion::V0),
u8::MAX => Some(SaplingSighashVersion::NoVersion),
_ => None,
}
}

impl Spend {
/// Parses a PCZT spend from its component parts.
#[allow(clippy::too_many_arguments)]
Expand All @@ -53,7 +63,7 @@ impl Spend {
nullifier: [u8; 32],
rk: [u8; 32],
zkproof: Option<GrothProofBytes>,
spend_auth_sig: Option<[u8; 64]>,
spend_auth_sig: Option<(u8, [u8; 64])>,
recipient: Option<[u8; 43]>,
value: Option<u64>,
rcm: Option<[u8; 32]>,
Expand All @@ -75,7 +85,15 @@ impl Spend {
let rk = redjubjub::VerificationKey::try_from(rk)
.map_err(|_| ParseError::InvalidRandomizedKey)?;

let spend_auth_sig = spend_auth_sig.map(redjubjub::Signature::from);
let spend_auth_sig = spend_auth_sig
.as_ref()
.map(|(version, sig)| {
let version = sapling_sighash_version_from_u8(*version)
.ok_or(ParseError::InvalidSighashVersion)?;
let sig = redjubjub::Signature::from(*sig);
Ok(VerSpendAuthSig::new(version, sig))
})
.transpose()?;
Comment on lines +88 to +96
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this backward compatible? If not, let's discuss

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not backward compatible because we add the version for every spend auth signature in PCZT


let recipient = recipient
.as_ref()
Expand Down Expand Up @@ -283,6 +301,8 @@ pub enum ParseError {
InvalidRandomizedKey,
/// An invalid `recipient` was provided.
InvalidRecipient,
/// An invalid `SaplingSighashVersion` was provided.
InvalidSighashVersion,
/// An invalid `alpha` was provided.
InvalidSpendAuthRandomizer,
/// An invalid `cv` was provided.
Expand Down
10 changes: 8 additions & 2 deletions src/pczt/signer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use rand::{CryptoRng, RngCore};

use crate::keys::SpendAuthorizingKey;
use crate::{
keys::SpendAuthorizingKey,
sapling_sighash_versioning::{SaplingSighashVersion, VerSpendAuthSig},
};

impl super::Spend {
/// Signs the Sapling spend with the given spend authorizing key.
Expand All @@ -20,7 +23,10 @@ impl super::Spend {
let rk = redjubjub::VerificationKey::from(&rsk);

if self.rk == rk {
self.spend_auth_sig = Some(rsk.sign(rng, &sighash));
self.spend_auth_sig = Some(VerSpendAuthSig::new(
SaplingSighashVersion::V0,
rsk.sign(rng, &sighash),
));
Ok(())
} else {
Err(SignerError::WrongSpendAuthorizingKey)
Expand Down
Loading
Loading