Impl Debug, Display, and FromStr for Sapling FullViewingKey

This commit is contained in:
Deirdre Connolly 2020-04-15 04:49:01 -04:00 committed by Deirdre Connolly
parent c30a5a64b2
commit 3eeb9925eb
1 changed files with 94 additions and 1 deletions

View File

@ -8,8 +8,14 @@
//! [ps]: https://zips.z.cash/protocol/protocol.pdf#saplingkeycomponents
//! [3.1]: https://zips.z.cash/protocol/protocol.pdf#addressesandkeys
use std::{convert::TryFrom, fmt, ops::Deref};
use std::{
convert::{From, Into, TryFrom},
fmt,
io::{self, Write},
ops::Deref,
};
use bech32::{self, FromBase32, ToBase32};
use blake2b_simd;
use blake2s_simd;
use jubjub;
@ -21,6 +27,11 @@ use proptest::{array, prelude::*};
#[cfg(test)]
use proptest_derive::Arbitrary;
use crate::{
serialization::{ReadZcashExt, SerializationError},
Network,
};
/// The [Randomness Beacon][1] ("URS").
///
/// First 64 bytes of the BLAKE2s input during JubJub group hash. URS
@ -270,6 +281,13 @@ impl fmt::Debug for OutgoingViewingKey {
}
}
impl From<[u8; 32]> for OutgoingViewingKey {
/// Generate an _OutgoingViewingKey_ from existing bytes.
fn from(bytes: [u8; 32]) -> Self {
Self(bytes)
}
}
impl From<SpendingKey> for OutgoingViewingKey {
/// For this invocation of Blake2b-512 as _PRF^expand_, t=2.
///
@ -332,6 +350,12 @@ impl From<SpendAuthorizingKey> for AuthorizingKey {
#[derive(Copy, Clone, PartialEq)]
pub struct NullifierDerivingKey(pub jubjub::AffinePoint);
impl From<[u8; 32]> for NullifierDerivingKey {
fn from(bytes: [u8; 32]) -> Self {
Self(jubjub::AffinePoint::from_bytes(bytes).unwrap())
}
}
impl Deref for NullifierDerivingKey {
type Target = jubjub::AffinePoint;
@ -543,6 +567,14 @@ impl Arbitrary for TransmissionKey {
type Strategy = BoxedStrategy<Self>;
}
/// Magic human-readable strings used to identify what networks
/// Sapling FullViewingKeys are associated with when encoded/decoded
/// with bech32.
mod fvk_hrp {
pub const MAINNET: &str = "zviews";
pub const TESTNET: &str = "zviewtestsapling";
}
/// Full Viewing Keys
///
/// Allows recognizing both incoming and outgoing notes without having
@ -554,11 +586,71 @@ impl Arbitrary for TransmissionKey {
///
/// https://zips.z.cash/protocol/protocol.pdf#saplingfullviewingkeyencoding
pub struct FullViewingKey {
network: Network,
authorizing_key: AuthorizingKey,
nullifier_deriving_key: NullifierDerivingKey,
outgoing_viewing_key: OutgoingViewingKey,
}
impl fmt::Debug for FullViewingKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("FullViewingKey")
.field("network", &self.network)
.field("authorizing_key", &self.authorizing_key)
.field("nullifier_deriving_key", &self.nullifier_deriving_key)
.field("outgoing_viewing_key", &self.outgoing_viewing_key)
.finish()
}
}
impl fmt::Display for FullViewingKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut bytes = io::Cursor::new(Vec::new());
let auth_key_bytes: [u8; 32] = self.authorizing_key.into();
let _ = bytes.write_all(&auth_key_bytes);
let _ = bytes.write_all(&self.nullifier_deriving_key.to_bytes());
let _ = bytes.write_all(&self.outgoing_viewing_key.0);
let hrp = match self.network {
Network::Mainnet => fvk_hrp::MAINNET,
_ => fvk_hrp::TESTNET,
};
bech32::encode_to_fmt(f, hrp, bytes.get_ref().to_base32()).unwrap()
}
}
impl std::str::FromStr for FullViewingKey {
type Err = SerializationError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match bech32::decode(s) {
Ok((hrp, bytes)) => {
let mut decoded_bytes = io::Cursor::new(Vec::<u8>::from_base32(&bytes).unwrap());
let authorizing_key_bytes = decoded_bytes.read_32_bytes()?;
let nullifier_deriving_key_bytes = decoded_bytes.read_32_bytes()?;
let outgoing_key_bytes = decoded_bytes.read_32_bytes()?;
Ok(FullViewingKey {
network: match hrp.as_str() {
fvk_hrp::MAINNET => Network::Mainnet,
_ => Network::Testnet,
},
authorizing_key: AuthorizingKey::from(authorizing_key_bytes),
nullifier_deriving_key: NullifierDerivingKey::from(
nullifier_deriving_key_bytes,
),
outgoing_viewing_key: OutgoingViewingKey::from(outgoing_key_bytes),
})
}
Err(_) => Err(SerializationError::Parse("bech32 decoding error")),
}
}
}
#[cfg(test)]
mod tests {
@ -593,6 +685,7 @@ mod tests {
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,