Impl Display/FromStr for Sapling IncomingViewingKey, including network field

This commit is contained in:
Deirdre Connolly 2020-04-15 05:16:14 -04:00 committed by Deirdre Connolly
parent cdfcdc4751
commit 68c281c590
1 changed files with 55 additions and 11 deletions

View File

@ -394,6 +394,14 @@ impl From<ProofAuthorizingKey> for NullifierDerivingKey {
}
}
/// Magic human-readable strings used to identify what networks
/// Sapling IncomingViewingKeys are associated with when
/// encoded/decoded with bech32.
mod ivk_hrp {
pub const MAINNET: &str = "zivks";
pub const TESTNET: &str = "zivktestsapling";
}
/// An _Incoming Viewing Key_, as described in [protocol specification
/// §4.2.2][ps].
///
@ -401,13 +409,18 @@ impl From<ProofAuthorizingKey> for NullifierDerivingKey {
///
/// [ps]: https://zips.z.cash/protocol/protocol.pdf#saplingkeycomponents
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct IncomingViewingKey(pub Scalar);
pub struct IncomingViewingKey {
network: Network,
scalar: Scalar,
}
// TODO: impl a From that accepts a Network?
impl Deref for IncomingViewingKey {
type Target = Scalar;
fn deref(&self) -> &Scalar {
&self.0
&self.scalar
}
}
@ -419,6 +432,41 @@ impl fmt::Debug for IncomingViewingKey {
}
}
impl fmt::Display for IncomingViewingKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let hrp = match self.network {
Network::Mainnet => ivk_hrp::MAINNET,
_ => ivk_hrp::TESTNET,
};
bech32::encode_to_fmt(f, hrp, &self.scalar.to_bytes().to_base32()).unwrap()
}
}
impl std::str::FromStr for IncomingViewingKey {
type Err = SerializationError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match bech32::decode(s) {
Ok((hrp, bytes)) => {
let decoded = Vec::<u8>::from_base32(&bytes).unwrap();
let mut scalar_bytes = [0u8; 32];
scalar_bytes[..].copy_from_slice(&decoded[0..32]);
Ok(IncomingViewingKey {
network: match hrp.as_str() {
ivk_hrp::MAINNET => Network::Mainnet,
_ => Network::Testnet,
},
scalar: Scalar::from_bytes(&scalar_bytes).unwrap(),
})
}
Err(_) => Err(SerializationError::Parse("bech32 decoding error")),
}
}
}
impl IncomingViewingKey {
/// For this invocation of Blake2s-256 as _CRH^ivk_.
///
@ -447,7 +495,10 @@ impl IncomingViewingKey {
// https://github.com/zcash/librustzcash/blob/master/zcash_primitives/src/primitives.rs#L86
hash_bytes[31] &= 0b0000_0111;
Self(Scalar::from_bytes(&hash_bytes).unwrap())
Self {
network: Network::default(),
scalar: Scalar::from_bytes(&hash_bytes).unwrap(),
}
}
}
@ -534,7 +585,7 @@ impl TransmissionKey {
/// 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.0,
diversify_hash(d.0).unwrap() * ivk.scalar,
))
}
@ -658,13 +709,6 @@ mod tests {
use super::*;
#[test]
fn check_deref() {
let ivk = IncomingViewingKey(jubjub::Fr::zero());
ivk.to_bytes();
}
#[test]
fn derive() {
let spending_key = SpendingKey::new(&mut OsRng);