Skip to content

Commit

Permalink
Merge of #8198
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Jan 30, 2024
2 parents 18477ec + 52a531d commit 73d11b2
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 3 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5709,6 +5709,7 @@ dependencies = [
"uint",
"x25519-dalek",
"zcash_address",
"zcash_client_backend",
"zcash_encoding",
"zcash_history",
"zcash_note_encryption",
Expand Down
10 changes: 9 additions & 1 deletion zebra-chain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ getblocktemplate-rpcs = [
"zcash_address",
]

# Experimental shielded scanning support
shielded-scan = [
"zcash_client_backend"
]

# Experimental internal miner support
# TODO: Internal miner feature functionality was removed at https://github.com/ZcashFoundation/zebra/issues/8180
# See what was removed at https://github.com/ZcashFoundation/zebra/blob/v1.5.1/zebra-chain/Cargo.toml#L38-L43
Expand Down Expand Up @@ -127,9 +132,12 @@ serde_json = { version = "1.0.113", optional = true }
# Production feature async-error and testing feature proptest-impl
tokio = { version = "1.35.1", optional = true }

# Experimental feature getblocktemplate-rpcs
# Production feature getblocktemplate-rpcs
zcash_address = { version = "0.3.1", optional = true }

# Experimental feature shielded-scan
zcash_client_backend = { version = "0.10.0-rc.1", optional = true }

# Optional testing dependencies
proptest = { version = "1.4.0", optional = true }
proptest-derive = { version = "0.4.0", optional = true }
Expand Down
3 changes: 3 additions & 0 deletions zebra-chain/src/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ mod address;
#[cfg(feature = "getblocktemplate-rpcs")]
pub use address::Address;

#[cfg(feature = "shielded-scan")]
pub mod viewing_key;

pub mod byte_array;

pub use ed25519_zebra as ed25519;
Expand Down
43 changes: 43 additions & 0 deletions zebra-chain/src/primitives/viewing_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//! Type definitions for viewing keys and their hashes.
use crate::parameters::Network;

mod orchard;
mod sapling;

use orchard::OrchardViewingKey;
use sapling::SaplingViewingKey;

#[cfg(test)]
mod tests;

/// A Zcash Sapling or Orchard viewing key
#[derive(Debug, Clone)]
pub enum ViewingKey {
/// A viewing key for Sapling
Sapling(SaplingViewingKey),

/// A viewing key for Orchard
Orchard(OrchardViewingKey),
}

impl ViewingKey {
/// Accepts an encoded Sapling viewing key to decode
///
/// Returns a [`ViewingKey`] if successful, or None otherwise
fn parse_sapling(sapling_key: &str, network: Network) -> Option<Self> {
SaplingViewingKey::parse(sapling_key, network).map(Self::Sapling)
}

/// Accepts an encoded Orchard viewing key to decode
///
/// Returns a [`ViewingKey`] if successful, or None otherwise
fn parse_orchard(sapling_key: &str, network: Network) -> Option<Self> {
OrchardViewingKey::parse(sapling_key, network).map(Self::Orchard)
}

/// Parses an encoded viewing key and returns it as a [`ViewingKey`] type.
pub fn parse(key: &str, network: Network) -> Option<Self> {
Self::parse_sapling(key, network).or_else(|| Self::parse_orchard(key, network))
}
}
17 changes: 17 additions & 0 deletions zebra-chain/src/primitives/viewing_key/orchard.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! Defines types and implements methods for parsing Orchard viewing keys and converting them to `zebra-chain` types
use crate::parameters::Network;

/// A Zcash Orchard viewing key
#[derive(Debug, Clone)]
pub enum OrchardViewingKey {}

impl OrchardViewingKey {
/// Accepts an encoded Orchard viewing key to decode
///
/// Returns a [`OrchardViewingKey`] if successful, or None otherwise
pub fn parse(_key: &str, _network: Network) -> Option<Self> {
// TODO: parse Orchard viewing keys
None
}
}
87 changes: 87 additions & 0 deletions zebra-chain/src/primitives/viewing_key/sapling.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//! Defines types and implements methods for parsing Sapling viewing keys and converting them to `zebra-chain` types
use zcash_client_backend::encoding::decode_extended_full_viewing_key;
use zcash_primitives::{
constants::*,
sapling::keys::{FullViewingKey as SaplingFvk, SaplingIvk},
zip32::DiversifiableFullViewingKey as SaplingDfvk,
};

use crate::parameters::Network;

/// A Zcash Sapling viewing key
#[derive(Debug, Clone)]
pub enum SaplingViewingKey {
/// An incoming viewing key for Sapling
Ivk(Box<SaplingIvk>),

/// A full viewing key for Sapling
Fvk(Box<SaplingFvk>),

/// A diversifiable full viewing key for Sapling
Dfvk(Box<SaplingDfvk>),
}

impl SaplingViewingKey {
/// Accepts an encoded Sapling extended full viewing key to decode
///
/// Returns a [`SaplingViewingKey::Dfvk`] if successful, or None otherwise
fn parse_extended_full_viewing_key(sapling_key: &str, network: Network) -> Option<Self> {
decode_extended_full_viewing_key(network.sapling_efvk_hrp(), sapling_key)
// this should fail often, so a debug-level log is okay
.map_err(|err| debug!(?err, "could not decode Sapling extended full viewing key"))
.ok()
.map(|efvk| Box::new(efvk.to_diversifiable_full_viewing_key()))
.map(Self::Dfvk)
}

/// Accepts an encoded Sapling diversifiable full viewing key to decode
///
/// Returns a [`SaplingViewingKey::Dfvk`] if successful, or None otherwise
fn parse_diversifiable_full_viewing_key(_sapling_key: &str, _network: Network) -> Option<Self> {
// TODO: Parse Sapling diversifiable full viewing key
None
}

/// Accepts an encoded Sapling full viewing key to decode
///
/// Returns a [`SaplingViewingKey::Fvk`] if successful, or None otherwise
fn parse_full_viewing_key(_sapling_key: &str, _network: Network) -> Option<Self> {
// TODO: Parse Sapling full viewing key
None
}

/// Accepts an encoded Sapling incoming viewing key to decode
///
/// Returns a [`SaplingViewingKey::Ivk`] if successful, or None otherwise
fn parse_incoming_viewing_key(_sapling_key: &str, _network: Network) -> Option<Self> {
// TODO: Parse Sapling incoming viewing key
None
}

/// Accepts an encoded Sapling viewing key to decode
///
/// Returns a [`SaplingViewingKey`] if successful, or None otherwise
pub(super) fn parse(key: &str, network: Network) -> Option<Self> {
// TODO: Try types with prefixes first if some don't have prefixes?
Self::parse_extended_full_viewing_key(key, network)
.or_else(|| Self::parse_diversifiable_full_viewing_key(key, network))
.or_else(|| Self::parse_full_viewing_key(key, network))
.or_else(|| Self::parse_incoming_viewing_key(key, network))
}
}

impl Network {
/// Returns the human-readable prefix for an Zcash Sapling extended full viewing key
/// for this network.
fn sapling_efvk_hrp(&self) -> &'static str {
if self.is_a_test_network() {
// Assume custom testnets have the same HRP
//
// TODO: add the regtest HRP here
testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY
} else {
mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY
}
}
}
15 changes: 15 additions & 0 deletions zebra-chain/src/primitives/viewing_key/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//! Tests for zebra-chain viewing key hashes
use super::*;

/// The extended Sapling viewing key of [ZECpages](https://zecpages.com/boardinfo)
pub const ZECPAGES_SAPLING_VIEWING_KEY: &str = "zxviews1q0duytgcqqqqpqre26wkl45gvwwwd706xw608hucmvfalr759ejwf7qshjf5r9aa7323zulvz6plhttp5mltqcgs9t039cx2d09mgq05ts63n8u35hyv6h9nc9ctqqtue2u7cer2mqegunuulq2luhq3ywjcz35yyljewa4mgkgjzyfwh6fr6jd0dzd44ghk0nxdv2hnv4j5nxfwv24rwdmgllhe0p8568sgqt9ckt02v2kxf5ahtql6s0ltjpkckw8gtymxtxuu9gcr0swvz";

/// Tests that `ViewingKey::parse` successfully decodes the zecpages sapling extended full viewing key
#[test]
fn parses_sapling_efvk_correctly() {
let _init_guard = zebra_test::init();

ViewingKey::parse(ZECPAGES_SAPLING_VIEWING_KEY, Network::Mainnet)
.expect("should parse hard-coded viewing key successfully");
}
5 changes: 3 additions & 2 deletions zebra-scan/src/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,9 @@ pub fn scan_block<K: ScanningKey>(
/// Currently only accepts extended full viewing keys, and returns both their diversifiable full
/// viewing key and their individual viewing key, for testing purposes.
///
/// TODO: work out what string format is used for SaplingIvk, if any, and support it here
/// performance: stop returning both the dfvk and ivk for the same key
// TODO: work out what string format is used for SaplingIvk, if any, and support it here
// performance: stop returning both the dfvk and ivk for the same key
// TODO: use `ViewingKey::parse` from zebra-chain instead
pub fn sapling_key_to_scan_block_keys(
sapling_key: &SaplingScanningKey,
network: Network,
Expand Down

0 comments on commit 73d11b2

Please sign in to comment.