Impl Debug, Display, and FromStr for Sapling FullViewingKey
This commit is contained in:
parent
c30a5a64b2
commit
3eeb9925eb
|
@ -8,8 +8,14 @@
|
||||||
//! [ps]: https://zips.z.cash/protocol/protocol.pdf#saplingkeycomponents
|
//! [ps]: https://zips.z.cash/protocol/protocol.pdf#saplingkeycomponents
|
||||||
//! [3.1]: https://zips.z.cash/protocol/protocol.pdf#addressesandkeys
|
//! [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 blake2b_simd;
|
||||||
use blake2s_simd;
|
use blake2s_simd;
|
||||||
use jubjub;
|
use jubjub;
|
||||||
|
@ -21,6 +27,11 @@ use proptest::{array, prelude::*};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use proptest_derive::Arbitrary;
|
use proptest_derive::Arbitrary;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
serialization::{ReadZcashExt, SerializationError},
|
||||||
|
Network,
|
||||||
|
};
|
||||||
|
|
||||||
/// The [Randomness Beacon][1] ("URS").
|
/// The [Randomness Beacon][1] ("URS").
|
||||||
///
|
///
|
||||||
/// First 64 bytes of the BLAKE2s input during JubJub group hash. 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 {
|
impl From<SpendingKey> for OutgoingViewingKey {
|
||||||
/// For this invocation of Blake2b-512 as _PRF^expand_, t=2.
|
/// For this invocation of Blake2b-512 as _PRF^expand_, t=2.
|
||||||
///
|
///
|
||||||
|
@ -332,6 +350,12 @@ impl From<SpendAuthorizingKey> for AuthorizingKey {
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub struct NullifierDerivingKey(pub jubjub::AffinePoint);
|
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 {
|
impl Deref for NullifierDerivingKey {
|
||||||
type Target = jubjub::AffinePoint;
|
type Target = jubjub::AffinePoint;
|
||||||
|
|
||||||
|
@ -543,6 +567,14 @@ impl Arbitrary for TransmissionKey {
|
||||||
type Strategy = BoxedStrategy<Self>;
|
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
|
/// Full Viewing Keys
|
||||||
///
|
///
|
||||||
/// Allows recognizing both incoming and outgoing notes without having
|
/// 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
|
/// https://zips.z.cash/protocol/protocol.pdf#saplingfullviewingkeyencoding
|
||||||
pub struct FullViewingKey {
|
pub struct FullViewingKey {
|
||||||
|
network: Network,
|
||||||
authorizing_key: AuthorizingKey,
|
authorizing_key: AuthorizingKey,
|
||||||
nullifier_deriving_key: NullifierDerivingKey,
|
nullifier_deriving_key: NullifierDerivingKey,
|
||||||
outgoing_viewing_key: OutgoingViewingKey,
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
|
@ -593,6 +685,7 @@ mod tests {
|
||||||
let _transmission_key = TransmissionKey::from(incoming_viewing_key, diversifier);
|
let _transmission_key = TransmissionKey::from(incoming_viewing_key, diversifier);
|
||||||
|
|
||||||
let _full_viewing_key = FullViewingKey {
|
let _full_viewing_key = FullViewingKey {
|
||||||
|
network: Network::default(),
|
||||||
authorizing_key,
|
authorizing_key,
|
||||||
nullifier_deriving_key,
|
nullifier_deriving_key,
|
||||||
outgoing_viewing_key,
|
outgoing_viewing_key,
|
||||||
|
|
Loading…
Reference in New Issue