zip316::transparent: Implement ZIP 316 transparent internal ovk.

This commit is contained in:
therealyingtong 2022-01-11 08:52:28 +08:00 committed by Kris Nuttycombe
parent a4c9f53a3a
commit 5033d29d2f
1 changed files with 52 additions and 1 deletions

View File

@ -1,6 +1,7 @@
use crate::legacy::TransparentAddress;
use crate::{legacy::TransparentAddress, sapling::keys::prf_expand_vec};
use hdwallet::{ExtendedPrivKey, ExtendedPubKey};
use sha2::{Digest, Sha256};
use std::convert::TryInto;
/// A type representing a private key at the BIP-44 external child
/// level `m/44'/<coin_type>'/<account>'/0/<child_index>
@ -42,4 +43,54 @@ impl ExternalPubKey {
pub fn public_key(&self) -> &secp256k1::key::PublicKey {
&self.0.public_key
}
/// Returns the chain code component of this public key.
pub fn chain_code(&self) -> &[u8] {
&self.0.chain_code
}
/// Derives the internal ovk and external ovk corresponding to this
/// transparent fvk. As specified in [ZIP 316][transparent-ovk].
///
/// [transparent-ovk]: https://zips.z.cash/zip-0316#deriving-internal-keys
fn ovk_for_shielding(&self) -> (InternalOvk, ExternalOvk) {
let i_ovk = prf_expand_vec(
&self.chain_code(),
&[&[0xd0], &self.public_key().serialize()],
);
let i_ovk = i_ovk.as_bytes();
let ovk_internal = InternalOvk(i_ovk[..32].try_into().unwrap());
let ovk_external = ExternalOvk(i_ovk[32..].try_into().unwrap());
(ovk_internal, ovk_external)
}
/// Derives the internal ovk corresponding to this transparent fvk.
pub fn internal_ovk(&self) -> InternalOvk {
self.ovk_for_shielding().0
}
/// Derives the external ovk corresponding to this transparent fvk.
pub fn external_ovk(&self) -> ExternalOvk {
self.ovk_for_shielding().1
}
}
/// Internal ovk used for autoshielding.
pub struct InternalOvk([u8; 32]);
impl InternalOvk {
pub fn as_bytes(&self) -> [u8; 32] {
self.0
}
}
/// External ovk used by zcashd for transparent -> shielded spends to
/// external receivers.
pub struct ExternalOvk([u8; 32]);
impl ExternalOvk {
pub fn as_bytes(&self) -> [u8; 32] {
self.0
}
}