From d4457996264c132e7975572790d9669971b58465 Mon Sep 17 00:00:00 2001 From: Deirdre Connolly Date: Sat, 18 Apr 2020 03:21:41 -0400 Subject: [PATCH] Remove the Deref's and make the From's consistent for all key types --- zebra-chain/src/addresses/sapling.rs | 10 +- zebra-chain/src/keys/sapling.rs | 183 +++++++++++++++----------- zebra-chain/src/keys/sapling/tests.rs | 41 +----- 3 files changed, 120 insertions(+), 114 deletions(-) diff --git a/zebra-chain/src/addresses/sapling.rs b/zebra-chain/src/addresses/sapling.rs index 08f8054f..15cc297a 100644 --- a/zebra-chain/src/addresses/sapling.rs +++ b/zebra-chain/src/addresses/sapling.rs @@ -49,8 +49,8 @@ impl fmt::Display for SaplingShieldedAddress { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut bytes = io::Cursor::new(Vec::new()); - let _ = bytes.write_all(&self.diversifier.0[..]); - let _ = bytes.write_all(&self.transmission_key.to_bytes()); + let _ = bytes.write_all(&<[u8; 11]>::from(self.diversifier)); + let _ = bytes.write_all(&<[u8; 32]>::from(self.transmission_key)); let hrp = match self.network { Network::Mainnet => human_readable_parts::MAINNET, @@ -79,8 +79,8 @@ impl std::str::FromStr for SaplingShieldedAddress { human_readable_parts::MAINNET => Network::Mainnet, _ => Network::Testnet, }, - diversifier: sapling::Diversifier(diversifier_bytes), - transmission_key: sapling::TransmissionKey::from_bytes(transmission_key_bytes), + diversifier: sapling::Diversifier::from(diversifier_bytes), + transmission_key: sapling::TransmissionKey::from(transmission_key_bytes), }) } Err(_) => Err(SerializationError::Parse("bech32 decoding error")), @@ -147,7 +147,7 @@ mod tests { sapling::IncomingViewingKey::from((authorizing_key, nullifier_deriving_key)); let diversifier = sapling::Diversifier::new(&mut OsRng); - let transmission_key = sapling::TransmissionKey::from(incoming_viewing_key, diversifier); + let transmission_key = sapling::TransmissionKey::from((incoming_viewing_key, diversifier)); let _sapling_shielded_address = SaplingShieldedAddress { network: Network::Mainnet, diff --git a/zebra-chain/src/keys/sapling.rs b/zebra-chain/src/keys/sapling.rs index bf565b62..cb33bf1e 100644 --- a/zebra-chain/src/keys/sapling.rs +++ b/zebra-chain/src/keys/sapling.rs @@ -17,7 +17,6 @@ use std::{ convert::{From, Into, TryFrom}, fmt, io::{self, Write}, - ops::Deref, str::FromStr, }; @@ -253,24 +252,29 @@ impl SpendingKey { /// _Spend Description_, proving ownership of notes. /// /// [ps]: https://zips.z.cash/protocol/protocol.pdf#saplingkeycomponents +#[derive(Copy, Clone, Eq, PartialEq)] pub struct SpendAuthorizingKey(pub Scalar); -impl Deref for SpendAuthorizingKey { - type Target = Scalar; - - fn deref(&self) -> &Scalar { - &self.0 - } -} - impl fmt::Debug for SpendAuthorizingKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("SpendAuthorizingKey") - .field(&hex::encode(self.to_bytes())) + .field(&hex::encode(<[u8; 32]>::from(*self))) .finish() } } +impl From<[u8; 32]> for SpendAuthorizingKey { + fn from(bytes: [u8; 32]) -> Self { + Self(Scalar::from_bytes(&bytes).unwrap()) + } +} + +impl From for [u8; 32] { + fn from(sk: SpendAuthorizingKey) -> Self { + sk.0.to_bytes() + } +} + impl From for SpendAuthorizingKey { /// Invokes Blake2b-512 as _PRF^expand_, t=0, to derive a /// SpendAuthorizingKey from a SpendingKey. @@ -284,30 +288,41 @@ impl From for SpendAuthorizingKey { } } +impl PartialEq<[u8; 32]> for SpendAuthorizingKey { + fn eq(&self, other: &[u8; 32]) -> bool { + <[u8; 32]>::from(*self) == *other + } +} + /// A _Proof Authorizing Key_, as described in [protocol specification /// §4.2.2][ps]. /// /// Used in the _Spend Statement_ to prove nullifier integrity. /// /// [ps]: https://zips.z.cash/protocol/protocol.pdf#saplingkeycomponents +#[derive(Copy, Clone, Eq, PartialEq)] pub struct ProofAuthorizingKey(pub Scalar); -impl Deref for ProofAuthorizingKey { - type Target = Scalar; - - fn deref(&self) -> &Scalar { - &self.0 - } -} - impl fmt::Debug for ProofAuthorizingKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("ProofAuthorizingKey") - .field(&hex::encode(&self.to_bytes())) + .field(&hex::encode(<[u8; 32]>::from(*self))) .finish() } } +impl From<[u8; 32]> for ProofAuthorizingKey { + fn from(bytes: [u8; 32]) -> Self { + Self(Scalar::from_bytes(&bytes).unwrap()) + } +} + +impl From for [u8; 32] { + fn from(sk: ProofAuthorizingKey) -> Self { + sk.0.to_bytes() + } +} + impl From for ProofAuthorizingKey { /// For this invocation of Blake2b-512 as _PRF^expand_, t=1. /// @@ -320,6 +335,12 @@ impl From for ProofAuthorizingKey { } } +impl PartialEq<[u8; 32]> for ProofAuthorizingKey { + fn eq(&self, other: &[u8; 32]) -> bool { + <[u8; 32]>::from(*self) == *other + } +} + /// An _Outgoing Viewing Key_, as described in [protocol specification /// §4.2.2][ps]. /// @@ -371,12 +392,6 @@ impl PartialEq<[u8; 32]> for OutgoingViewingKey { } } -impl PartialEq for [u8; 32] { - fn eq(&self, other: &OutgoingViewingKey) -> bool { - *self == other.0 - } -} - /// An _Authorizing Key_, as described in [protocol specification /// §4.2.2][ps]. /// @@ -387,6 +402,8 @@ impl PartialEq for [u8; 32] { #[derive(Copy, Clone, Debug)] pub struct AuthorizingKey(pub redjubjub::PublicKey); +impl Eq for AuthorizingKey {} + impl From<[u8; 32]> for AuthorizingKey { fn from(bytes: [u8; 32]) -> Self { Self(redjubjub::PublicKey::try_from(bytes).unwrap()) @@ -401,20 +418,20 @@ impl From for [u8; 32] { impl From for AuthorizingKey { fn from(ask: SpendAuthorizingKey) -> Self { - let sk = redjubjub::SecretKey::::try_from(ask.to_bytes()).unwrap(); + let sk = redjubjub::SecretKey::::try_from(<[u8; 32]>::from(ask)).unwrap(); Self(redjubjub::PublicKey::from(&sk)) } } impl PartialEq for AuthorizingKey { fn eq(&self, other: &Self) -> bool { - Into::<[u8; 32]>::into(self.0) == Into::<[u8; 32]>::into(other.0) + <[u8; 32]>::from(self.0) == <[u8; 32]>::from(other.0) } } impl PartialEq<[u8; 32]> for AuthorizingKey { fn eq(&self, other: &[u8; 32]) -> bool { - Into::<[u8; 32]>::into(self.0) == *other + <[u8; 32]>::from(self.0) == *other } } @@ -427,35 +444,29 @@ impl PartialEq<[u8; 32]> for AuthorizingKey { #[derive(Copy, Clone, PartialEq)] pub struct NullifierDerivingKey(pub jubjub::AffinePoint); +impl fmt::Debug for NullifierDerivingKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("NullifierDerivingKey") + .field("u", &hex::encode(self.0.get_u().to_bytes())) + .field("v", &hex::encode(self.0.get_v().to_bytes())) + .finish() + } +} + impl From<[u8; 32]> for NullifierDerivingKey { fn from(bytes: [u8; 32]) -> Self { Self(jubjub::AffinePoint::from_bytes(bytes).unwrap()) } } +impl Eq for NullifierDerivingKey {} + impl From for [u8; 32] { fn from(nk: NullifierDerivingKey) -> [u8; 32] { nk.0.to_bytes() } } -impl Deref for NullifierDerivingKey { - type Target = jubjub::AffinePoint; - - fn deref(&self) -> &jubjub::AffinePoint { - &self.0 - } -} - -impl fmt::Debug for NullifierDerivingKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("NullifierDerivingKey") - .field("u", &hex::encode(self.get_u().to_bytes())) - .field("v", &hex::encode(self.get_v().to_bytes())) - .finish() - } -} - impl From for NullifierDerivingKey { /// Requires JubJub's _FindGroupHash^J("Zcash_H_", "")_, then uses /// the resulting generator point to scalar multiply the @@ -477,6 +488,12 @@ impl From for NullifierDerivingKey { } } +impl PartialEq<[u8; 32]> for NullifierDerivingKey { + fn eq(&self, other: &[u8; 32]) -> bool { + <[u8; 32]>::from(*self) == *other + } +} + /// Magic human-readable strings used to identify what networks /// Sapling IncomingViewingKeys are associated with when /// encoded/decoded with bech32. @@ -552,7 +569,7 @@ impl From<(AuthorizingKey, NullifierDerivingKey)> for IncomingViewingKey { // // [ps]: https://zips.z.cash/protocol/protocol.pdf#saplingkeycomponents fn from((ask, nk): (AuthorizingKey, NullifierDerivingKey)) -> Self { - let hash_bytes = crh_ivk(ask.into(), nk.to_bytes()); + let hash_bytes = crh_ivk(ask.into(), nk.into()); IncomingViewingKey::from(hash_bytes) } @@ -606,6 +623,18 @@ impl fmt::Debug for Diversifier { } } +impl From<[u8; 11]> for Diversifier { + fn from(bytes: [u8; 11]) -> Self { + Self(bytes) + } +} + +impl From for [u8; 11] { + fn from(d: Diversifier) -> [u8; 11] { + d.0 + } +} + impl From for Diversifier { /// Derives a [_default diversifier_][4.2.2] from a SpendingKey. /// @@ -678,44 +707,50 @@ impl Diversifier { #[derive(Copy, Clone, PartialEq)] pub struct TransmissionKey(pub jubjub::AffinePoint); -impl Deref for TransmissionKey { - type Target = jubjub::AffinePoint; - - fn deref(&self) -> &jubjub::AffinePoint { - &self.0 - } -} - impl fmt::Debug for TransmissionKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("TransmissionKey") - .field("u", &hex::encode(self.get_u().to_bytes())) - .field("v", &hex::encode(self.get_v().to_bytes())) + .field("u", &hex::encode(self.0.get_u().to_bytes())) + .field("v", &hex::encode(self.0.get_v().to_bytes())) .finish() } } impl Eq for TransmissionKey {} -impl TransmissionKey { - /// This includes _KA^Sapling.DerivePublic(ivk, G_d)_, which is just a - /// scalar mult _[ivk]G_d_. - /// - /// https://zips.z.cash/protocol/protocol.pdf#saplingkeycomponents - /// https://zips.z.cash/protocol/protocol.pdf#concretesaplingkeyagreement - pub fn from(ivk: IncomingViewingKey, d: Diversifier) -> Self { - Self(jubjub::AffinePoint::from( - diversify_hash(d.0).unwrap() * ivk.scalar, - )) - } - +impl From<[u8; 32]> for TransmissionKey { /// Attempts to interpret a byte representation of an /// affine point, failing if the element is not on /// the curve or non-canonical. /// /// https://github.com/zkcrypto/jubjub/blob/master/src/lib.rs#L411 - pub fn from_bytes(b: [u8; 32]) -> Self { - Self(jubjub::AffinePoint::from_bytes(b).unwrap()) + fn from(bytes: [u8; 32]) -> Self { + Self(jubjub::AffinePoint::from_bytes(bytes).unwrap()) + } +} + +impl From for [u8; 32] { + fn from(pk_d: TransmissionKey) -> [u8; 32] { + pk_d.0.to_bytes() + } +} + +impl From<(IncomingViewingKey, Diversifier)> for TransmissionKey { + /// This includes _KA^Sapling.DerivePublic(ivk, G_d)_, which is just a + /// scalar mult _[ivk]G_d_. + /// + /// https://zips.z.cash/protocol/protocol.pdf#saplingkeycomponents + /// https://zips.z.cash/protocol/protocol.pdf#concretesaplingkeyagreement + fn from((ivk, d): (IncomingViewingKey, Diversifier)) -> Self { + Self(jubjub::AffinePoint::from( + diversify_hash(d.0).unwrap() * ivk.scalar, + )) + } +} + +impl PartialEq<[u8; 32]> for TransmissionKey { + fn eq(&self, other: &[u8; 32]) -> bool { + <[u8; 32]>::from(*self) == *other } } @@ -737,7 +772,7 @@ mod fvk_hrp { /// test network, the Human-Readable Part is “zviewtestsapling”. /// /// https://zips.z.cash/protocol/protocol.pdf#saplingfullviewingkeyencoding -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Eq, PartialEq)] pub struct FullViewingKey { network: Network, authorizing_key: AuthorizingKey, @@ -762,9 +797,9 @@ impl fmt::Display for FullViewingKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut bytes = io::Cursor::new(Vec::new()); - let _ = bytes.write_all(&Into::<[u8; 32]>::into(self.authorizing_key)); - let _ = bytes.write_all(&Into::<[u8; 32]>::into(self.nullifier_deriving_key)); - let _ = bytes.write_all(&Into::<[u8; 32]>::into(self.outgoing_viewing_key)); + let _ = bytes.write_all(&<[u8; 32]>::from(self.authorizing_key)); + let _ = bytes.write_all(&<[u8; 32]>::from(self.nullifier_deriving_key)); + let _ = bytes.write_all(&<[u8; 32]>::from(self.outgoing_viewing_key)); let hrp = match self.network { Network::Mainnet => fvk_hrp::MAINNET, diff --git a/zebra-chain/src/keys/sapling/tests.rs b/zebra-chain/src/keys/sapling/tests.rs index f2661f6e..3d2a932c 100644 --- a/zebra-chain/src/keys/sapling/tests.rs +++ b/zebra-chain/src/keys/sapling/tests.rs @@ -21,7 +21,7 @@ impl Arbitrary for TransmissionKey { let diversifier = Diversifier::from(spending_key); - return Self::from(incoming_viewing_key, diversifier); + return Self::from((incoming_viewing_key, diversifier)); }) .boxed() } @@ -32,53 +32,24 @@ impl Arbitrary for TransmissionKey { #[cfg(test)] mod tests { - use rand_core::OsRng; - use super::*; - #[test] - fn derive() { - let spending_key = SpendingKey::new(&mut OsRng); - - let spend_authorizing_key = SpendAuthorizingKey::from(spending_key); - let proof_authorizing_key = ProofAuthorizingKey::from(spending_key); - let outgoing_viewing_key = OutgoingViewingKey::from(spending_key); - - let authorizing_key = AuthorizingKey::from(spend_authorizing_key); - let nullifier_deriving_key = NullifierDerivingKey::from(proof_authorizing_key); - // "If ivk = 0, discard this key and start over with a new - // [spending key]." - // https://zips.z.cash/protocol/protocol.pdf#saplingkeycomponents - let incoming_viewing_key = - IncomingViewingKey::from((authorizing_key, nullifier_deriving_key)); - - let diversifier = Diversifier::new(&mut OsRng); - let _transmission_key = TransmissionKey::from(incoming_viewing_key, diversifier); - - let _full_viewing_key = FullViewingKey { - network: Network::default(), - authorizing_key, - nullifier_deriving_key, - outgoing_viewing_key, - }; - } - #[test] fn derive_for_each_test_vector() { for test_vector in test_vectors::TEST_VECTORS.iter() { let spending_key = SpendingKey::from(test_vector.sk); let spend_authorizing_key = SpendAuthorizingKey::from(spending_key); - assert_eq!(spend_authorizing_key.to_bytes(), test_vector.ask); + assert_eq!(spend_authorizing_key, test_vector.ask); let proof_authorizing_key = ProofAuthorizingKey::from(spending_key); - assert_eq!(proof_authorizing_key.to_bytes(), test_vector.nsk); + assert_eq!(proof_authorizing_key, test_vector.nsk); let outgoing_viewing_key = OutgoingViewingKey::from(spending_key); assert_eq!(outgoing_viewing_key, test_vector.ovk); let authorizing_key = AuthorizingKey::from(spend_authorizing_key); assert_eq!(authorizing_key, test_vector.ak); let nullifier_deriving_key = NullifierDerivingKey::from(proof_authorizing_key); - assert_eq!(nullifier_deriving_key.to_bytes(), test_vector.nk); + assert_eq!(nullifier_deriving_key, test_vector.nk); let incoming_viewing_key = IncomingViewingKey::from((authorizing_key, nullifier_deriving_key)); assert_eq!(incoming_viewing_key, test_vector.ivk); @@ -86,8 +57,8 @@ mod tests { let diversifier = Diversifier::from(spending_key); assert_eq!(diversifier, test_vector.default_d); - let transmission_key = TransmissionKey::from(incoming_viewing_key, diversifier); - assert_eq!(transmission_key.to_bytes(), test_vector.default_pk_d); + let transmission_key = TransmissionKey::from((incoming_viewing_key, diversifier)); + assert_eq!(transmission_key, test_vector.default_pk_d); let _full_viewing_key = FullViewingKey { network: Network::default(),