zcash_client_backend: Update to use extracted `zip321` crate
This commit is contained in:
parent
d982d7826a
commit
3ea7d84183
|
@ -8,8 +8,8 @@ and this library adheres to Rust's notion of
|
|||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- `zcash_address::ZcashAddress::can_receive_memo`
|
||||
- `zcash_address::unified::Address::can_receive_memo`
|
||||
- `zcash_address::ZcashAddress::{can_receive_memo, can_receive_as}`
|
||||
- `zcash_address::unified::Address::{can_receive_memo, has_receiver}`
|
||||
- Module `zcash_address::testing` under the `test-dependencies` feature.
|
||||
- Module `zcash_address::unified::address::testing` under the
|
||||
`test-dependencies` feature.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use zcash_protocol::{PoolType, ShieldedProtocol};
|
||||
|
||||
use super::{private::SealedItem, ParseError, Typecode};
|
||||
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
@ -102,6 +104,17 @@ impl SealedItem for Receiver {
|
|||
pub struct Address(pub(crate) Vec<Receiver>);
|
||||
|
||||
impl Address {
|
||||
/// Returns whether this address has the ability to receive transfers of the given pool type.
|
||||
pub fn has_receiver(&self, pool_type: PoolType) -> bool {
|
||||
self.0.iter().any(|r| match r {
|
||||
Receiver::Orchard(_) => pool_type == PoolType::Shielded(ShieldedProtocol::Orchard),
|
||||
Receiver::Sapling(_) => pool_type == PoolType::Shielded(ShieldedProtocol::Sapling),
|
||||
Receiver::P2pkh(_) => pool_type == PoolType::Transparent,
|
||||
Receiver::P2sh(_) => pool_type == PoolType::Transparent,
|
||||
Receiver::Unknown { .. } => false,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns whether this address can receive a memo.
|
||||
pub fn can_receive_memo(&self) -> bool {
|
||||
self.0
|
||||
|
|
|
@ -142,6 +142,7 @@ pub use convert::{
|
|||
pub use encoding::ParseError;
|
||||
pub use kind::unified;
|
||||
pub use zcash_protocol::consensus::NetworkType as Network;
|
||||
use zcash_protocol::{PoolType, ShieldedProtocol};
|
||||
|
||||
/// A Zcash address.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
|
@ -267,6 +268,18 @@ impl ZcashAddress {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns whether this address has the ability to receive transfers of the given pool type.
|
||||
pub fn can_receive_as(&self, pool_type: PoolType) -> bool {
|
||||
match &self.kind {
|
||||
AddressKind::Sprout(_) => false,
|
||||
AddressKind::Sapling(_) => pool_type == PoolType::Shielded(ShieldedProtocol::Sapling),
|
||||
AddressKind::Unified(addr) => addr.has_receiver(pool_type),
|
||||
AddressKind::P2pkh(_) => pool_type == PoolType::Transparent,
|
||||
AddressKind::P2sh(_) => pool_type == PoolType::Transparent,
|
||||
AddressKind::Tex(_) => pool_type == PoolType::Transparent,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether this address can receive a memo.
|
||||
pub fn can_receive_memo(&self) -> bool {
|
||||
match &self.kind {
|
||||
|
|
|
@ -19,6 +19,12 @@ and this library adheres to Rust's notion of
|
|||
of the root module of the `zip321` crate. Several of the APIs of this module
|
||||
have changed as a consequence of this extraction; please see the `zip321`
|
||||
CHANGELOG for details.
|
||||
- `zcash_client_backend::data_api`:
|
||||
- `error::Error` has a new `Address` variant.
|
||||
- `wallet::input_selection::InputSelectorError` has a new `Address` variant.
|
||||
- `zcash_client_backend::proto::proposal::Proposal::{from_standard_proposal,
|
||||
try_into_standard_proposal}` each no longer require a `consensus::Parameters`
|
||||
argument.
|
||||
|
||||
## [0.12.1] - 2024-03-27
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::error;
|
|||
use std::fmt::{self, Debug, Display};
|
||||
|
||||
use shardtree::error::ShardTreeError;
|
||||
use zcash_address::ConversionError;
|
||||
use zcash_primitives::transaction::components::amount::NonNegativeAmount;
|
||||
use zcash_primitives::transaction::{
|
||||
builder,
|
||||
|
@ -81,6 +82,9 @@ pub enum Error<DataSourceError, CommitmentTreeError, SelectionError, FeeError> {
|
|||
/// full viewing key for an account.
|
||||
NoteMismatch(NoteId),
|
||||
|
||||
/// An error occurred parsing the address from a payment request.
|
||||
Address(ConversionError<&'static str>),
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
AddressNotRecognized(TransparentAddress),
|
||||
}
|
||||
|
@ -145,6 +149,9 @@ where
|
|||
Error::NoSpendingKey(addr) => write!(f, "No spending key available for address: {}", addr),
|
||||
Error::NoteMismatch(n) => write!(f, "A note being spent ({:?}) does not correspond to either the internal or external full viewing key for the provided spending key.", n),
|
||||
|
||||
Error::Address(e) => {
|
||||
write!(f, "An error occurred decoding the address from a payment request: {}.", e)
|
||||
}
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
Error::AddressNotRecognized(_) => {
|
||||
write!(f, "The specified transparent address was not recognized as belonging to the wallet.")
|
||||
|
@ -184,6 +191,12 @@ impl<DE, CE, SE, FE> From<BalanceError> for Error<DE, CE, SE, FE> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<DE, CE, SE, FE> From<ConversionError<&'static str>> for Error<DE, CE, SE, FE> {
|
||||
fn from(value: ConversionError<&'static str>) -> Self {
|
||||
Error::Address(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DE, CE, SE, FE> From<InputSelectorError<DE, SE>> for Error<DE, CE, SE, FE> {
|
||||
fn from(e: InputSelectorError<DE, SE>) -> Self {
|
||||
match e {
|
||||
|
@ -198,6 +211,7 @@ impl<DE, CE, SE, FE> From<InputSelectorError<DE, SE>> for Error<DE, CE, SE, FE>
|
|||
required,
|
||||
},
|
||||
InputSelectorError::SyncRequired => Error::ScanRequired,
|
||||
InputSelectorError::Address(e) => Error::Address(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -498,7 +498,7 @@ where
|
|||
DbT::NoteRef: Copy + Eq + Ord,
|
||||
{
|
||||
let request = zip321::TransactionRequest::new(vec![Payment {
|
||||
recipient_address: to.clone(),
|
||||
recipient_address: to.to_zcash_address(params),
|
||||
amount,
|
||||
memo,
|
||||
label: None,
|
||||
|
@ -848,13 +848,16 @@ where
|
|||
// the transaction in payment index order, so we can use dead reckoning to
|
||||
// figure out which output it ended up being.
|
||||
let (prior_step, result) = &prior_step_results[input_ref.step_index()];
|
||||
let recipient_address = match &prior_step
|
||||
let recipient_address = &prior_step
|
||||
.transaction_request()
|
||||
.payments()
|
||||
.get(&i)
|
||||
.expect("Payment step references are checked at construction")
|
||||
.recipient_address
|
||||
{
|
||||
.clone()
|
||||
.convert_if_network(params.network_type())?;
|
||||
|
||||
let recipient_taddr = match recipient_address {
|
||||
Address::Transparent(t) => Some(t),
|
||||
Address::Unified(uaddr) => uaddr.transparent(),
|
||||
_ => None,
|
||||
|
@ -879,7 +882,7 @@ where
|
|||
.ok_or(Error::Proposal(ProposalError::ReferenceError(*input_ref)))?
|
||||
.vout[outpoint.n() as usize];
|
||||
|
||||
add_transparent_input(recipient_address, outpoint, utxo.clone())?;
|
||||
add_transparent_input(recipient_taddr, outpoint, utxo.clone())?;
|
||||
}
|
||||
proposal::StepOutputIndex::Change(_) => unreachable!(),
|
||||
}
|
||||
|
@ -953,7 +956,11 @@ where
|
|||
(payment, output_pool)
|
||||
})
|
||||
{
|
||||
match &payment.recipient_address {
|
||||
let recipient_address = payment
|
||||
.recipient_address
|
||||
.clone()
|
||||
.convert_if_network::<Address>(params.network_type())?;
|
||||
match recipient_address {
|
||||
Address::Unified(ua) => {
|
||||
let memo = payment
|
||||
.memo
|
||||
|
@ -1019,17 +1026,17 @@ where
|
|||
.map_or_else(MemoBytes::empty, |m| m.clone());
|
||||
builder.add_sapling_output(
|
||||
sapling_external_ovk,
|
||||
*addr,
|
||||
addr,
|
||||
payment.amount,
|
||||
memo.clone(),
|
||||
)?;
|
||||
sapling_output_meta.push((Recipient::Sapling(*addr), payment.amount, Some(memo)));
|
||||
sapling_output_meta.push((Recipient::Sapling(addr), payment.amount, Some(memo)));
|
||||
}
|
||||
Address::Transparent(to) => {
|
||||
if payment.memo.is_some() {
|
||||
return Err(Error::MemoForbidden);
|
||||
} else {
|
||||
builder.add_transparent_output(to, payment.amount)?;
|
||||
builder.add_transparent_output(&to, payment.amount)?;
|
||||
}
|
||||
transparent_output_meta.push((to, payment.amount));
|
||||
}
|
||||
|
@ -1167,7 +1174,7 @@ where
|
|||
.map(|(index, _)| index)
|
||||
.expect("An output should exist in the transaction for each transparent payment.");
|
||||
|
||||
SentTransactionOutput::from_parts(output_index, Recipient::Transparent(*addr), value, None)
|
||||
SentTransactionOutput::from_parts(output_index, Recipient::Transparent(addr), value, None)
|
||||
});
|
||||
|
||||
let mut outputs = vec![];
|
||||
|
|
|
@ -8,6 +8,7 @@ use std::{
|
|||
};
|
||||
|
||||
use nonempty::NonEmpty;
|
||||
use zcash_address::ConversionError;
|
||||
use zcash_primitives::{
|
||||
consensus::{self, BlockHeight},
|
||||
transaction::{
|
||||
|
@ -48,6 +49,8 @@ pub enum InputSelectorError<DbErrT, SelectorErrT> {
|
|||
Selection(SelectorErrT),
|
||||
/// Input selection attempted to generate an invalid transaction proposal.
|
||||
Proposal(ProposalError),
|
||||
/// An error occurred parsing the address from a payment request.
|
||||
Address(ConversionError<&'static str>),
|
||||
/// Insufficient funds were available to satisfy the payment request that inputs were being
|
||||
/// selected to attempt to satisfy.
|
||||
InsufficientFunds {
|
||||
|
@ -59,6 +62,12 @@ pub enum InputSelectorError<DbErrT, SelectorErrT> {
|
|||
SyncRequired,
|
||||
}
|
||||
|
||||
impl<E, S> From<ConversionError<&'static str>> for InputSelectorError<E, S> {
|
||||
fn from(value: ConversionError<&'static str>) -> Self {
|
||||
InputSelectorError::Address(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DE: fmt::Display, SE: fmt::Display> fmt::Display for InputSelectorError<DE, SE> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match &self {
|
||||
|
@ -79,6 +88,13 @@ impl<DE: fmt::Display, SE: fmt::Display> fmt::Display for InputSelectorError<DE,
|
|||
e
|
||||
)
|
||||
}
|
||||
InputSelectorError::Address(e) => {
|
||||
write!(
|
||||
f,
|
||||
"An error occurred decoding the address from a payment request: {}.",
|
||||
e
|
||||
)
|
||||
}
|
||||
InputSelectorError::InsufficientFunds {
|
||||
available,
|
||||
required,
|
||||
|
@ -344,7 +360,11 @@ where
|
|||
let mut orchard_outputs = vec![];
|
||||
let mut payment_pools = BTreeMap::new();
|
||||
for (idx, payment) in transaction_request.payments() {
|
||||
match &payment.recipient_address {
|
||||
let recipient_address = payment
|
||||
.recipient_address
|
||||
.clone()
|
||||
.convert_if_network::<Address>(params.network_type())?;
|
||||
match recipient_address {
|
||||
Address::Transparent(addr) => {
|
||||
payment_pools.insert(*idx, PoolType::Transparent);
|
||||
transparent_outputs.push(TxOut {
|
||||
|
@ -380,7 +400,7 @@ where
|
|||
}
|
||||
|
||||
return Err(InputSelectorError::Selection(
|
||||
GreedyInputSelectorError::UnsupportedAddress(Box::new(addr.clone())),
|
||||
GreedyInputSelectorError::UnsupportedAddress(Box::new(addr)),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -377,7 +377,7 @@ impl<NoteRef> Step<NoteRef> {
|
|||
.payments()
|
||||
.get(idx)
|
||||
.iter()
|
||||
.any(|payment| payment.recipient_address.has_receiver(*pool))
|
||||
.any(|payment| payment.recipient_address.can_receive_as(*pool))
|
||||
{
|
||||
return Err(ProposalError::PaymentPoolsMismatch);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use sapling::{self, note::ExtractedNoteCommitment, Node};
|
|||
use zcash_note_encryption::{EphemeralKeyBytes, COMPACT_NOTE_SIZE};
|
||||
use zcash_primitives::{
|
||||
block::{BlockHash, BlockHeader},
|
||||
consensus::{self, BlockHeight, Parameters},
|
||||
consensus::BlockHeight,
|
||||
memo::{self, MemoBytes},
|
||||
merkle_tree::read_commitment_tree,
|
||||
transaction::{components::amount::NonNegativeAmount, fees::StandardFeeRule, TxId},
|
||||
|
@ -485,17 +485,14 @@ impl From<ShieldedProtocol> for proposal::ValuePool {
|
|||
impl proposal::Proposal {
|
||||
/// Serializes a [`Proposal`] based upon a supported [`StandardFeeRule`] to its protobuf
|
||||
/// representation.
|
||||
pub fn from_standard_proposal<P: Parameters, NoteRef>(
|
||||
params: &P,
|
||||
value: &Proposal<StandardFeeRule, NoteRef>,
|
||||
) -> Self {
|
||||
pub fn from_standard_proposal<NoteRef>(value: &Proposal<StandardFeeRule, NoteRef>) -> Self {
|
||||
use proposal::proposed_input;
|
||||
use proposal::{PriorStepChange, PriorStepOutput, ReceivedOutput};
|
||||
let steps = value
|
||||
.steps()
|
||||
.iter()
|
||||
.map(|step| {
|
||||
let transaction_request = step.transaction_request().to_uri(params);
|
||||
let transaction_request = step.transaction_request().to_uri();
|
||||
|
||||
let anchor_height = step
|
||||
.shielded_inputs()
|
||||
|
@ -607,9 +604,8 @@ impl proposal::Proposal {
|
|||
|
||||
/// Attempts to parse a [`Proposal`] based upon a supported [`StandardFeeRule`] from its
|
||||
/// protobuf representation.
|
||||
pub fn try_into_standard_proposal<P: consensus::Parameters, DbT, DbError>(
|
||||
pub fn try_into_standard_proposal<DbT, DbError>(
|
||||
&self,
|
||||
params: &P,
|
||||
wallet_db: &DbT,
|
||||
) -> Result<Proposal<StandardFeeRule, DbT::NoteRef>, ProposalDecodingError<DbError>>
|
||||
where
|
||||
|
@ -631,7 +627,7 @@ impl proposal::Proposal {
|
|||
let mut steps = Vec::with_capacity(self.steps.len());
|
||||
for step in &self.steps {
|
||||
let transaction_request =
|
||||
TransactionRequest::from_uri(params, &step.transaction_request)?;
|
||||
TransactionRequest::from_uri(&step.transaction_request)?;
|
||||
|
||||
let payment_pools = step
|
||||
.payment_output_pools
|
||||
|
|
|
@ -1896,7 +1896,7 @@ fn check_proposal_serialization_roundtrip(
|
|||
db_data: &WalletDb<rusqlite::Connection, LocalNetwork>,
|
||||
proposal: &Proposal<StandardFeeRule, ReceivedNoteId>,
|
||||
) {
|
||||
let proposal_proto = proposal::Proposal::from_standard_proposal(&db_data.params, proposal);
|
||||
let deserialized_proposal = proposal_proto.try_into_standard_proposal(&db_data.params, db_data);
|
||||
let proposal_proto = proposal::Proposal::from_standard_proposal(proposal);
|
||||
let deserialized_proposal = proposal_proto.try_into_standard_proposal(db_data);
|
||||
assert_matches!(deserialized_proposal, Ok(r) if &r == proposal);
|
||||
}
|
||||
|
|
|
@ -169,7 +169,7 @@ pub(crate) fn send_single_step_proposed_transfer<T: ShieldedPoolTester>() {
|
|||
let to_extsk = T::sk(&[0xf5; 32]);
|
||||
let to: Address = T::sk_default_address(&to_extsk);
|
||||
let request = zip321::TransactionRequest::new(vec![Payment {
|
||||
recipient_address: to,
|
||||
recipient_address: to.to_zcash_address(&st.network()),
|
||||
amount: NonNegativeAmount::const_from_u64(10000),
|
||||
memo: None, // this should result in the creation of an empty memo
|
||||
label: None,
|
||||
|
@ -338,7 +338,7 @@ pub(crate) fn send_multi_step_proposed_transfer<T: ShieldedPoolTester>() {
|
|||
// The first step will deshield to the wallet's default transparent address
|
||||
let to0 = Address::Transparent(account.usk().default_transparent_address().0);
|
||||
let request0 = zip321::TransactionRequest::new(vec![Payment {
|
||||
recipient_address: to0,
|
||||
recipient_address: to0.to_zcash_address(&st.network()),
|
||||
amount: NonNegativeAmount::const_from_u64(50000),
|
||||
memo: None,
|
||||
label: None,
|
||||
|
@ -383,7 +383,7 @@ pub(crate) fn send_multi_step_proposed_transfer<T: ShieldedPoolTester>() {
|
|||
.0,
|
||||
);
|
||||
let request1 = zip321::TransactionRequest::new(vec![Payment {
|
||||
recipient_address: to1,
|
||||
recipient_address: to1.to_zcash_address(&st.network()),
|
||||
amount: NonNegativeAmount::const_from_u64(40000),
|
||||
memo: None,
|
||||
label: None,
|
||||
|
@ -1043,7 +1043,7 @@ pub(crate) fn external_address_change_spends_detected_in_restore_from_seed<
|
|||
let req = TransactionRequest::new(vec![
|
||||
// payment to an external recipient
|
||||
Payment {
|
||||
recipient_address: addr2,
|
||||
recipient_address: addr2.to_zcash_address(&st.network()),
|
||||
amount: amount_sent,
|
||||
memo: None,
|
||||
label: None,
|
||||
|
@ -1052,7 +1052,7 @@ pub(crate) fn external_address_change_spends_detected_in_restore_from_seed<
|
|||
},
|
||||
// payment back to the originating wallet, simulating legacy change
|
||||
Payment {
|
||||
recipient_address: addr,
|
||||
recipient_address: addr.to_zcash_address(&st.network()),
|
||||
amount: amount_legacy_change,
|
||||
memo: None,
|
||||
label: None,
|
||||
|
@ -1152,7 +1152,7 @@ pub(crate) fn zip317_spend<T: ShieldedPoolTester>() {
|
|||
|
||||
// This first request will fail due to insufficient non-dust funds
|
||||
let req = TransactionRequest::new(vec![Payment {
|
||||
recipient_address: T::fvk_default_address(&dfvk),
|
||||
recipient_address: T::fvk_default_address(&dfvk).to_zcash_address(&st.network()),
|
||||
amount: NonNegativeAmount::const_from_u64(50000),
|
||||
memo: None,
|
||||
label: None,
|
||||
|
@ -1177,7 +1177,7 @@ pub(crate) fn zip317_spend<T: ShieldedPoolTester>() {
|
|||
// This request will succeed, spending a single dust input to pay the 10000
|
||||
// ZAT fee in addition to the 41000 ZAT output to the recipient
|
||||
let req = TransactionRequest::new(vec![Payment {
|
||||
recipient_address: T::fvk_default_address(&dfvk),
|
||||
recipient_address: T::fvk_default_address(&dfvk).to_zcash_address(&st.network()),
|
||||
amount: NonNegativeAmount::const_from_u64(41000),
|
||||
memo: None,
|
||||
label: None,
|
||||
|
@ -1480,7 +1480,7 @@ pub(crate) fn pool_crossing_required<P0: ShieldedPoolTester, P1: ShieldedPoolTes
|
|||
|
||||
let transfer_amount = NonNegativeAmount::const_from_u64(200000);
|
||||
let p0_to_p1 = zip321::TransactionRequest::new(vec![Payment {
|
||||
recipient_address: p1_to,
|
||||
recipient_address: p1_to.to_zcash_address(&st.network()),
|
||||
amount: transfer_amount,
|
||||
memo: None,
|
||||
label: None,
|
||||
|
@ -1571,7 +1571,7 @@ pub(crate) fn fully_funded_fully_private<P0: ShieldedPoolTester, P1: ShieldedPoo
|
|||
|
||||
let transfer_amount = NonNegativeAmount::const_from_u64(200000);
|
||||
let p0_to_p1 = zip321::TransactionRequest::new(vec![Payment {
|
||||
recipient_address: p1_to,
|
||||
recipient_address: p1_to.to_zcash_address(&st.network()),
|
||||
amount: transfer_amount,
|
||||
memo: None,
|
||||
label: None,
|
||||
|
@ -1662,7 +1662,7 @@ pub(crate) fn fully_funded_send_to_t<P0: ShieldedPoolTester, P1: ShieldedPoolTes
|
|||
|
||||
let transfer_amount = NonNegativeAmount::const_from_u64(200000);
|
||||
let p0_to_p1 = zip321::TransactionRequest::new(vec![Payment {
|
||||
recipient_address: Address::Transparent(p1_to),
|
||||
recipient_address: Address::Transparent(p1_to).to_zcash_address(&st.network()),
|
||||
amount: transfer_amount,
|
||||
memo: None,
|
||||
label: None,
|
||||
|
@ -1777,7 +1777,7 @@ pub(crate) fn multi_pool_checkpoint<P0: ShieldedPoolTester, P1: ShieldedPoolTest
|
|||
// First, send funds just to P0
|
||||
let transfer_amount = NonNegativeAmount::const_from_u64(200000);
|
||||
let p0_transfer = zip321::TransactionRequest::new(vec![Payment::without_memo(
|
||||
P0::random_address(&mut st.rng),
|
||||
P0::random_address(&mut st.rng).to_zcash_address(&st.network()),
|
||||
transfer_amount,
|
||||
)])
|
||||
.unwrap();
|
||||
|
@ -1802,8 +1802,14 @@ pub(crate) fn multi_pool_checkpoint<P0: ShieldedPoolTester, P1: ShieldedPoolTest
|
|||
|
||||
// In the next block, send funds to both P0 and P1
|
||||
let both_transfer = zip321::TransactionRequest::new(vec![
|
||||
Payment::without_memo(P0::random_address(&mut st.rng), transfer_amount),
|
||||
Payment::without_memo(P1::random_address(&mut st.rng), transfer_amount),
|
||||
Payment::without_memo(
|
||||
P0::random_address(&mut st.rng).to_zcash_address(&st.network()),
|
||||
transfer_amount,
|
||||
),
|
||||
Payment::without_memo(
|
||||
P1::random_address(&mut st.rng).to_zcash_address(&st.network()),
|
||||
transfer_amount,
|
||||
),
|
||||
])
|
||||
.unwrap();
|
||||
let res = st
|
||||
|
@ -2110,7 +2116,7 @@ pub(crate) fn scan_cached_blocks_allows_blocks_out_of_order<T: ShieldedPoolTeste
|
|||
|
||||
// We can spend the received notes
|
||||
let req = TransactionRequest::new(vec![Payment {
|
||||
recipient_address: T::fvk_default_address(&dfvk),
|
||||
recipient_address: T::fvk_default_address(&dfvk).to_zcash_address(&st.network()),
|
||||
amount: NonNegativeAmount::const_from_u64(110_000),
|
||||
memo: None,
|
||||
label: None,
|
||||
|
|
|
@ -65,6 +65,7 @@ The entries below are relative to the `zcash_client_backend` crate as of
|
|||
- `UnifiedAddressRequest`
|
||||
- A new `orchard` feature flag has been added to make it possible to
|
||||
build client code without `orchard` dependendencies.
|
||||
- `zcash_keys::address::Address::to_zcash_address`
|
||||
|
||||
### Changed
|
||||
- The following methods and enum variants have been placed behind an `orchard`
|
||||
|
|
|
@ -295,7 +295,7 @@ impl Address {
|
|||
addr.convert_if_network(params.network_type()).ok()
|
||||
}
|
||||
|
||||
pub fn encode<P: consensus::Parameters>(&self, params: &P) -> String {
|
||||
pub fn to_zcash_address<P: consensus::Parameters>(&self, params: &P) -> ZcashAddress {
|
||||
let net = params.network_type();
|
||||
|
||||
match self {
|
||||
|
@ -311,7 +311,10 @@ impl Address {
|
|||
},
|
||||
Address::Unified(ua) => ua.to_address(net),
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub fn encode<P: consensus::Parameters>(&self, params: &P) -> String {
|
||||
self.to_zcash_address(params).to_string()
|
||||
}
|
||||
|
||||
pub fn has_receiver(&self, pool_type: PoolType) -> bool {
|
||||
|
|
Loading…
Reference in New Issue