zebra_chain/primitives/viewing_key/sapling.rs
1//! Defines types and implements methods for parsing Sapling viewing keys and converting them to `zebra-chain` types
2
3use sapling_crypto::keys::{FullViewingKey as SaplingFvk, SaplingIvk};
4use zcash_client_backend::{
5 encoding::decode_extended_full_viewing_key,
6 keys::sapling::DiversifiableFullViewingKey as SaplingDfvk,
7};
8use zcash_protocol::constants::*;
9
10use crate::parameters::Network;
11
12/// A Zcash Sapling viewing key
13#[derive(Debug, Clone)]
14pub enum SaplingViewingKey {
15 /// An incoming viewing key for Sapling
16 Ivk(Box<SaplingIvk>),
17
18 /// A full viewing key for Sapling
19 Fvk(Box<SaplingFvk>),
20
21 /// A diversifiable full viewing key for Sapling
22 Dfvk(Box<SaplingDfvk>),
23}
24
25impl SaplingViewingKey {
26 /// Accepts an encoded Sapling extended full viewing key to decode
27 ///
28 /// Returns a [`SaplingViewingKey::Dfvk`] if successful, or None otherwise
29 fn parse_extended_full_viewing_key(sapling_key: &str, network: &Network) -> Option<Self> {
30 decode_extended_full_viewing_key(network.sapling_efvk_hrp(), sapling_key)
31 // this should fail often, so a debug-level log is okay
32 .map_err(|err| debug!(?err, "could not decode Sapling extended full viewing key"))
33 .ok()
34 .map(|efvk| Box::new(efvk.to_diversifiable_full_viewing_key()))
35 .map(Self::Dfvk)
36 }
37
38 /// Accepts an encoded Sapling diversifiable full viewing key to decode
39 ///
40 /// Returns a [`SaplingViewingKey::Dfvk`] if successful, or None otherwise
41 fn parse_diversifiable_full_viewing_key(
42 _sapling_key: &str,
43 _network: &Network,
44 ) -> Option<Self> {
45 // TODO: Parse Sapling diversifiable full viewing key
46 None
47 }
48
49 /// Accepts an encoded Sapling full viewing key to decode
50 ///
51 /// Returns a [`SaplingViewingKey::Fvk`] if successful, or None otherwise
52 fn parse_full_viewing_key(_sapling_key: &str, _network: &Network) -> Option<Self> {
53 // TODO: Parse Sapling full viewing key
54 None
55 }
56
57 /// Accepts an encoded Sapling incoming viewing key to decode
58 ///
59 /// Returns a [`SaplingViewingKey::Ivk`] if successful, or None otherwise
60 fn parse_incoming_viewing_key(_sapling_key: &str, _network: &Network) -> Option<Self> {
61 // TODO: Parse Sapling incoming viewing key
62 None
63 }
64
65 /// Accepts an encoded Sapling viewing key to decode
66 ///
67 /// Returns a [`SaplingViewingKey`] if successful, or None otherwise
68 pub(super) fn parse(key: &str, network: &Network) -> Option<Self> {
69 // TODO: Try types with prefixes first if some don't have prefixes?
70 Self::parse_extended_full_viewing_key(key, network)
71 .or_else(|| Self::parse_diversifiable_full_viewing_key(key, network))
72 .or_else(|| Self::parse_full_viewing_key(key, network))
73 .or_else(|| Self::parse_incoming_viewing_key(key, network))
74 }
75}
76
77impl Network {
78 /// Returns the human-readable prefix for an Zcash Sapling extended full viewing key
79 /// for this network.
80 pub fn sapling_efvk_hrp(&self) -> &'static str {
81 if self.is_a_test_network() {
82 // Assume custom testnets have the same HRP
83 //
84 // TODO: add the regtest HRP here
85 testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY
86 } else {
87 mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY
88 }
89 }
90}