Apply suggestions from code review

Co-authored-by: str4d <thestr4d@gmail.com>
Co-authored-by: Daira-Emma Hopwood <daira@jacaranda.org>
This commit is contained in:
Kris Nuttycombe 2024-03-05 10:17:32 -07:00
parent 04fdac7931
commit b8aa5132c2
19 changed files with 127 additions and 143 deletions

View File

@ -7,12 +7,6 @@ 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`

View File

@ -16,9 +16,13 @@ The entries below are relative to the `zcash_primitives` crate as of the tag
- `constants`
- `zcash_protocol::value` replaces `zcash_primitives::transaction::components::amount`
- `zcash_protocol::consensus`:
- `NetworkConstants` has been extracted from the `Parameters` trait.
- `NetworkConstants` has been extracted from the `Parameters` trait. Relative to the
state prior to the extraction, the bech32 prefixes now return `&'static str` instead
of `&str`.
- `NetworkType`
- `Parameters::b58_sprout_address_prefix`
- `zcash_protocol::consensus`:
- `impl Hash for LocalNetwork`
- `zcash_protocol::constants::{mainnet, testnet}::B58_SPROUT_ADDRESS_PREFIX`
- Added in `zcash_protocol::value`:
- `Zatoshis`
@ -40,6 +44,8 @@ The entries below are relative to the `zcash_primitives` crate as of the tag
- `TryFrom<orchard::ValueSum> for Amount`
- `From<NonNegativeAmount> for sapling::value::NoteValue>`
- `TryFrom<sapling::value::NoteValue> for NonNegativeAmount`
- `impl AddAssign for NonNegativeAmount`
- `impl SubAssign 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`

View File

@ -37,13 +37,22 @@ proptest.workspace = true
[features]
## Exposes APIs that are useful for testing, such as `proptest` strategies.
test-dependencies = ["dep:proptest", "incrementalmerkletree/test-dependencies"]
test-dependencies = [
"dep:incrementalmerkletree",
"dep:proptest",
"incrementalmerkletree?/test-dependencies",
]
## Exposes support for working with a local consensus (e.g. regtest).
local-consensus = []
#! ### Experimental features
#!
#! ⚠️ Enabling these features will likely make your code incompatible with current Zcash
#! consensus rules!
## Exposes the in-development NU6 features.
unstable-nu6 = []
## Exposes early in-development features that are not yet planned for any network upgrade.
zfuture = []
## Exposes support for working with a local consensus (e.g. regtest
local-consensus = []

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2021 Electric Coin Company
Copyright (c) 2021-2024 Electric Coin Company
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -8,9 +8,6 @@ use std::ops::{Add, Bound, RangeBounds, Sub};
use crate::constants::{mainnet, regtest, testnet};
#[cfg(feature = "local-consensus")]
use crate::local_consensus::LocalNetwork;
/// A wrapper type representing blockchain heights.
///
/// Safe conversion from various integer types, as well as addition and subtraction, are
@ -146,7 +143,7 @@ pub trait NetworkConstants: Clone {
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.
/// for the network to which this NetworkConstants value applies.
///
/// Defined in [ZIP 32].
///
@ -164,7 +161,7 @@ pub trait NetworkConstants: Clone {
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.
/// for the network to which this NetworkConstants value applies.
///
/// Defined in section 5.6.4 of the [Zcash Protocol Specification].
///
@ -382,9 +379,6 @@ pub enum Network {
MainNetwork,
/// Zcash Testnet.
TestNetwork,
/// Private integration / regression testing, used in `zcashd`.
#[cfg(feature = "local-consensus")]
Regtest(LocalNetwork),
}
memuse::impl_no_dynamic_usage!(Network);
@ -394,8 +388,6 @@ impl Parameters for Network {
match self {
Network::MainNetwork => NetworkType::Main,
Network::TestNetwork => NetworkType::Test,
#[cfg(feature = "local-consensus")]
Network::Regtest(_) => NetworkType::Regtest,
}
}
@ -403,8 +395,6 @@ impl Parameters for Network {
match self {
Network::MainNetwork => MAIN_NETWORK.activation_height(nu),
Network::TestNetwork => TEST_NETWORK.activation_height(nu),
#[cfg(feature = "local-consensus")]
Network::Regtest(network_params) => network_params.activation_height(nu),
}
}
}

View File

@ -17,7 +17,7 @@ pub const HRP_SAPLING_EXTENDED_SPENDING_KEY: &str = "secret-extended-key-main";
///
/// Defined in [ZIP 32].
///
/// [`ExtendedFullViewingKey`]: https://docs.rs/sapling-crypto/latest/sapling_crypto/zip32/struct.ExtendedFullViewingKey.html#
/// [`ExtendedFullViewingKey`]: https://docs.rs/sapling-crypto/latest/sapling_crypto/zip32/struct.ExtendedFullViewingKey.html
/// [ZIP 32]: https://github.com/zcash/zips/blob/master/zip-0032.rst
pub const HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY: &str = "zxviews";

View File

@ -21,7 +21,7 @@ pub const HRP_SAPLING_EXTENDED_SPENDING_KEY: &str = "secret-extended-key-regtest
///
/// It is defined in [the `zcashd` codebase].
///
/// [`ExtendedFullViewingKey`]: https://docs.rs/sapling-crypto/latest/sapling_crypto/zip32/struct.ExtendedFullViewingKey.html#
/// [`ExtendedFullViewingKey`]: https://docs.rs/sapling-crypto/latest/sapling_crypto/zip32/struct.ExtendedFullViewingKey.html
/// [the `zcashd` codebase]: <https://github.com/zcash/zcash/blob/128d863fb8be39ee294fda397c1ce3ba3b889cb2/src/chainparams.cpp#L494>
pub const HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY: &str = "zxviewregtestsapling";
@ -33,7 +33,7 @@ pub const HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY: &str = "zxviewregtestsapling";
/// [the `zcashd` codebase]: <https://github.com/zcash/zcash/blob/128d863fb8be39ee294fda397c1ce3ba3b889cb2/src/chainparams.cpp#L493>
pub const HRP_SAPLING_PAYMENT_ADDRESS: &str = "zregtestsapling";
/// The prefix for a Base58Check-encoded regtest Sprout address
/// 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.

View File

@ -17,7 +17,7 @@ pub const HRP_SAPLING_EXTENDED_SPENDING_KEY: &str = "secret-extended-key-test";
///
/// Defined in [ZIP 32].
///
/// [`ExtendedFullViewingKey`]: https://docs.rs/sapling-crypto/latest/sapling_crypto/zip32/struct.ExtendedFullViewingKey.html#
/// [`ExtendedFullViewingKey`]: https://docs.rs/sapling-crypto/latest/sapling_crypto/zip32/struct.ExtendedFullViewingKey.html
/// [ZIP 32]: https://github.com/zcash/zips/blob/master/zip-0032.rst
pub const HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY: &str = "zxviewtestsapling";
@ -29,7 +29,7 @@ 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
/// The prefix for a Base58Check-encoded testnet Sprout addresses.
///
/// Defined in the [Zcash Protocol Specification section 5.6.3][sproutpaymentaddrencoding].
///

View File

@ -1,7 +1,7 @@
use std::convert::{Infallible, TryFrom};
use std::error;
use std::iter::Sum;
use std::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign};
use std::ops::{Add, Mul, Neg, Sub};
use memuse::DynamicUsage;
@ -12,12 +12,9 @@ pub const MAX_BALANCE: i64 = MAX_MONEY as i64;
/// A type-safe representation of a Zcash value delta, in zatoshis.
///
/// An ZatBalance can only be constructed from an integer that is within the valid monetary
/// range of `{-MAX_MONEY..MAX_MONEY}` (where `MAX_MONEY` = 21,000,000 × 10⁸ zatoshis).
/// However, this range is not preserved as an invariant internally; it is possible to
/// add two valid ZatBalances together to obtain an invalid ZatBalance. It is the user's
/// responsibility to handle the result of serializing potentially-invalid ZatBalances. In
/// particular, a [`Transaction`] containing serialized invalid ZatBalances will be rejected
/// by the network consensus rules.
/// range of `{-MAX_MONEY..MAX_MONEY}` (where `MAX_MONEY` = 21,000,000 × 10⁸ zatoshis),
/// and this is preserved as an invariant internally. (A [`Transaction`] containing serialized
/// invalid ZatBalances would also be rejected by the network consensus rules.)
///
/// [`Transaction`]: https://docs.rs/zcash_primitives/latest/zcash_primitives/transaction/struct.Transaction.html
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
@ -174,12 +171,6 @@ impl Add<ZatBalance> for Option<ZatBalance> {
}
}
impl AddAssign<ZatBalance> for ZatBalance {
fn add_assign(&mut self, rhs: ZatBalance) {
*self = (*self + rhs).expect("Addition must produce a valid amount value.")
}
}
impl Sub<ZatBalance> for ZatBalance {
type Output = Option<ZatBalance>;
@ -196,12 +187,6 @@ impl Sub<ZatBalance> for Option<ZatBalance> {
}
}
impl SubAssign<ZatBalance> for ZatBalance {
fn sub_assign(&mut self, rhs: ZatBalance) {
*self = (*self - rhs).expect("Subtraction must produce a valid amount value.")
}
}
impl Sum<ZatBalance> for Option<ZatBalance> {
fn sum<I: Iterator<Item = ZatBalance>>(iter: I) -> Self {
iter.fold(Some(ZatBalance::zero()), |acc, a| acc? + a)
@ -272,7 +257,7 @@ impl Zatoshis {
///
/// Returns an error if the amount is outside the range `{0..MAX_MONEY}`.
pub fn from_nonnegative_i64(amount: i64) -> Result<Self, ()> {
u64::try_from(amount).map(Zatoshis).map_err(|_| ())
Self::from_u64(u64::try_from(amount).map_err(|_| ())?)
}
/// Reads an Zatoshis from an unsigned 64-bit little-endian integer.
@ -516,23 +501,9 @@ mod tests {
assert_eq!(v + ZatBalance(1), None)
}
#[test]
#[should_panic]
fn add_assign_panics_on_overflow() {
let mut a = ZatBalance(MAX_BALANCE);
a += ZatBalance(1);
}
#[test]
fn sub_underflow() {
let v = ZatBalance(-MAX_BALANCE);
assert_eq!(v - ZatBalance(1), None)
}
#[test]
#[should_panic]
fn sub_assign_panics_on_underflow() {
let mut a = ZatBalance(-MAX_BALANCE);
a -= ZatBalance(1);
}
}

View File

@ -264,15 +264,10 @@ impl<C: Borrow<rusqlite::Connection>, P: consensus::Parameters> WalletRead for W
// Keys are not comparable with `Eq`, but addresses are, so we derive what should
// be equivalent addresses for each key and use those to check for key equality.
UnifiedAddressRequest::all().map_or(Ok(false), |ua_request| {
match (
usk.to_unified_full_viewing_key()
.default_address(ua_request),
ufvk.default_address(ua_request),
) {
(Ok(a), Ok(b)) => Ok(a == b),
(Err(e), _) => Err(e.into()),
(_, Err(e)) => Err(e.into()),
}
Ok(usk
.to_unified_full_viewing_key()
.default_address(ua_request)?
== ufvk.default_address(ua_request)?)
})
})
})

View File

@ -2,21 +2,18 @@
use std::fmt;
use rusqlite::{self};
use schemer::{Migrator, MigratorError};
use schemer_rusqlite::RusqliteAdapter;
use secrecy::SecretVec;
use shardtree::error::ShardTreeError;
use uuid::Uuid;
use zcash_primitives::{
consensus::{self},
transaction::components::amount::BalanceError,
};
use zcash_client_backend::keys::AddressGenerationError;
use zcash_primitives::{consensus, transaction::components::amount::BalanceError};
use crate::WalletDb;
use super::commitment_tree::{self};
use super::commitment_tree;
mod migrations;
@ -28,6 +25,9 @@ pub enum WalletMigrationError {
/// Decoding of an existing value from its serialized form has failed.
CorruptedData(String),
/// An error occurred in migrating a Zcash address or key.
AddressGeneration(AddressGenerationError),
/// Wrapper for rusqlite errors.
DbError(rusqlite::Error),
@ -56,6 +56,12 @@ impl From<ShardTreeError<commitment_tree::Error>> for WalletMigrationError {
}
}
impl From<AddressGenerationError> for WalletMigrationError {
fn from(e: AddressGenerationError) -> Self {
WalletMigrationError::AddressGeneration(e)
}
}
impl fmt::Display for WalletMigrationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self {
@ -71,6 +77,9 @@ impl fmt::Display for WalletMigrationError {
WalletMigrationError::DbError(e) => write!(f, "{}", e),
WalletMigrationError::BalanceError(e) => write!(f, "Balance error: {:?}", e),
WalletMigrationError::CommitmentTree(e) => write!(f, "Commitment tree error: {:?}", e),
WalletMigrationError::AddressGeneration(e) => {
write!(f, "Address generation error: {:?}", e)
}
}
}
}
@ -79,6 +88,9 @@ impl std::error::Error for WalletMigrationError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match &self {
WalletMigrationError::DbError(e) => Some(e),
WalletMigrationError::BalanceError(e) => Some(e),
WalletMigrationError::CommitmentTree(e) => Some(e),
WalletMigrationError::AddressGeneration(e) => Some(e),
_ => None,
}
}

View File

@ -88,13 +88,9 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
"Address in accounts table was not a Unified Address.".to_string(),
));
};
let (expected_address, idx) = ufvk
.default_address(UnifiedAddressRequest::unsafe_new(
false,
true,
UA_TRANSPARENT,
))
.expect("A valid default address exists for the UFVK");
let (expected_address, idx) = ufvk.default_address(
UnifiedAddressRequest::unsafe_new(false, true, UA_TRANSPARENT),
)?;
if decoded_address != expected_address {
return Err(WalletMigrationError::CorruptedData(format!(
"Decoded UA {} does not match the UFVK's default address {} at {:?}.",
@ -164,13 +160,11 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
],
)?;
let (address, d_idx) = ufvk
.default_address(UnifiedAddressRequest::unsafe_new(
false,
true,
UA_TRANSPARENT,
))
.expect("A valid default address exists for the UFVK");
let (address, d_idx) = ufvk.default_address(UnifiedAddressRequest::unsafe_new(
false,
true,
UA_TRANSPARENT,
))?;
insert_address(transaction, &self.params, account, d_idx, &address)?;
}

View File

@ -172,17 +172,25 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
);
let ufvk_str: String = row.get(5)?;
let ufvk = UnifiedFullViewingKey::decode(&self.params, &ufvk_str)
.expect("Stored UFVKs must be valid");
let dfvk = ufvk
.sapling()
.expect("UFVK must have a Sapling component to have received Sapling notes");
let ufvk = UnifiedFullViewingKey::decode(&self.params, &ufvk_str).map_err(|e| {
WalletMigrationError::CorruptedData(format!("Stored UFVK was invalid: {:?}", e))
})?;
let dfvk = ufvk.sapling().ok_or_else(|| {
WalletMigrationError::CorruptedData(
"UFVK must have a Sapling component to have received Sapling notes.".to_owned(),
)
})?;
// We previously set the default to external scope, so we now verify whether the output
// is decryptable using the intenally-scoped IVK and, if so, mark it as such.
if let Some(tx_data) = tx_data_opt {
let tx = Transaction::read(&tx_data[..], BranchId::Canopy)
.expect("Transaction must be valid");
let tx = Transaction::read(&tx_data[..], BranchId::Canopy).map_err(|e| {
WalletMigrationError::CorruptedData(format!(
"Unable to parse raw transaction: {:?}",
e
))
})?;
let output = tx
.sapling_bundle()
.and_then(|b| b.shielded_outputs().get(output_index))

View File

@ -68,8 +68,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
let mut stmt_fetch_accounts =
transaction.prepare("SELECT account, address FROM accounts")?;
let ua_request = UnifiedAddressRequest::new(false, true, UA_TRANSPARENT)
.expect("A shielded receiver type is requested.");
let ua_request = UnifiedAddressRequest::unsafe_new(false, true, UA_TRANSPARENT);
let mut rows = stmt_fetch_accounts.query([])?;
while let Some(row) = rows.next()? {
// We only need to check for the presence of the seed if we have keys that
@ -94,9 +93,8 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
})?;
match decoded {
Address::Sapling(decoded_address) => {
let dfvk = ufvk.sapling().expect(
"Derivation should have produced a UFVK containing a Sapling component.",
);
let dfvk = ufvk.sapling().ok_or_else(||
WalletMigrationError::CorruptedData("Derivation should have produced a UFVK containing a Sapling component.".to_owned()))?;
let (idx, expected_address) = dfvk.default_address();
if decoded_address != expected_address {
return Err(WalletMigrationError::CorruptedData(
@ -111,9 +109,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
"Address field value decoded to a transparent address; should have been Sapling or unified.".to_string()));
}
Address::Unified(decoded_address) => {
let (expected_address, idx) = ufvk
.default_address(ua_request)
.expect("A valid default address exists for the UFVK");
let (expected_address, idx) = ufvk.default_address(ua_request)?;
if decoded_address != expected_address {
return Err(WalletMigrationError::CorruptedData(
format!("Decoded unified address {} does not match the ufvk's default address {} at {:?}.",
@ -125,11 +121,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
}
let ufvk_str: String = ufvk.encode(&self.params);
let address_str: String = ufvk
.default_address(ua_request)
.expect("A valid default address exists for the UFVK")
.0
.encode(&self.params);
let address_str: String = ufvk.default_address(ua_request)?.0.encode(&self.params);
// This migration, and the wallet behaviour before it, stored the default
// transparent address in the `accounts` table. This does not necessarily

View File

@ -13,10 +13,15 @@ and this library adheres to Rust's notion of
### Changed
- `zcash_keys::keys::AddressGenerationError` has a new variant
`DiversifierSpaceExhausted`
`DiversifierSpaceExhausted`.
- `zcash_keys::keys::UnifiedFullViewingKey::{find_address, default_address}`
now return `Result<(UnifiedAddress, DiversifierIndex), AddressGenerationError>`
instead of `Option<(UnifiedAddress, DiversifierIndex)>`
(instead of `Option<(UnifiedAddress, DiversifierIndex)>` for `find_address`).
### Fixed
- `UnifiedFullViewingKey::find_address` can now find an address for a diversifier
index outside the valid transparent range if you aren't requesting a
transparent receiver.
## [0.1.1] - 2024-03-04

View File

@ -131,16 +131,16 @@ impl<P: consensus::Parameters> AddressCodec<P> for TransparentAddress {
fn encode(&self, params: &P) -> String {
encode_transparent_address(
&params.network_type().b58_pubkey_address_prefix(),
&params.network_type().b58_script_address_prefix(),
&params.b58_pubkey_address_prefix(),
&params.b58_script_address_prefix(),
self,
)
}
fn decode(params: &P, address: &str) -> Result<TransparentAddress, TransparentCodecError> {
decode_transparent_address(
&params.network_type().b58_pubkey_address_prefix(),
&params.network_type().b58_script_address_prefix(),
&params.b58_pubkey_address_prefix(),
&params.b58_script_address_prefix(),
address,
)
.map_err(TransparentCodecError::Base58)
@ -155,11 +155,11 @@ impl<P: consensus::Parameters> AddressCodec<P> for sapling::PaymentAddress {
type Error = Bech32DecodeError;
fn encode(&self, params: &P) -> String {
encode_payment_address(params.network_type().hrp_sapling_payment_address(), self)
encode_payment_address(params.hrp_sapling_payment_address(), self)
}
fn decode(params: &P, address: &str) -> Result<Self, Bech32DecodeError> {
decode_payment_address(params.network_type().hrp_sapling_payment_address(), address)
decode_payment_address(params.hrp_sapling_payment_address(), address)
}
}
@ -299,7 +299,7 @@ pub fn encode_payment_address_p<P: consensus::Parameters>(
params: &P,
addr: &sapling::PaymentAddress,
) -> String {
encode_payment_address(params.network_type().hrp_sapling_payment_address(), addr)
encode_payment_address(params.hrp_sapling_payment_address(), addr)
}
/// Decodes a [`PaymentAddress`] from a Bech32-encoded string.
@ -326,7 +326,7 @@ pub fn encode_payment_address_p<P: consensus::Parameters>(
///
/// assert_eq!(
/// decode_payment_address(
/// TEST_NETWORK.network_type().hrp_sapling_payment_address(),
/// TEST_NETWORK.hrp_sapling_payment_address(),
/// "ztestsapling1qqqqqqqqqqqqqqqqqqcguyvaw2vjk4sdyeg0lc970u659lvhqq7t0np6hlup5lusxle75ss7jnk",
/// ),
/// Ok(pa),
@ -364,8 +364,8 @@ pub fn decode_payment_address(
///
/// assert_eq!(
/// encode_transparent_address(
/// &TEST_NETWORK.network_type().b58_pubkey_address_prefix(),
/// &TEST_NETWORK.network_type().b58_script_address_prefix(),
/// &TEST_NETWORK.b58_pubkey_address_prefix(),
/// &TEST_NETWORK.b58_script_address_prefix(),
/// &TransparentAddress::PublicKeyHash([0; 20]),
/// ),
/// "tm9iMLAuYMzJ6jtFLcA7rzUmfreGuKvr7Ma",
@ -373,8 +373,8 @@ pub fn decode_payment_address(
///
/// assert_eq!(
/// encode_transparent_address(
/// &TEST_NETWORK.network_type().b58_pubkey_address_prefix(),
/// &TEST_NETWORK.network_type().b58_script_address_prefix(),
/// &TEST_NETWORK.b58_pubkey_address_prefix(),
/// &TEST_NETWORK.b58_script_address_prefix(),
/// &TransparentAddress::ScriptHash([0; 20]),
/// ),
/// "t26YoyZ1iPgiMEWL4zGUm74eVWfhyDMXzY2",
@ -411,8 +411,8 @@ pub fn encode_transparent_address_p<P: consensus::Parameters>(
addr: &TransparentAddress,
) -> String {
encode_transparent_address(
&params.network_type().b58_pubkey_address_prefix(),
&params.network_type().b58_script_address_prefix(),
&params.b58_pubkey_address_prefix(),
&params.b58_script_address_prefix(),
addr,
)
}
@ -432,8 +432,8 @@ pub fn encode_transparent_address_p<P: consensus::Parameters>(
///
/// assert_eq!(
/// decode_transparent_address(
/// &TEST_NETWORK.network_type().b58_pubkey_address_prefix(),
/// &TEST_NETWORK.network_type().b58_script_address_prefix(),
/// &TEST_NETWORK.b58_pubkey_address_prefix(),
/// &TEST_NETWORK.b58_script_address_prefix(),
/// "tm9iMLAuYMzJ6jtFLcA7rzUmfreGuKvr7Ma",
/// ),
/// Ok(Some(TransparentAddress::PublicKeyHash([0; 20]))),
@ -441,8 +441,8 @@ pub fn encode_transparent_address_p<P: consensus::Parameters>(
///
/// assert_eq!(
/// decode_transparent_address(
/// &TEST_NETWORK.network_type().b58_pubkey_address_prefix(),
/// &TEST_NETWORK.network_type().b58_script_address_prefix(),
/// &TEST_NETWORK.b58_pubkey_address_prefix(),
/// &TEST_NETWORK.b58_script_address_prefix(),
/// "t26YoyZ1iPgiMEWL4zGUm74eVWfhyDMXzY2",
/// ),
/// Ok(Some(TransparentAddress::ScriptHash([0; 20]))),

View File

@ -448,6 +448,7 @@ pub enum AddressGenerationError {
impl fmt::Display for AddressGenerationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self {
#[cfg(feature = "transparent-inputs")]
AddressGenerationError::InvalidTransparentChildIndex(i) => {
write!(
f,
@ -826,7 +827,8 @@ impl UnifiedFullViewingKey {
/// produce a valid diversifier, and return the Unified Address constructed using that
/// diversifier along with the index at which the valid diversifier was found.
///
/// Returns `None` if no valid diversifier exists
/// Returns an `Err(AddressGenerationError)` if no valid diversifier exists or if the features
/// required to satisfy the unified address request are not properly enabled.
#[allow(unused_mut)]
pub fn find_address(
&self,
@ -864,8 +866,11 @@ impl UnifiedFullViewingKey {
}
}
/// Returns the Unified Address corresponding to the smallest valid diversifier index,
/// along with that index.
/// Find the Unified Address corresponding to the smallest valid diversifier index, along with
/// that index.
///
/// Returns an `Err(AddressGenerationError)` if no valid diversifier exists or if the features
/// required to satisfy the unified address request are not properly enabled.
pub fn default_address(
&self,
request: UnifiedAddressRequest,

View File

@ -11,13 +11,14 @@ and this library adheres to Rust's notion of
- `zcash_primitives::transaction::components::sapling::zip212_enforcement`
### Changed
- `zcash_primitives::consensus` is now a reexport of the
`zcash_protocol::consensus` module.
- `zcash_primitives::constants` is now a reexport of the
`zcash_protocol::constants` module.
- `zcash_primitives::transaction::components::amount` is now a reexport of the
`zcash_protocol::value` module.
- `zcash_primitives::memo` is now a reexport of the `zcash_protocol::memo` module.
- The following modules are now re-exported from the `zcash_protocol` crate.
Additional changes have also been made therein; refer to the `zcash_protocol`
changelog for details.
- `zcash_primitives::consensus` re-exports `zcash_protocol::consensus`.
- `zcash_primitives::constants` re-exports `zcash_protocol::constants`.
- `zcash_primitives::transaction::components::amount` re-exports
`zcash_protocol::value`.
- `zcash_primitives::memo` re-exports `zcash_protocol::memo`.
### Removed
- `zcash_primitives::consensus::sapling_zip212_enforcement` instead use
@ -28,6 +29,8 @@ and this library adheres to Rust's notion of
- `impl From<NonNegativeAmount> for sapling::value::NoteValue`
- `impl TryFrom<orchard::ValueSum> for Amount`
- `impl From<NonNegativeAmount> for orchard::NoteValue`
- The `local_consensus` module and feature flag have been removed; use the module
from the `zcash_protocol` crate instead.
## [0.14.0] - 2024-03-01
### Added

View File

@ -118,9 +118,9 @@ temporary-zcashd = []
## Exposes APIs that are useful for testing, such as `proptest` strategies.
test-dependencies = [
"dep:proptest",
"zcash_protocol/test-dependencies",
"orchard/test-dependencies",
"sapling/test-dependencies",
"zcash_protocol/test-dependencies",
]
#! ### Experimental features