diff --git a/Cargo.lock b/Cargo.lock index 750ccdd26..d88d1524b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3002,6 +3002,7 @@ dependencies = [ "f4jumble", "proptest", "zcash_encoding", + "zcash_protocol", ] [[package]] @@ -3239,7 +3240,6 @@ dependencies = [ "incrementalmerkletree", "memuse", "proptest", - "zcash_address", ] [[package]] diff --git a/components/zcash_address/CHANGELOG.md b/components/zcash_address/CHANGELOG.md index 780712c60..4189e1885 100644 --- a/components/zcash_address/CHANGELOG.md +++ b/components/zcash_address/CHANGELOG.md @@ -7,6 +7,12 @@ and this library adheres to Rust's notion of ## [Unreleased] +### Removed +- `zcash_address::kind::p2pkh` - use constants from `zcash_protocol` instead. +- `zcash_address::kind::p2sh` - use constants from `zcash_protocol` instead. +- `zcash_address::kind::sapling` - use constants from `zcash_protocol` instead. +- `zcash_address::kind::sprout` - use constants from `zcash_protocol` instead. + ## [0.3.1] - 2024-01-12 ### Fixed - Stubs for `zcash_address::convert` traits that are created by `rust-analyzer` diff --git a/components/zcash_address/Cargo.toml b/components/zcash_address/Cargo.toml index b797ae22d..e8ed075a5 100644 --- a/components/zcash_address/Cargo.toml +++ b/components/zcash_address/Cargo.toml @@ -22,7 +22,8 @@ rustdoc-args = ["--cfg", "docsrs"] bech32 = "0.9" bs58 = { version = "0.5", features = ["check"] } f4jumble = { version = "0.1", path = "../f4jumble" } -zcash_encoding = { version = "0.2", path = "../zcash_encoding" } +zcash_protocol.workspace = true +zcash_encoding.workspace = true [dev-dependencies] assert_matches = "1.3.0" diff --git a/components/zcash_address/src/encoding.rs b/components/zcash_address/src/encoding.rs index 9e5e422ce..2f5bf8445 100644 --- a/components/zcash_address/src/encoding.rs +++ b/components/zcash_address/src/encoding.rs @@ -1,9 +1,11 @@ use std::{convert::TryInto, error::Error, fmt, str::FromStr}; use bech32::{self, FromBase32, ToBase32, Variant}; +use zcash_protocol::consensus::{NetworkConstants, NetworkType}; +use zcash_protocol::constants::{mainnet, regtest, testnet}; use crate::kind::unified::Encoding; -use crate::{kind::*, AddressKind, Network, ZcashAddress}; +use crate::{kind::*, AddressKind, ZcashAddress}; /// An error while attempting to parse a string as a Zcash address. #[derive(Debug, PartialEq, Eq)] @@ -68,9 +70,9 @@ impl FromStr for ZcashAddress { let data = Vec::::from_base32(&data).map_err(|_| ParseError::InvalidEncoding)?; let net = match hrp.as_str() { - sapling::MAINNET => Network::Main, - sapling::TESTNET => Network::Test, - sapling::REGTEST => Network::Regtest, + mainnet::HRP_SAPLING_PAYMENT_ADDRESS => NetworkType::Main, + testnet::HRP_SAPLING_PAYMENT_ADDRESS => NetworkType::Test, + regtest::HRP_SAPLING_PAYMENT_ADDRESS => NetworkType::Regtest, // We will not define new Bech32 address encodings. _ => { return Err(ParseError::NotZcash); @@ -86,23 +88,33 @@ impl FromStr for ZcashAddress { // The rest use Base58Check. if let Ok(decoded) = bs58::decode(s).with_check(None).into_vec() { - let net = match decoded[..2].try_into().unwrap() { - sprout::MAINNET | p2pkh::MAINNET | p2sh::MAINNET => Network::Main, - sprout::TESTNET | p2pkh::TESTNET | p2sh::TESTNET => Network::Test, - // We will not define new Base58Check address encodings. - _ => return Err(ParseError::NotZcash), - }; + if decoded.len() >= 2 { + let (prefix, net) = match decoded[..2].try_into().unwrap() { + prefix @ (mainnet::B58_PUBKEY_ADDRESS_PREFIX + | mainnet::B58_SCRIPT_ADDRESS_PREFIX + | mainnet::B58_SPROUT_ADDRESS_PREFIX) => (prefix, NetworkType::Main), + prefix @ (testnet::B58_PUBKEY_ADDRESS_PREFIX + | testnet::B58_SCRIPT_ADDRESS_PREFIX + | testnet::B58_SPROUT_ADDRESS_PREFIX) => (prefix, NetworkType::Test), + // We will not define new Base58Check address encodings. + _ => return Err(ParseError::NotZcash), + }; - return match decoded[..2].try_into().unwrap() { - sprout::MAINNET | sprout::TESTNET => { - decoded[2..].try_into().map(AddressKind::Sprout) + return match prefix { + mainnet::B58_SPROUT_ADDRESS_PREFIX | testnet::B58_SPROUT_ADDRESS_PREFIX => { + decoded[2..].try_into().map(AddressKind::Sprout) + } + mainnet::B58_PUBKEY_ADDRESS_PREFIX | testnet::B58_PUBKEY_ADDRESS_PREFIX => { + decoded[2..].try_into().map(AddressKind::P2pkh) + } + mainnet::B58_SCRIPT_ADDRESS_PREFIX | testnet::B58_SCRIPT_ADDRESS_PREFIX => { + decoded[2..].try_into().map(AddressKind::P2sh) + } + _ => unreachable!(), } - p2pkh::MAINNET | p2pkh::TESTNET => decoded[2..].try_into().map(AddressKind::P2pkh), - p2sh::MAINNET | p2sh::TESTNET => decoded[2..].try_into().map(AddressKind::P2sh), - _ => unreachable!(), + .map_err(|_| ParseError::InvalidEncoding) + .map(|kind| ZcashAddress { kind, net }); } - .map_err(|_| ParseError::InvalidEncoding) - .map(|kind| ZcashAddress { kind, net }); }; // If it's not valid Bech32, Bech32m, or Base58Check, it's not a Zcash address. @@ -124,36 +136,13 @@ fn encode_b58(prefix: [u8; 2], data: &[u8]) -> String { impl fmt::Display for ZcashAddress { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let encoded = match &self.kind { - AddressKind::Sprout(data) => encode_b58( - match self.net { - Network::Main => sprout::MAINNET, - Network::Test | Network::Regtest => sprout::TESTNET, - }, - data, - ), - AddressKind::Sapling(data) => encode_bech32( - match self.net { - Network::Main => sapling::MAINNET, - Network::Test => sapling::TESTNET, - Network::Regtest => sapling::REGTEST, - }, - data, - ), + AddressKind::Sprout(data) => encode_b58(self.net.b58_sprout_address_prefix(), data), + AddressKind::Sapling(data) => { + encode_bech32(self.net.hrp_sapling_payment_address(), data) + } AddressKind::Unified(addr) => addr.encode(&self.net), - AddressKind::P2pkh(data) => encode_b58( - match self.net { - Network::Main => p2pkh::MAINNET, - Network::Test | Network::Regtest => p2pkh::TESTNET, - }, - data, - ), - AddressKind::P2sh(data) => encode_b58( - match self.net { - Network::Main => p2sh::MAINNET, - Network::Test | Network::Regtest => p2sh::TESTNET, - }, - data, - ), + AddressKind::P2pkh(data) => encode_b58(self.net.b58_pubkey_address_prefix(), data), + AddressKind::P2sh(data) => encode_b58(self.net.b58_script_address_prefix(), data), }; write!(f, "{}", encoded) } @@ -162,7 +151,7 @@ impl fmt::Display for ZcashAddress { #[cfg(test)] mod tests { use super::*; - use crate::kind::unified; + use crate::{kind::unified, Network}; fn encoding(encoded: &str, decoded: ZcashAddress) { assert_eq!(decoded.to_string(), encoded); diff --git a/components/zcash_address/src/kind.rs b/components/zcash_address/src/kind.rs index 5397c027f..38b4557a6 100644 --- a/components/zcash_address/src/kind.rs +++ b/components/zcash_address/src/kind.rs @@ -1,7 +1 @@ pub mod unified; - -pub(crate) mod sapling; -pub(crate) mod sprout; - -pub(crate) mod p2pkh; -pub(crate) mod p2sh; diff --git a/components/zcash_address/src/kind/p2pkh.rs b/components/zcash_address/src/kind/p2pkh.rs deleted file mode 100644 index a37377d3c..000000000 --- a/components/zcash_address/src/kind/p2pkh.rs +++ /dev/null @@ -1,5 +0,0 @@ -/// The prefix for a Base58Check-encoded mainnet transparent P2PKH address. -pub(crate) const MAINNET: [u8; 2] = [0x1c, 0xb8]; - -/// The prefix for a Base58Check-encoded testnet transparent P2PKH address. -pub(crate) const TESTNET: [u8; 2] = [0x1d, 0x25]; diff --git a/components/zcash_address/src/kind/p2sh.rs b/components/zcash_address/src/kind/p2sh.rs deleted file mode 100644 index 1ebef52ab..000000000 --- a/components/zcash_address/src/kind/p2sh.rs +++ /dev/null @@ -1,5 +0,0 @@ -/// The prefix for a Base58Check-encoded mainnet transparent P2SH address. -pub(crate) const MAINNET: [u8; 2] = [0x1c, 0xbd]; - -/// The prefix for a Base58Check-encoded testnet transparent P2SH address. -pub(crate) const TESTNET: [u8; 2] = [0x1c, 0xba]; diff --git a/components/zcash_address/src/kind/sapling.rs b/components/zcash_address/src/kind/sapling.rs deleted file mode 100644 index 6f2e945b9..000000000 --- a/components/zcash_address/src/kind/sapling.rs +++ /dev/null @@ -1,20 +0,0 @@ -/// The HRP for a Bech32-encoded mainnet Sapling address. -/// -/// Defined in the [Zcash Protocol Specification section 5.6.4][saplingpaymentaddrencoding]. -/// -/// [saplingpaymentaddrencoding]: https://zips.z.cash/protocol/protocol.pdf#saplingpaymentaddrencoding -pub(crate) const MAINNET: &str = "zs"; - -/// The HRP for a Bech32-encoded testnet Sapling address. -/// -/// Defined in the [Zcash Protocol Specification section 5.6.4][saplingpaymentaddrencoding]. -/// -/// [saplingpaymentaddrencoding]: https://zips.z.cash/protocol/protocol.pdf#saplingpaymentaddrencoding -pub(crate) const TESTNET: &str = "ztestsapling"; - -/// The HRP for a Bech32-encoded regtest Sapling address. -/// -/// It is defined in [the `zcashd` codebase]. -/// -/// [the `zcashd` codebase]: https://github.com/zcash/zcash/blob/128d863fb8be39ee294fda397c1ce3ba3b889cb2/src/chainparams.cpp#L493 -pub(crate) const REGTEST: &str = "zregtestsapling"; diff --git a/components/zcash_address/src/kind/sprout.rs b/components/zcash_address/src/kind/sprout.rs deleted file mode 100644 index 06a8a03c7..000000000 --- a/components/zcash_address/src/kind/sprout.rs +++ /dev/null @@ -1,13 +0,0 @@ -/// The prefix for a Base58Check-encoded mainnet Sprout address. -/// -/// Defined in the [Zcash Protocol Specification section 5.6.3][sproutpaymentaddrencoding]. -/// -/// [sproutpaymentaddrencoding]: https://zips.z.cash/protocol/protocol.pdf#sproutpaymentaddrencoding -pub(crate) const MAINNET: [u8; 2] = [0x16, 0x9a]; - -/// The prefix for a Base58Check-encoded testnet Sprout address. -/// -/// Defined in the [Zcash Protocol Specification section 5.6.3][sproutpaymentaddrencoding]. -/// -/// [sproutpaymentaddrencoding]: https://zips.z.cash/protocol/protocol.pdf#sproutpaymentaddrencoding -pub(crate) const TESTNET: [u8; 2] = [0x16, 0xb6]; diff --git a/components/zcash_address/src/lib.rs b/components/zcash_address/src/lib.rs index a16281943..6f516a941 100644 --- a/components/zcash_address/src/lib.rs +++ b/components/zcash_address/src/lib.rs @@ -141,6 +141,7 @@ pub use convert::{ }; pub use encoding::ParseError; pub use kind::unified; +pub use zcash_protocol::consensus::NetworkType as Network; /// A Zcash address. #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -149,20 +150,6 @@ pub struct ZcashAddress { kind: AddressKind, } -/// The Zcash network for which an address is encoded. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum Network { - /// Zcash Mainnet. - Main, - /// Zcash Testnet. - Test, - /// Private integration / regression testing, used in `zcashd`. - /// - /// For some address types there is no distinction between test and regtest encodings; - /// those will always be parsed as `Network::Test`. - Regtest, -} - /// Known kinds of Zcash addresses. #[derive(Clone, Debug, PartialEq, Eq, Hash)] enum AddressKind { diff --git a/components/zcash_protocol/CHANGELOG.md b/components/zcash_protocol/CHANGELOG.md index c29a7fd01..f6b80a9c7 100644 --- a/components/zcash_protocol/CHANGELOG.md +++ b/components/zcash_protocol/CHANGELOG.md @@ -15,6 +15,11 @@ The entries below are relative to the `zcash_primitives` crate as of the tag - `consensus` - `constants` - `zcash_protocol::value` replaces `zcash_primitives::transaction::components::amount` +- `zcash_protocol::consensus`: + - `NetworkConstants` has been extracted from the `Parameters` trait. + - `NetworkType` + - `Parameters::b58_sprout_address_prefix` +- `zcash_protocol::constants::{mainnet, testnet}::B58_SPROUT_ADDRESS_PREFIX` - Added in `zcash_protocol::value`: - `Zatoshis` - `ZatBalance` @@ -35,3 +40,7 @@ The entries below are relative to the `zcash_primitives` crate as of the tag - `TryFrom for Amount` - `From for sapling::value::NoteValue>` - `TryFrom for NonNegativeAmount` +- `zcash_protocol::consensus::Parameters` has been split into two traits, with + the `NetworkConstants` trait providing all network constant accessors. Also, + the `address_network` method has been replaced with a new `network_type` + method that serves the same purpose. diff --git a/components/zcash_protocol/Cargo.toml b/components/zcash_protocol/Cargo.toml index 03cc53b3b..b5c8f651d 100644 --- a/components/zcash_protocol/Cargo.toml +++ b/components/zcash_protocol/Cargo.toml @@ -20,8 +20,6 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] -zcash_address.workspace = true - # - Logging and metrics memuse.workspace = true diff --git a/components/zcash_protocol/src/consensus.rs b/components/zcash_protocol/src/consensus.rs index c060b68f8..aabcebcde 100644 --- a/components/zcash_protocol/src/consensus.rs +++ b/components/zcash_protocol/src/consensus.rs @@ -5,9 +5,11 @@ use std::cmp::{Ord, Ordering}; use std::convert::TryFrom; use std::fmt; use std::ops::{Add, Bound, RangeBounds, Sub}; -use zcash_address; -use crate::constants; +use crate::constants::{mainnet, regtest, testnet}; + +#[cfg(feature = "local-consensus")] +use crate::local_consensus::LocalNetwork; /// A wrapper type representing blockchain heights. /// @@ -136,8 +138,142 @@ impl Sub for BlockHeight { } } +/// Constants associated with a given Zcash network. +pub trait NetworkConstants: Clone { + /// The coin type for ZEC, as defined by [SLIP 44]. + /// + /// [SLIP 44]: https://github.com/satoshilabs/slips/blob/master/slip-0044.md + fn coin_type(&self) -> u32; + + /// Returns the human-readable prefix for Bech32-encoded Sapling extended spending keys + /// the network to which this NetworkConstants value applies. + /// + /// Defined in [ZIP 32]. + /// + /// [`ExtendedSpendingKey`]: zcash_primitives::zip32::ExtendedSpendingKey + /// [ZIP 32]: https://github.com/zcash/zips/blob/master/zip-0032.rst + fn hrp_sapling_extended_spending_key(&self) -> &'static str; + + /// Returns the human-readable prefix for Bech32-encoded Sapling extended full + /// viewing keys for the network to which this NetworkConstants value applies. + /// + /// Defined in [ZIP 32]. + /// + /// [`ExtendedFullViewingKey`]: zcash_primitives::zip32::ExtendedFullViewingKey + /// [ZIP 32]: https://github.com/zcash/zips/blob/master/zip-0032.rst + fn hrp_sapling_extended_full_viewing_key(&self) -> &'static str; + + /// Returns the Bech32-encoded human-readable prefix for Sapling payment addresses + /// viewing keys for the network to which this NetworkConstants value applies. + /// + /// Defined in section 5.6.4 of the [Zcash Protocol Specification]. + /// + /// [`PaymentAddress`]: zcash_primitives::primitives::PaymentAddress + /// [Zcash Protocol Specification]: https://github.com/zcash/zips/blob/master/protocol/protocol.pdf + fn hrp_sapling_payment_address(&self) -> &'static str; + + /// Returns the human-readable prefix for Base58Check-encoded Sprout + /// payment addresses for the network to which this NetworkConstants value + /// applies. + /// + /// Defined in the [Zcash Protocol Specification section 5.6.3][sproutpaymentaddrencoding]. + /// + /// [sproutpaymentaddrencoding]: https://zips.z.cash/protocol/protocol.pdf#sproutpaymentaddrencoding + fn b58_sprout_address_prefix(&self) -> [u8; 2]; + + /// Returns the human-readable prefix for Base58Check-encoded transparent + /// pay-to-public-key-hash payment addresses for the network to which this NetworkConstants value + /// applies. + /// + /// [`TransparentAddress::PublicKey`]: zcash_primitives::legacy::TransparentAddress::PublicKey + fn b58_pubkey_address_prefix(&self) -> [u8; 2]; + + /// Returns the human-readable prefix for Base58Check-encoded transparent pay-to-script-hash + /// payment addresses for the network to which this NetworkConstants value applies. + /// + /// [`TransparentAddress::Script`]: zcash_primitives::legacy::TransparentAddress::Script + fn b58_script_address_prefix(&self) -> [u8; 2]; +} + +/// The enumeration of known Zcash network types. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum NetworkType { + /// Zcash Mainnet. + Main, + /// Zcash Testnet. + Test, + /// Private integration / regression testing, used in `zcashd`. + /// + /// For some address types there is no distinction between test and regtest encodings; + /// those will always be parsed as `Network::Test`. + Regtest, +} + +memuse::impl_no_dynamic_usage!(NetworkType); + +impl NetworkConstants for NetworkType { + fn coin_type(&self) -> u32 { + match self { + NetworkType::Main => mainnet::COIN_TYPE, + NetworkType::Test => testnet::COIN_TYPE, + NetworkType::Regtest => regtest::COIN_TYPE, + } + } + + fn hrp_sapling_extended_spending_key(&self) -> &'static str { + match self { + NetworkType::Main => mainnet::HRP_SAPLING_EXTENDED_SPENDING_KEY, + NetworkType::Test => testnet::HRP_SAPLING_EXTENDED_SPENDING_KEY, + NetworkType::Regtest => regtest::HRP_SAPLING_EXTENDED_SPENDING_KEY, + } + } + + fn hrp_sapling_extended_full_viewing_key(&self) -> &'static str { + match self { + NetworkType::Main => mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, + NetworkType::Test => testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, + NetworkType::Regtest => regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, + } + } + + fn hrp_sapling_payment_address(&self) -> &'static str { + match self { + NetworkType::Main => mainnet::HRP_SAPLING_PAYMENT_ADDRESS, + NetworkType::Test => testnet::HRP_SAPLING_PAYMENT_ADDRESS, + NetworkType::Regtest => regtest::HRP_SAPLING_PAYMENT_ADDRESS, + } + } + + fn b58_sprout_address_prefix(&self) -> [u8; 2] { + match self { + NetworkType::Main => mainnet::B58_SPROUT_ADDRESS_PREFIX, + NetworkType::Test => testnet::B58_SPROUT_ADDRESS_PREFIX, + NetworkType::Regtest => regtest::B58_SPROUT_ADDRESS_PREFIX, + } + } + + fn b58_pubkey_address_prefix(&self) -> [u8; 2] { + match self { + NetworkType::Main => mainnet::B58_PUBKEY_ADDRESS_PREFIX, + NetworkType::Test => testnet::B58_PUBKEY_ADDRESS_PREFIX, + NetworkType::Regtest => regtest::B58_PUBKEY_ADDRESS_PREFIX, + } + } + + fn b58_script_address_prefix(&self) -> [u8; 2] { + match self { + NetworkType::Main => mainnet::B58_SCRIPT_ADDRESS_PREFIX, + NetworkType::Test => testnet::B58_SCRIPT_ADDRESS_PREFIX, + NetworkType::Regtest => regtest::B58_SCRIPT_ADDRESS_PREFIX, + } + } +} + /// Zcash consensus parameters. pub trait Parameters: Clone { + /// Returns the type of network configured by this set of consensus parameters. + fn network_type(&self) -> NetworkType; + /// Returns the activation height for a particular network upgrade, /// if an activation height has been set. fn activation_height(&self, nu: NetworkUpgrade) -> Option; @@ -147,55 +283,36 @@ pub trait Parameters: Clone { fn is_nu_active(&self, nu: NetworkUpgrade, height: BlockHeight) -> bool { self.activation_height(nu).map_or(false, |h| h <= height) } +} - /// The coin type for ZEC, as defined by [SLIP 44]. - /// - /// [SLIP 44]: https://github.com/satoshilabs/slips/blob/master/slip-0044.md - fn coin_type(&self) -> u32; +impl NetworkConstants for P { + fn coin_type(&self) -> u32 { + self.network_type().coin_type() + } - /// Returns the standard network constant for address encoding. Returns - /// 'None' for nonstandard networks. - fn address_network(&self) -> Option; + fn hrp_sapling_extended_spending_key(&self) -> &'static str { + self.network_type().hrp_sapling_extended_spending_key() + } - /// Returns the human-readable prefix for Bech32-encoded Sapling extended spending keys - /// the network to which this Parameters value applies. - /// - /// Defined in [ZIP 32]. - /// - /// [`ExtendedSpendingKey`]: zcash_primitives::zip32::ExtendedSpendingKey - /// [ZIP 32]: https://github.com/zcash/zips/blob/master/zip-0032.rst - fn hrp_sapling_extended_spending_key(&self) -> &str; + fn hrp_sapling_extended_full_viewing_key(&self) -> &'static str { + self.network_type().hrp_sapling_extended_full_viewing_key() + } - /// Returns the human-readable prefix for Bech32-encoded Sapling extended full - /// viewing keys for the network to which this Parameters value applies. - /// - /// Defined in [ZIP 32]. - /// - /// [`ExtendedFullViewingKey`]: zcash_primitives::zip32::ExtendedFullViewingKey - /// [ZIP 32]: https://github.com/zcash/zips/blob/master/zip-0032.rst - fn hrp_sapling_extended_full_viewing_key(&self) -> &str; + fn hrp_sapling_payment_address(&self) -> &'static str { + self.network_type().hrp_sapling_payment_address() + } - /// Returns the Bech32-encoded human-readable prefix for Sapling payment addresses - /// viewing keys for the network to which this Parameters value applies. - /// - /// Defined in section 5.6.4 of the [Zcash Protocol Specification]. - /// - /// [`PaymentAddress`]: zcash_primitives::primitives::PaymentAddress - /// [Zcash Protocol Specification]: https://github.com/zcash/zips/blob/master/protocol/protocol.pdf - fn hrp_sapling_payment_address(&self) -> &str; + fn b58_sprout_address_prefix(&self) -> [u8; 2] { + self.network_type().b58_sprout_address_prefix() + } - /// Returns the human-readable prefix for Base58Check-encoded transparent - /// pay-to-public-key-hash payment addresses for the network to which this Parameters value - /// applies. - /// - /// [`TransparentAddress::PublicKey`]: zcash_primitives::legacy::TransparentAddress::PublicKey - fn b58_pubkey_address_prefix(&self) -> [u8; 2]; + fn b58_pubkey_address_prefix(&self) -> [u8; 2] { + self.network_type().b58_pubkey_address_prefix() + } - /// Returns the human-readable prefix for Base58Check-encoded transparent pay-to-script-hash - /// payment addresses for the network to which this Parameters value applies. - /// - /// [`TransparentAddress::Script`]: zcash_primitives::legacy::TransparentAddress::Script - fn b58_script_address_prefix(&self) -> [u8; 2]; + fn b58_script_address_prefix(&self) -> [u8; 2] { + self.network_type().b58_script_address_prefix() + } } /// Marker struct for the production network. @@ -208,6 +325,10 @@ memuse::impl_no_dynamic_usage!(MainNetwork); pub const MAIN_NETWORK: MainNetwork = MainNetwork; impl Parameters for MainNetwork { + fn network_type(&self) -> NetworkType { + NetworkType::Main + } + fn activation_height(&self, nu: NetworkUpgrade) -> Option { match nu { NetworkUpgrade::Overwinter => Some(BlockHeight(347_500)), @@ -222,34 +343,6 @@ impl Parameters for MainNetwork { NetworkUpgrade::ZFuture => None, } } - - fn coin_type(&self) -> u32 { - constants::mainnet::COIN_TYPE - } - - fn address_network(&self) -> Option { - Some(zcash_address::Network::Main) - } - - fn hrp_sapling_extended_spending_key(&self) -> &str { - constants::mainnet::HRP_SAPLING_EXTENDED_SPENDING_KEY - } - - fn hrp_sapling_extended_full_viewing_key(&self) -> &str { - constants::mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY - } - - fn hrp_sapling_payment_address(&self) -> &str { - constants::mainnet::HRP_SAPLING_PAYMENT_ADDRESS - } - - fn b58_pubkey_address_prefix(&self) -> [u8; 2] { - constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX - } - - fn b58_script_address_prefix(&self) -> [u8; 2] { - constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX - } } /// Marker struct for the test network. @@ -262,6 +355,10 @@ memuse::impl_no_dynamic_usage!(TestNetwork); pub const TEST_NETWORK: TestNetwork = TestNetwork; impl Parameters for TestNetwork { + fn network_type(&self) -> NetworkType { + NetworkType::Test + } + fn activation_height(&self, nu: NetworkUpgrade) -> Option { match nu { NetworkUpgrade::Overwinter => Some(BlockHeight(207_500)), @@ -276,99 +373,38 @@ impl Parameters for TestNetwork { NetworkUpgrade::ZFuture => None, } } - - fn coin_type(&self) -> u32 { - constants::testnet::COIN_TYPE - } - - fn address_network(&self) -> Option { - Some(zcash_address::Network::Test) - } - - fn hrp_sapling_extended_spending_key(&self) -> &str { - constants::testnet::HRP_SAPLING_EXTENDED_SPENDING_KEY - } - - fn hrp_sapling_extended_full_viewing_key(&self) -> &str { - constants::testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY - } - - fn hrp_sapling_payment_address(&self) -> &str { - constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS - } - - fn b58_pubkey_address_prefix(&self) -> [u8; 2] { - constants::testnet::B58_PUBKEY_ADDRESS_PREFIX - } - - fn b58_script_address_prefix(&self) -> [u8; 2] { - constants::testnet::B58_SCRIPT_ADDRESS_PREFIX - } } -/// Marker enum for the deployed Zcash consensus networks. -#[derive(PartialEq, Eq, Copy, Clone, Debug)] +/// The enumeration of known Zcash networks. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum Network { + /// Zcash Mainnet. MainNetwork, + /// Zcash Testnet. TestNetwork, + /// Private integration / regression testing, used in `zcashd`. + #[cfg(feature = "local-consensus")] + Regtest(LocalNetwork), } memuse::impl_no_dynamic_usage!(Network); impl Parameters for Network { + fn network_type(&self) -> NetworkType { + match self { + Network::MainNetwork => NetworkType::Main, + Network::TestNetwork => NetworkType::Test, + #[cfg(feature = "local-consensus")] + Network::Regtest(_) => NetworkType::Regtest, + } + } + fn activation_height(&self, nu: NetworkUpgrade) -> Option { match self { Network::MainNetwork => MAIN_NETWORK.activation_height(nu), Network::TestNetwork => TEST_NETWORK.activation_height(nu), - } - } - - fn coin_type(&self) -> u32 { - match self { - Network::MainNetwork => MAIN_NETWORK.coin_type(), - Network::TestNetwork => TEST_NETWORK.coin_type(), - } - } - - fn address_network(&self) -> Option { - match self { - Network::MainNetwork => Some(zcash_address::Network::Main), - Network::TestNetwork => Some(zcash_address::Network::Test), - } - } - - fn hrp_sapling_extended_spending_key(&self) -> &str { - match self { - Network::MainNetwork => MAIN_NETWORK.hrp_sapling_extended_spending_key(), - Network::TestNetwork => TEST_NETWORK.hrp_sapling_extended_spending_key(), - } - } - - fn hrp_sapling_extended_full_viewing_key(&self) -> &str { - match self { - Network::MainNetwork => MAIN_NETWORK.hrp_sapling_extended_full_viewing_key(), - Network::TestNetwork => TEST_NETWORK.hrp_sapling_extended_full_viewing_key(), - } - } - - fn hrp_sapling_payment_address(&self) -> &str { - match self { - Network::MainNetwork => MAIN_NETWORK.hrp_sapling_payment_address(), - Network::TestNetwork => TEST_NETWORK.hrp_sapling_payment_address(), - } - } - - fn b58_pubkey_address_prefix(&self) -> [u8; 2] { - match self { - Network::MainNetwork => MAIN_NETWORK.b58_pubkey_address_prefix(), - Network::TestNetwork => TEST_NETWORK.b58_pubkey_address_prefix(), - } - } - - fn b58_script_address_prefix(&self) -> [u8; 2] { - match self { - Network::MainNetwork => MAIN_NETWORK.b58_script_address_prefix(), - Network::TestNetwork => TEST_NETWORK.b58_script_address_prefix(), + #[cfg(feature = "local-consensus")] + Network::Regtest(network_params) => network_params.activation_height(nu), } } } diff --git a/components/zcash_protocol/src/constants/mainnet.rs b/components/zcash_protocol/src/constants/mainnet.rs index bd31a895e..467f22df5 100644 --- a/components/zcash_protocol/src/constants/mainnet.rs +++ b/components/zcash_protocol/src/constants/mainnet.rs @@ -29,6 +29,13 @@ pub const HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY: &str = "zxviews"; /// [Zcash Protocol Specification]: https://github.com/zcash/zips/blob/master/protocol/protocol.pdf pub const HRP_SAPLING_PAYMENT_ADDRESS: &str = "zs"; +/// The prefix for a Base58Check-encoded mainnet Sprout address +/// +/// Defined in the [Zcash Protocol Specification section 5.6.3][sproutpaymentaddrencoding]. +/// +/// [sproutpaymentaddrencoding]: https://zips.z.cash/protocol/protocol.pdf#sproutpaymentaddrencoding +pub const B58_SPROUT_ADDRESS_PREFIX: [u8; 2] = [0x16, 0x9a]; + /// The prefix for a Base58Check-encoded mainnet [`PublicKeyHash`]. /// /// [`PublicKeyHash`]: https://docs.rs/zcash_primitives/latest/zcash_primitives/legacy/enum.TransparentAddress.html diff --git a/components/zcash_protocol/src/constants/regtest.rs b/components/zcash_protocol/src/constants/regtest.rs index 7ae37dec5..cd793f6c7 100644 --- a/components/zcash_protocol/src/constants/regtest.rs +++ b/components/zcash_protocol/src/constants/regtest.rs @@ -33,6 +33,14 @@ pub const HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY: &str = "zxviewregtestsapling"; /// [the `zcashd` codebase]: pub const HRP_SAPLING_PAYMENT_ADDRESS: &str = "zregtestsapling"; +/// The prefix for a Base58Check-encoded regtest Sprout address +/// +/// Defined in the [Zcash Protocol Specification section 5.6.3][sproutpaymentaddrencoding]. +/// Same as the testnet prefix. +/// +/// [sproutpaymentaddrencoding]: https://zips.z.cash/protocol/protocol.pdf#sproutpaymentaddrencoding +pub const B58_SPROUT_ADDRESS_PREFIX: [u8; 2] = [0x16, 0xb6]; + /// The prefix for a Base58Check-encoded regtest transparent [`PublicKeyHash`]. /// Same as the testnet prefix. /// diff --git a/components/zcash_protocol/src/constants/testnet.rs b/components/zcash_protocol/src/constants/testnet.rs index dba86bb9c..7bf330969 100644 --- a/components/zcash_protocol/src/constants/testnet.rs +++ b/components/zcash_protocol/src/constants/testnet.rs @@ -29,6 +29,13 @@ pub const HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY: &str = "zxviewtestsapling"; /// [Zcash Protocol Specification]: https://github.com/zcash/zips/blob/master/protocol/protocol.pdf pub const HRP_SAPLING_PAYMENT_ADDRESS: &str = "ztestsapling"; +/// The prefix for a Base58Check-encoded testnet Sprout address +/// +/// Defined in the [Zcash Protocol Specification section 5.6.3][sproutpaymentaddrencoding]. +/// +/// [sproutpaymentaddrencoding]: https://zips.z.cash/protocol/protocol.pdf#sproutpaymentaddrencoding +pub const B58_SPROUT_ADDRESS_PREFIX: [u8; 2] = [0x16, 0xb6]; + /// The prefix for a Base58Check-encoded testnet transparent [`PublicKeyHash`]. /// /// [`PublicKeyHash`]: https://docs.rs/zcash_primitives/latest/zcash_primitives/legacy/enum.TransparentAddress.html diff --git a/components/zcash_protocol/src/local_consensus.rs b/components/zcash_protocol/src/local_consensus.rs index 8c4b647cc..cf4dffe60 100644 --- a/components/zcash_protocol/src/local_consensus.rs +++ b/components/zcash_protocol/src/local_consensus.rs @@ -1,7 +1,4 @@ -use crate::{ - consensus::{BlockHeight, NetworkUpgrade, Parameters}, - constants, -}; +use crate::consensus::{BlockHeight, NetworkType, NetworkUpgrade, Parameters}; /// a `LocalNetwork` setup should define the activation heights /// of network upgrades. `None` is considered as "not activated" @@ -36,7 +33,7 @@ use crate::{ /// }; /// ``` /// -#[derive(Clone, PartialEq, Eq, Copy, Debug)] +#[derive(Clone, PartialEq, Eq, Copy, Debug, Hash)] pub struct LocalNetwork { pub overwinter: Option, pub sapling: Option, @@ -44,18 +41,18 @@ pub struct LocalNetwork { pub heartwood: Option, pub canopy: Option, pub nu5: Option, + #[cfg(feature = "unstable-nu6")] pub nu6: Option, #[cfg(feature = "zfuture")] pub z_future: Option, } -/// Parameters default implementation for `LocalNetwork` -/// Important note: -/// The functions `coin_type()`, `address_network()`, -/// `hrp_sapling_extended_spending_key()`, `hrp_sapling_extended_full_viewing_key()`, -/// `hrp_sapling_payment_address()`, `b58_script_address_prefix()` return -/// `constants::regtest` values +/// Parameters implementation for `LocalNetwork` impl Parameters for LocalNetwork { + fn network_type(&self) -> NetworkType { + NetworkType::Regtest + } + fn activation_height(&self, nu: NetworkUpgrade) -> Option { match nu { NetworkUpgrade::Overwinter => self.overwinter, @@ -70,44 +67,12 @@ impl Parameters for LocalNetwork { NetworkUpgrade::ZFuture => self.z_future, } } - - fn coin_type(&self) -> u32 { - constants::regtest::COIN_TYPE - } - - fn address_network(&self) -> Option { - Some(zcash_address::Network::Regtest) - } - - fn hrp_sapling_extended_spending_key(&self) -> &str { - constants::regtest::HRP_SAPLING_EXTENDED_SPENDING_KEY - } - - fn hrp_sapling_extended_full_viewing_key(&self) -> &str { - constants::regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY - } - - fn hrp_sapling_payment_address(&self) -> &str { - constants::regtest::HRP_SAPLING_PAYMENT_ADDRESS - } - - fn b58_pubkey_address_prefix(&self) -> [u8; 2] { - constants::regtest::B58_PUBKEY_ADDRESS_PREFIX - } - - fn b58_script_address_prefix(&self) -> [u8; 2] { - constants::regtest::B58_SCRIPT_ADDRESS_PREFIX - } - - fn is_nu_active(&self, nu: NetworkUpgrade, height: BlockHeight) -> bool { - self.activation_height(nu).map_or(false, |h| h <= height) - } } #[cfg(test)] mod tests { use crate::{ - consensus::{BlockHeight, NetworkUpgrade, Parameters}, + consensus::{BlockHeight, NetworkConstants, NetworkUpgrade, Parameters}, constants, local_consensus::LocalNetwork, }; @@ -148,24 +113,6 @@ mod tests { assert!(regtest.is_nu_active(NetworkUpgrade::Nu6, expected_nu6)); #[cfg(feature = "zfuture")] assert!(!regtest.is_nu_active(NetworkUpgrade::ZFuture, expected_nu5)); - - assert_eq!(regtest.coin_type(), constants::regtest::COIN_TYPE); - assert_eq!( - regtest.hrp_sapling_extended_spending_key(), - constants::regtest::HRP_SAPLING_EXTENDED_SPENDING_KEY - ); - assert_eq!( - regtest.hrp_sapling_extended_full_viewing_key(), - constants::regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY - ); - assert_eq!( - regtest.hrp_sapling_payment_address(), - constants::regtest::HRP_SAPLING_PAYMENT_ADDRESS - ); - assert_eq!( - regtest.b58_pubkey_address_prefix(), - constants::regtest::B58_PUBKEY_ADDRESS_PREFIX - ); } #[test] @@ -251,25 +198,30 @@ mod tests { z_future: Some(expected_z_future), }; - assert_eq!(regtest.coin_type(), constants::regtest::COIN_TYPE); assert_eq!( - regtest.hrp_sapling_extended_spending_key(), + regtest.network_type().coin_type(), + constants::regtest::COIN_TYPE + ); + assert_eq!( + regtest.network_type().hrp_sapling_extended_spending_key(), constants::regtest::HRP_SAPLING_EXTENDED_SPENDING_KEY ); assert_eq!( - regtest.hrp_sapling_extended_full_viewing_key(), + regtest + .network_type() + .hrp_sapling_extended_full_viewing_key(), constants::regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY ); assert_eq!( - regtest.hrp_sapling_payment_address(), + regtest.network_type().hrp_sapling_payment_address(), constants::regtest::HRP_SAPLING_PAYMENT_ADDRESS ); assert_eq!( - regtest.b58_pubkey_address_prefix(), + regtest.network_type().b58_pubkey_address_prefix(), constants::regtest::B58_PUBKEY_ADDRESS_PREFIX ); assert_eq!( - regtest.b58_script_address_prefix(), + regtest.network_type().b58_script_address_prefix(), constants::regtest::B58_SCRIPT_ADDRESS_PREFIX ); } diff --git a/zcash_client_backend/src/zip321.rs b/zcash_client_backend/src/zip321.rs index a3e8e0093..82b68b9f1 100644 --- a/zcash_client_backend/src/zip321.rs +++ b/zcash_client_backend/src/zip321.rs @@ -16,10 +16,10 @@ use nom::{ sequence::preceded, }; use zcash_primitives::{ - consensus, memo::{self, MemoBytes}, transaction::components::amount::NonNegativeAmount, }; +use zcash_protocol::consensus; use crate::address::Address; @@ -819,10 +819,10 @@ mod tests { use zcash_keys::address::testing::arb_addr; use zcash_primitives::{ - consensus::{Parameters, TEST_NETWORK}, memo::Memo, transaction::components::amount::{testing::arb_nonnegative_amount, NonNegativeAmount}, }; + use zcash_protocol::consensus::{NetworkConstants, NetworkType, TEST_NETWORK}; #[cfg(feature = "local-consensus")] use zcash_primitives::{local_consensus::LocalNetwork, BlockHeight}; @@ -870,7 +870,7 @@ mod tests { let expected = TransactionRequest::new( vec![ Payment { - recipient_address: Address::Sapling(decode_payment_address(TEST_NETWORK.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap()), + recipient_address: Address::Sapling(decode_payment_address(NetworkType::Test.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap()), amount: NonNegativeAmount::const_from_u64(376876902796286), memo: None, label: None, @@ -891,7 +891,7 @@ mod tests { let expected = TransactionRequest::new( vec![ Payment { - recipient_address: Address::Sapling(decode_payment_address(TEST_NETWORK.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap()), + recipient_address: Address::Sapling(decode_payment_address(NetworkType::Test.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap()), amount: NonNegativeAmount::ZERO, memo: None, label: None, @@ -909,7 +909,7 @@ mod tests { let req = TransactionRequest::new( vec![ Payment { - recipient_address: Address::Sapling(decode_payment_address(TEST_NETWORK.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap()), + recipient_address: Address::Sapling(decode_payment_address(NetworkType::Test.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap()), amount: NonNegativeAmount::ZERO, memo: None, label: None, diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs index 54f311a58..75cada3f1 100644 --- a/zcash_client_sqlite/src/lib.rs +++ b/zcash_client_sqlite/src/lib.rs @@ -1330,6 +1330,8 @@ mod tests { #[cfg(feature = "unstable")] #[test] pub(crate) fn fsblockdb_api() { + use zcash_primitives::consensus::NetworkConstants; + let mut st = TestBuilder::new().with_fs_block_cache().build(); // The BlockMeta DB starts off empty. @@ -1338,7 +1340,11 @@ mod tests { // Generate some fake CompactBlocks. let seed = [0u8; 32]; let account = AccountId::ZERO; - let extsk = sapling::spending_key(&seed, st.wallet().params.coin_type(), account); + let extsk = sapling::spending_key( + &seed, + st.wallet().params.network_type().coin_type(), + account, + ); let dfvk = extsk.to_diversifiable_full_viewing_key(); let (h1, meta1, _) = st.generate_next_block( &dfvk, diff --git a/zcash_client_sqlite/src/wallet/init.rs b/zcash_client_sqlite/src/wallet/init.rs index 14bf46d30..949314959 100644 --- a/zcash_client_sqlite/src/wallet/init.rs +++ b/zcash_client_sqlite/src/wallet/init.rs @@ -176,7 +176,9 @@ mod tests { use ::sapling::zip32::ExtendedFullViewingKey; use zcash_primitives::{ - consensus::{self, BlockHeight, BranchId, Network, NetworkUpgrade, Parameters}, + consensus::{ + self, BlockHeight, BranchId, Network, NetworkConstants, NetworkUpgrade, Parameters, + }, transaction::{TransactionData, TxVersion}, zip32::AccountId, }; @@ -698,11 +700,13 @@ mod tests { )?; let address = encode_payment_address( - wdb.params.hrp_sapling_payment_address(), + wdb.params.network_type().hrp_sapling_payment_address(), &extfvk.default_address().1, ); let extfvk = encode_extended_full_viewing_key( - wdb.params.hrp_sapling_extended_full_viewing_key(), + wdb.params + .network_type() + .hrp_sapling_extended_full_viewing_key(), extfvk, ); wdb.conn.execute( @@ -723,7 +727,8 @@ mod tests { let seed = [0xab; 32]; let account = AccountId::ZERO; - let secret_key = sapling::spending_key(&seed, db_data.params.coin_type(), account); + let secret_key = + sapling::spending_key(&seed, db_data.params.network_type().coin_type(), account); let extfvk = secret_key.to_extended_full_viewing_key(); init_0_3_0(&mut db_data, &extfvk, account).unwrap(); @@ -835,11 +840,13 @@ mod tests { )?; let address = encode_payment_address( - wdb.params.hrp_sapling_payment_address(), + wdb.params.network_type().hrp_sapling_payment_address(), &extfvk.default_address().1, ); let extfvk = encode_extended_full_viewing_key( - wdb.params.hrp_sapling_extended_full_viewing_key(), + wdb.params + .network_type() + .hrp_sapling_extended_full_viewing_key(), extfvk, ); wdb.conn.execute( @@ -894,7 +901,8 @@ mod tests { let seed = [0xab; 32]; let account = AccountId::ZERO; - let secret_key = sapling::spending_key(&seed, db_data.params.coin_type(), account); + let secret_key = + sapling::spending_key(&seed, db_data.params.network_type().coin_type(), account); let extfvk = secret_key.to_extended_full_viewing_key(); init_autoshielding(&mut db_data, &extfvk, account).unwrap(); diff --git a/zcash_extensions/src/transparent/demo.rs b/zcash_extensions/src/transparent/demo.rs index 96f2d9f6f..6f2662993 100644 --- a/zcash_extensions/src/transparent/demo.rs +++ b/zcash_extensions/src/transparent/demo.rs @@ -484,8 +484,7 @@ mod tests { use sapling::{zip32::ExtendedSpendingKey, Node, Rseed}; use zcash_primitives::{ - consensus::{BlockHeight, BranchId, NetworkUpgrade, Parameters}, - constants, + consensus::{BlockHeight, BranchId, NetworkType, NetworkUpgrade, Parameters}, extensions::transparent::{self as tze, Extension, FromPayload, ToPayload}, legacy::TransparentAddress, transaction::{ @@ -520,34 +519,11 @@ mod tests { } } - fn address_network(&self) -> Option { - None - } - - fn coin_type(&self) -> u32 { - constants::testnet::COIN_TYPE - } - - fn hrp_sapling_extended_spending_key(&self) -> &str { - constants::testnet::HRP_SAPLING_EXTENDED_SPENDING_KEY - } - - fn hrp_sapling_extended_full_viewing_key(&self) -> &str { - constants::testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY - } - - fn hrp_sapling_payment_address(&self) -> &str { - constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS - } - - fn b58_pubkey_address_prefix(&self) -> [u8; 2] { - constants::testnet::B58_PUBKEY_ADDRESS_PREFIX - } - - fn b58_script_address_prefix(&self) -> [u8; 2] { - constants::testnet::B58_SCRIPT_ADDRESS_PREFIX + fn network_type(&self) -> NetworkType { + NetworkType::Test } } + fn demo_hashes(preimage_1: &[u8; 32], preimage_2: &[u8; 32]) -> ([u8; 32], [u8; 32]) { let hash_2 = { let mut hash = [0; 32]; diff --git a/zcash_keys/src/address.rs b/zcash_keys/src/address.rs index 2dfed4fa9..dd1fb9ac4 100644 --- a/zcash_keys/src/address.rs +++ b/zcash_keys/src/address.rs @@ -2,9 +2,10 @@ use zcash_address::{ unified::{self, Container, Encoding, Typecode}, - ConversionError, Network, ToAddress, TryFromRawAddress, ZcashAddress, + ConversionError, ToAddress, TryFromRawAddress, ZcashAddress, }; -use zcash_primitives::{consensus, legacy::TransparentAddress}; +use zcash_primitives::legacy::TransparentAddress; +use zcash_protocol::consensus::{self, NetworkType}; #[cfg(feature = "sapling")] use sapling::PaymentAddress; @@ -172,7 +173,7 @@ impl UnifiedAddress { &self.unknown } - fn to_address(&self, net: Network) -> ZcashAddress { + fn to_address(&self, net: NetworkType) -> ZcashAddress { let items = self .unknown .iter() @@ -209,8 +210,7 @@ impl UnifiedAddress { /// Returns the string encoding of this `UnifiedAddress` for the given network. pub fn encode(&self, params: &P) -> String { - self.to_address(params.address_network().expect("Unrecognized network")) - .to_string() + self.to_address(params.network_type()).to_string() } /// Returns the set of receiver typecodes. @@ -292,12 +292,11 @@ impl TryFromRawAddress for Address { impl Address { pub fn decode(params: &P, s: &str) -> Option { let addr = ZcashAddress::try_from_encoded(s).ok()?; - addr.convert_if_network(params.address_network().expect("Unrecognized network")) - .ok() + addr.convert_if_network(params.network_type()).ok() } pub fn encode(&self, params: &P) -> String { - let net = params.address_network().expect("Unrecognized network"); + let net = params.network_type(); match self { #[cfg(feature = "sapling")] diff --git a/zcash_keys/src/encoding.rs b/zcash_keys/src/encoding.rs index 7a280178c..cb1fef876 100644 --- a/zcash_keys/src/encoding.rs +++ b/zcash_keys/src/encoding.rs @@ -6,6 +6,7 @@ use crate::address::UnifiedAddress; use bs58::{self, decode::Error as Bs58Error}; use std::fmt; +use zcash_primitives::consensus::NetworkConstants; use zcash_address::unified::{self, Encoding}; use zcash_primitives::{consensus, legacy::TransparentAddress}; @@ -130,16 +131,16 @@ impl AddressCodec

for TransparentAddress { fn encode(&self, params: &P) -> String { encode_transparent_address( - ¶ms.b58_pubkey_address_prefix(), - ¶ms.b58_script_address_prefix(), + ¶ms.network_type().b58_pubkey_address_prefix(), + ¶ms.network_type().b58_script_address_prefix(), self, ) } fn decode(params: &P, address: &str) -> Result { decode_transparent_address( - ¶ms.b58_pubkey_address_prefix(), - ¶ms.b58_script_address_prefix(), + ¶ms.network_type().b58_pubkey_address_prefix(), + ¶ms.network_type().b58_script_address_prefix(), address, ) .map_err(TransparentCodecError::Base58) @@ -154,11 +155,11 @@ impl AddressCodec

for sapling::PaymentAddress { type Error = Bech32DecodeError; fn encode(&self, params: &P) -> String { - encode_payment_address(params.hrp_sapling_payment_address(), self) + encode_payment_address(params.network_type().hrp_sapling_payment_address(), self) } fn decode(params: &P, address: &str) -> Result { - decode_payment_address(params.hrp_sapling_payment_address(), address) + decode_payment_address(params.network_type().hrp_sapling_payment_address(), address) } } @@ -173,7 +174,7 @@ impl AddressCodec

for UnifiedAddress { unified::Address::decode(address) .map_err(|e| format!("{}", e)) .and_then(|(network, addr)| { - if params.address_network() == Some(network) { + if params.network_type() == network { UnifiedAddress::try_from(addr).map_err(|e| e.to_owned()) } else { Err(format!( @@ -298,7 +299,7 @@ pub fn encode_payment_address_p( params: &P, addr: &sapling::PaymentAddress, ) -> String { - encode_payment_address(params.hrp_sapling_payment_address(), addr) + encode_payment_address(params.network_type().hrp_sapling_payment_address(), addr) } /// Decodes a [`PaymentAddress`] from a Bech32-encoded string. @@ -312,7 +313,7 @@ pub fn encode_payment_address_p( /// encoding::decode_payment_address, /// }; /// use zcash_primitives::{ -/// consensus::{TEST_NETWORK, Parameters}, +/// consensus::{TEST_NETWORK, NetworkConstants, Parameters}, /// }; /// /// let pa = PaymentAddress::from_bytes(&[ @@ -325,7 +326,7 @@ pub fn encode_payment_address_p( /// /// assert_eq!( /// decode_payment_address( -/// TEST_NETWORK.hrp_sapling_payment_address(), +/// TEST_NETWORK.network_type().hrp_sapling_payment_address(), /// "ztestsapling1qqqqqqqqqqqqqqqqqqcguyvaw2vjk4sdyeg0lc970u659lvhqq7t0np6hlup5lusxle75ss7jnk", /// ), /// Ok(pa), @@ -357,14 +358,14 @@ pub fn decode_payment_address( /// encoding::encode_transparent_address, /// }; /// use zcash_primitives::{ -/// consensus::{TEST_NETWORK, Parameters}, +/// consensus::{TEST_NETWORK, NetworkConstants, Parameters}, /// legacy::TransparentAddress, /// }; /// /// assert_eq!( /// encode_transparent_address( -/// &TEST_NETWORK.b58_pubkey_address_prefix(), -/// &TEST_NETWORK.b58_script_address_prefix(), +/// &TEST_NETWORK.network_type().b58_pubkey_address_prefix(), +/// &TEST_NETWORK.network_type().b58_script_address_prefix(), /// &TransparentAddress::PublicKeyHash([0; 20]), /// ), /// "tm9iMLAuYMzJ6jtFLcA7rzUmfreGuKvr7Ma", @@ -372,8 +373,8 @@ pub fn decode_payment_address( /// /// assert_eq!( /// encode_transparent_address( -/// &TEST_NETWORK.b58_pubkey_address_prefix(), -/// &TEST_NETWORK.b58_script_address_prefix(), +/// &TEST_NETWORK.network_type().b58_pubkey_address_prefix(), +/// &TEST_NETWORK.network_type().b58_script_address_prefix(), /// &TransparentAddress::ScriptHash([0; 20]), /// ), /// "t26YoyZ1iPgiMEWL4zGUm74eVWfhyDMXzY2", @@ -410,8 +411,8 @@ pub fn encode_transparent_address_p( addr: &TransparentAddress, ) -> String { encode_transparent_address( - ¶ms.b58_pubkey_address_prefix(), - ¶ms.b58_script_address_prefix(), + ¶ms.network_type().b58_pubkey_address_prefix(), + ¶ms.network_type().b58_script_address_prefix(), addr, ) } @@ -422,17 +423,17 @@ pub fn encode_transparent_address_p( /// /// ``` /// use zcash_primitives::{ -/// consensus::{TEST_NETWORK, Parameters}, +/// consensus::{TEST_NETWORK, NetworkConstants, Parameters}, +/// legacy::TransparentAddress, /// }; /// use zcash_keys::{ /// encoding::decode_transparent_address, /// }; -/// use zcash_primitives::legacy::TransparentAddress; /// /// assert_eq!( /// decode_transparent_address( -/// &TEST_NETWORK.b58_pubkey_address_prefix(), -/// &TEST_NETWORK.b58_script_address_prefix(), +/// &TEST_NETWORK.network_type().b58_pubkey_address_prefix(), +/// &TEST_NETWORK.network_type().b58_script_address_prefix(), /// "tm9iMLAuYMzJ6jtFLcA7rzUmfreGuKvr7Ma", /// ), /// Ok(Some(TransparentAddress::PublicKeyHash([0; 20]))), @@ -440,8 +441,8 @@ pub fn encode_transparent_address_p( /// /// assert_eq!( /// decode_transparent_address( -/// &TEST_NETWORK.b58_pubkey_address_prefix(), -/// &TEST_NETWORK.b58_script_address_prefix(), +/// &TEST_NETWORK.network_type().b58_pubkey_address_prefix(), +/// &TEST_NETWORK.network_type().b58_script_address_prefix(), /// "t26YoyZ1iPgiMEWL4zGUm74eVWfhyDMXzY2", /// ), /// Ok(Some(TransparentAddress::ScriptHash([0; 20]))), diff --git a/zcash_keys/src/keys.rs b/zcash_keys/src/keys.rs index 3515f4cbf..6995f8c8b 100644 --- a/zcash_keys/src/keys.rs +++ b/zcash_keys/src/keys.rs @@ -1,9 +1,7 @@ //! Helper functions for managing light client key material. use zcash_address::unified::{self, Container, Encoding, Typecode}; -use zcash_primitives::{ - consensus, - zip32::{AccountId, DiversifierIndex}, -}; +use zcash_protocol::consensus::{self, NetworkConstants}; +use zip32::{AccountId, DiversifierIndex}; use crate::address::UnifiedAddress; @@ -190,11 +188,11 @@ impl UnifiedSpendingKey { transparent: legacy::AccountPrivKey::from_seed(_params, seed, _account) .map_err(DerivationError::Transparent)?, #[cfg(feature = "sapling")] - sapling: sapling::spending_key(seed, _params.coin_type(), _account), + sapling: sapling::spending_key(seed, _params.network_type().coin_type(), _account), #[cfg(feature = "orchard")] orchard: orchard::keys::SpendingKey::from_zip32_seed( seed, - _params.coin_type(), + _params.network_type().coin_type(), _account, ) .map_err(DerivationError::Orchard)?, @@ -554,7 +552,7 @@ impl UnifiedFullViewingKey { /// [ZIP 316]: https://zips.z.cash/zip-0316 pub fn decode(params: &P, encoding: &str) -> Result { let (net, ufvk) = unified::Ufvk::decode(encoding).map_err(|e| e.to_string())?; - let expected_net = params.address_network().expect("Unrecognized network"); + let expected_net = params.network_type(); if net != expected_net { return Err(format!( "UFVK is for network {:?} but we expected {:?}", @@ -663,7 +661,7 @@ impl UnifiedFullViewingKey { let ufvk = unified::Ufvk::try_from_items(items.collect()) .expect("UnifiedFullViewingKey should only be constructed safely"); - ufvk.encode(¶ms.address_network().expect("Unrecognized network")) + ufvk.encode(¶ms.network_type()) } /// Returns the transparent component of the unified key at the diff --git a/zcash_primitives/src/legacy/keys.rs b/zcash_primitives/src/legacy/keys.rs index ff4f7e946..19a12e59f 100644 --- a/zcash_primitives/src/legacy/keys.rs +++ b/zcash_primitives/src/legacy/keys.rs @@ -7,9 +7,10 @@ use hdwallet::{ use secp256k1::PublicKey; use sha2::{Digest, Sha256}; use subtle::{Choice, ConstantTimeEq}; -use zcash_spec::PrfExpand; -use crate::{consensus, zip32::AccountId}; +use zcash_protocol::consensus::{self, NetworkConstants}; +use zcash_spec::PrfExpand; +use zip32::AccountId; use super::TransparentAddress; @@ -119,7 +120,9 @@ impl AccountPrivKey { ) -> Result { ExtendedPrivKey::with_seed(seed)? .derive_private_key(KeyIndex::hardened_from_normalize_index(44)?)? - .derive_private_key(KeyIndex::hardened_from_normalize_index(params.coin_type())?)? + .derive_private_key(KeyIndex::hardened_from_normalize_index( + params.network_type().coin_type(), + )?)? .derive_private_key(KeyIndex::hardened_from_normalize_index(account.into())?) .map(AccountPrivKey) }