Replace SaplingInputSource and TransparentInputSource with InputSource
This unification allows us to better isolate transparent-input dependent functionality. Previously, `TransparentInputSource` could not be placed under a feature flag because the interface was needed for proposal deserialization; by instead making the transparent input source methods flag-dependent, we can correctly produce an error when proposal deserializaiton attempts to select transparent inputs and the feature flag is off.
This commit is contained in:
parent
b83877f44b
commit
d4aa2d6f06
|
@ -10,8 +10,7 @@ and this library adheres to Rust's notion of
|
|||
### Added
|
||||
- `zcash_client_backend::data_api`:
|
||||
- `BlockMetadata::orchard_tree_size` (when the `orchard` feature is enabled).
|
||||
- `TransparentInputSource`
|
||||
- `SaplingInputSource`
|
||||
- `InputSource`
|
||||
- `ScannedBlock::{into_commitments, sapling}`
|
||||
- `ScannedBlock::orchard` (when the `orchard` feature is enabled.)
|
||||
- `ScannedBundles`
|
||||
|
@ -112,15 +111,11 @@ and this library adheres to Rust's notion of
|
|||
- `wallet::create_spend_to_address`
|
||||
- `wallet::shield_transparent_funds`
|
||||
- `wallet::spend`
|
||||
- In order to support better reusability for input selection code, two new
|
||||
traits have been factored out from `WalletRead`:
|
||||
- `zcash_client_backend::data_api::TransparentInputSource`
|
||||
- `zcash_client_backend::data_api::SaplingInputSource`
|
||||
- `wallet::input_selection::InputSelector::propose_shielding`,
|
||||
has been moved out to the newly-created `ShieldingSelector` trait.
|
||||
- `ShieldingSelector::propose_shielding` has been altered such that it takes
|
||||
an explicit `target_height` in order to minimize the capabilities that the
|
||||
`data_api::TransparentInputSource` trait must expose. Also, it now takes its
|
||||
`data_api::InputSource` trait must expose. Also, it now takes its
|
||||
`min_confirmations` argument as `u32` instead of `NonZeroU32`.
|
||||
- The `wallet::input_selection::InputSelector::DataSource`
|
||||
associated type has been renamed to `InputSource`.
|
||||
|
@ -128,7 +123,7 @@ and this library adheres to Rust's notion of
|
|||
has been altered such that it longer takes `min_confirmations` as an
|
||||
argument, instead taking explicit `target_height` and `anchor_height`
|
||||
arguments. This helps to minimize the set of capabilities that the
|
||||
`data_api::SaplingInputSource` must expose.
|
||||
`data_api::InputSource` must expose.
|
||||
- `WalletRead::get_checkpoint_depth` has been removed without replacement. This
|
||||
is no longer needed given the change to use the stored anchor height for transaction
|
||||
proposal execution.
|
||||
|
@ -207,10 +202,11 @@ and this library adheres to Rust's notion of
|
|||
- `zcash_client_backend::data_api::WalletRead::is_valid_account_extfvk` has been
|
||||
removed; it was unused in the ECC mobile wallet SDKs and has been superseded by
|
||||
`get_account_for_ufvk`.
|
||||
- `zcash_client_backend::data_api::WalletRead::get_spendable_sapling_notes` has been
|
||||
removed without replacement as it was unused, and its functionality will be
|
||||
fully reproduced by `SaplingInputSource::select_spendable_sapling_notes` in a future
|
||||
change.
|
||||
- `zcash_client_backend::data_api::WalletRead::{
|
||||
get_spendable_sapling_notes
|
||||
select_spendable_sapling_notes,
|
||||
get_unspent_transparent_outputs,
|
||||
}` - use `data_api::InputSource` instead.
|
||||
- `zcash_client_backend::data_api::ScannedBlock::from_parts` has been made crate-private.
|
||||
- `zcash_client_backend::data_api::ScannedBlock::into_sapling_commitments` has been
|
||||
replaced by `into_commitments` which returns both Sapling and Orchard note commitments
|
||||
|
|
|
@ -17,10 +17,7 @@ use zcash_primitives::{
|
|||
legacy::TransparentAddress,
|
||||
memo::{Memo, MemoBytes},
|
||||
transaction::{
|
||||
components::{
|
||||
amount::{Amount, BalanceError, NonNegativeAmount},
|
||||
OutPoint,
|
||||
},
|
||||
components::amount::{Amount, BalanceError, NonNegativeAmount},
|
||||
Transaction, TxId,
|
||||
},
|
||||
zip32::{AccountId, Scope},
|
||||
|
@ -32,11 +29,15 @@ use crate::{
|
|||
keys::{UnifiedFullViewingKey, UnifiedSpendingKey},
|
||||
proto::service::TreeState,
|
||||
wallet::{NoteId, ReceivedNote, Recipient, WalletTransparentOutput, WalletTx},
|
||||
ShieldedProtocol,
|
||||
};
|
||||
|
||||
use self::chain::CommitmentTreeRoot;
|
||||
use self::scanning::ScanRange;
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
use zcash_primitives::transaction::components::OutPoint;
|
||||
|
||||
pub mod chain;
|
||||
pub mod error;
|
||||
pub mod scanning;
|
||||
|
@ -337,9 +338,9 @@ impl WalletSummary {
|
|||
}
|
||||
}
|
||||
|
||||
/// A trait representing the capability to query a data store for unspent Sapling notes belonging
|
||||
/// to a wallet.
|
||||
pub trait SaplingInputSource {
|
||||
/// A trait representing the capability to query a data store for unspent transaction outputs
|
||||
/// belonging to a wallet.
|
||||
pub trait InputSource {
|
||||
/// The type of errors produced by a wallet backend.
|
||||
type Error;
|
||||
|
||||
|
@ -349,51 +350,53 @@ pub trait SaplingInputSource {
|
|||
/// or a UUID.
|
||||
type NoteRef: Copy + Debug + Eq + Ord;
|
||||
|
||||
/// Fetches a spendable Sapling note by indexing into the specified transaction's
|
||||
/// [`sapling::Bundle::shielded_outputs`].
|
||||
/// Fetches a spendable note by indexing into a transaction's shielded outputs for the
|
||||
/// specified shielded protocol.
|
||||
///
|
||||
/// Returns `Ok(None)` if the note is not known to belong to the wallet or if the note
|
||||
/// is not spendable.
|
||||
fn get_spendable_sapling_note(
|
||||
fn get_spendable_note(
|
||||
&self,
|
||||
txid: &TxId,
|
||||
protocol: ShieldedProtocol,
|
||||
index: u32,
|
||||
) -> Result<Option<ReceivedNote<Self::NoteRef>>, Self::Error>;
|
||||
|
||||
/// Returns a list of spendable Sapling notes sufficient to cover the specified target value,
|
||||
/// if possible.
|
||||
fn select_spendable_sapling_notes(
|
||||
/// Returns a list of spendable notes sufficient to cover the specified target value, if
|
||||
/// possible. Only spendable notes corresponding to the specified shielded protocol will
|
||||
/// be included.
|
||||
fn select_spendable_notes(
|
||||
&self,
|
||||
account: AccountId,
|
||||
target_value: Amount,
|
||||
sources: &[ShieldedProtocol],
|
||||
anchor_height: BlockHeight,
|
||||
exclude: &[Self::NoteRef],
|
||||
) -> Result<Vec<ReceivedNote<Self::NoteRef>>, Self::Error>;
|
||||
}
|
||||
|
||||
/// A trait representing the capability to query a data store for unspent transparent UTXOs
|
||||
/// belonging to a wallet.
|
||||
pub trait TransparentInputSource {
|
||||
/// The type of errors produced by a wallet backend.
|
||||
type Error;
|
||||
|
||||
/// Fetches a spendable transparent output.
|
||||
///
|
||||
/// Returns `Ok(None)` if the UTXO is not known to belong to the wallet or is not
|
||||
/// spendable.
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
fn get_unspent_transparent_output(
|
||||
&self,
|
||||
outpoint: &OutPoint,
|
||||
) -> Result<Option<WalletTransparentOutput>, Self::Error>;
|
||||
_outpoint: &OutPoint,
|
||||
) -> Result<Option<WalletTransparentOutput>, Self::Error> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Returns a list of unspent transparent UTXOs that appear in the chain at heights up to and
|
||||
/// including `max_height`.
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
fn get_unspent_transparent_outputs(
|
||||
&self,
|
||||
address: &TransparentAddress,
|
||||
max_height: BlockHeight,
|
||||
exclude: &[OutPoint],
|
||||
) -> Result<Vec<WalletTransparentOutput>, Self::Error>;
|
||||
_address: &TransparentAddress,
|
||||
_max_height: BlockHeight,
|
||||
_exclude: &[OutPoint],
|
||||
) -> Result<Vec<WalletTransparentOutput>, Self::Error> {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
/// Read-only operations required for light wallet functions.
|
||||
|
@ -1094,11 +1097,12 @@ pub mod testing {
|
|||
address::{AddressMetadata, UnifiedAddress},
|
||||
keys::{UnifiedFullViewingKey, UnifiedSpendingKey},
|
||||
wallet::{NoteId, ReceivedNote, WalletTransparentOutput},
|
||||
ShieldedProtocol,
|
||||
};
|
||||
|
||||
use super::{
|
||||
chain::CommitmentTreeRoot, scanning::ScanRange, AccountBirthday, BlockMetadata,
|
||||
DecryptedTransaction, NullifierQuery, SaplingInputSource, ScannedBlock, SentTransaction,
|
||||
DecryptedTransaction, InputSource, NullifierQuery, ScannedBlock, SentTransaction,
|
||||
WalletCommitmentTrees, WalletRead, WalletSummary, WalletWrite, SAPLING_SHARD_HEIGHT,
|
||||
};
|
||||
|
||||
|
@ -1111,9 +1115,6 @@ pub mod testing {
|
|||
>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
use {super::TransparentInputSource, zcash_primitives::transaction::components::OutPoint};
|
||||
|
||||
impl MockWalletDb {
|
||||
pub fn new(network: Network) -> Self {
|
||||
Self {
|
||||
|
@ -1123,22 +1124,24 @@ pub mod testing {
|
|||
}
|
||||
}
|
||||
|
||||
impl SaplingInputSource for MockWalletDb {
|
||||
impl InputSource for MockWalletDb {
|
||||
type Error = ();
|
||||
type NoteRef = u32;
|
||||
|
||||
fn get_spendable_sapling_note(
|
||||
fn get_spendable_note(
|
||||
&self,
|
||||
_txid: &TxId,
|
||||
_protocol: ShieldedProtocol,
|
||||
_index: u32,
|
||||
) -> Result<Option<ReceivedNote<Self::NoteRef>>, Self::Error> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn select_spendable_sapling_notes(
|
||||
fn select_spendable_notes(
|
||||
&self,
|
||||
_account: AccountId,
|
||||
_target_value: Amount,
|
||||
_sources: &[ShieldedProtocol],
|
||||
_anchor_height: BlockHeight,
|
||||
_exclude: &[Self::NoteRef],
|
||||
) -> Result<Vec<ReceivedNote<Self::NoteRef>>, Self::Error> {
|
||||
|
@ -1146,27 +1149,6 @@ pub mod testing {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
impl TransparentInputSource for MockWalletDb {
|
||||
type Error = ();
|
||||
|
||||
fn get_unspent_transparent_output(
|
||||
&self,
|
||||
_outpoint: &OutPoint,
|
||||
) -> Result<Option<WalletTransparentOutput>, Self::Error> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn get_unspent_transparent_outputs(
|
||||
&self,
|
||||
_address: &TransparentAddress,
|
||||
_anchor_height: BlockHeight,
|
||||
_exclude: &[OutPoint],
|
||||
) -> Result<Vec<WalletTransparentOutput>, Self::Error> {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl WalletRead for MockWalletDb {
|
||||
type Error = ();
|
||||
|
||||
|
|
|
@ -36,13 +36,13 @@ use input_selection::{
|
|||
GreedyInputSelector, GreedyInputSelectorError, InputSelector, InputSelectorError,
|
||||
};
|
||||
|
||||
use super::SaplingInputSource;
|
||||
use super::InputSource;
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
use {
|
||||
super::TransparentInputSource, crate::wallet::WalletTransparentOutput,
|
||||
input_selection::ShieldingSelector, sapling::keys::OutgoingViewingKey,
|
||||
std::convert::Infallible, zcash_primitives::legacy::TransparentAddress,
|
||||
crate::wallet::WalletTransparentOutput, input_selection::ShieldingSelector,
|
||||
sapling::keys::OutgoingViewingKey, std::convert::Infallible,
|
||||
zcash_primitives::legacy::TransparentAddress,
|
||||
};
|
||||
|
||||
/// Scans a [`Transaction`] for any information that can be decrypted by the accounts in
|
||||
|
@ -216,10 +216,8 @@ pub fn create_spend_to_address<DbT, ParamsT>(
|
|||
>
|
||||
where
|
||||
ParamsT: consensus::Parameters + Clone,
|
||||
DbT: WalletWrite
|
||||
+ WalletCommitmentTrees
|
||||
+ SaplingInputSource<Error = <DbT as WalletRead>::Error>,
|
||||
DbT::NoteRef: Copy + Eq + Ord,
|
||||
DbT: WalletWrite + WalletCommitmentTrees + InputSource<Error = <DbT as WalletRead>::Error>,
|
||||
<DbT as InputSource>::NoteRef: Copy + Eq + Ord,
|
||||
{
|
||||
let account = wallet_db
|
||||
.get_account_for_ufvk(&usk.to_unified_full_viewing_key())
|
||||
|
@ -326,10 +324,8 @@ pub fn spend<DbT, ParamsT, InputsT>(
|
|||
>,
|
||||
>
|
||||
where
|
||||
DbT: WalletWrite
|
||||
+ WalletCommitmentTrees
|
||||
+ SaplingInputSource<Error = <DbT as WalletRead>::Error>,
|
||||
DbT::NoteRef: Copy + Eq + Ord,
|
||||
DbT: WalletWrite + WalletCommitmentTrees + InputSource<Error = <DbT as WalletRead>::Error>,
|
||||
<DbT as InputSource>::NoteRef: Copy + Eq + Ord,
|
||||
ParamsT: consensus::Parameters + Clone,
|
||||
InputsT: InputSelector<InputSource = DbT>,
|
||||
{
|
||||
|
@ -371,7 +367,7 @@ pub fn propose_transfer<DbT, ParamsT, InputsT, CommitmentTreeErrT>(
|
|||
request: zip321::TransactionRequest,
|
||||
min_confirmations: NonZeroU32,
|
||||
) -> Result<
|
||||
Proposal<InputsT::FeeRule, DbT::NoteRef>,
|
||||
Proposal<InputsT::FeeRule, <DbT as InputSource>::NoteRef>,
|
||||
Error<
|
||||
<DbT as WalletRead>::Error,
|
||||
CommitmentTreeErrT,
|
||||
|
@ -380,8 +376,8 @@ pub fn propose_transfer<DbT, ParamsT, InputsT, CommitmentTreeErrT>(
|
|||
>,
|
||||
>
|
||||
where
|
||||
DbT: WalletRead + SaplingInputSource<Error = <DbT as WalletRead>::Error>,
|
||||
DbT::NoteRef: Copy + Eq + Ord,
|
||||
DbT: WalletRead + InputSource<Error = <DbT as WalletRead>::Error>,
|
||||
<DbT as InputSource>::NoteRef: Copy + Eq + Ord,
|
||||
ParamsT: consensus::Parameters + Clone,
|
||||
InputsT: InputSelector<InputSource = DbT>,
|
||||
{
|
||||
|
@ -444,7 +440,7 @@ pub fn propose_standard_transfer_to_address<DbT, ParamsT, CommitmentTreeErrT>(
|
|||
>
|
||||
where
|
||||
ParamsT: consensus::Parameters + Clone,
|
||||
DbT: WalletRead + SaplingInputSource<Error = <DbT as WalletRead>::Error>,
|
||||
DbT: WalletRead + InputSource<Error = <DbT as WalletRead>::Error>,
|
||||
DbT::NoteRef: Copy + Eq + Ord,
|
||||
{
|
||||
let request = zip321::TransactionRequest::new(vec![Payment {
|
||||
|
@ -494,7 +490,7 @@ pub fn propose_shielding<DbT, ParamsT, InputsT, CommitmentTreeErrT>(
|
|||
>
|
||||
where
|
||||
ParamsT: consensus::Parameters,
|
||||
DbT: WalletRead + TransparentInputSource<Error = <DbT as WalletRead>::Error>,
|
||||
DbT: WalletRead + InputSource<Error = <DbT as WalletRead>::Error>,
|
||||
InputsT: ShieldingSelector<InputSource = DbT>,
|
||||
{
|
||||
let chain_tip_height = wallet_db
|
||||
|
@ -874,9 +870,7 @@ pub fn shield_transparent_funds<DbT, ParamsT, InputsT>(
|
|||
>
|
||||
where
|
||||
ParamsT: consensus::Parameters,
|
||||
DbT: WalletWrite
|
||||
+ WalletCommitmentTrees
|
||||
+ TransparentInputSource<Error = <DbT as WalletRead>::Error>,
|
||||
DbT: WalletWrite + WalletCommitmentTrees + InputSource<Error = <DbT as WalletRead>::Error>,
|
||||
InputsT: ShieldingSelector<InputSource = DbT>,
|
||||
{
|
||||
let proposal = propose_shielding(
|
||||
|
|
|
@ -19,15 +19,16 @@ use zcash_primitives::{
|
|||
|
||||
use crate::{
|
||||
address::{Address, UnifiedAddress},
|
||||
data_api::SaplingInputSource,
|
||||
data_api::InputSource,
|
||||
fees::{sapling, ChangeError, ChangeStrategy, DustOutputPolicy, TransactionBalance},
|
||||
wallet::{ReceivedNote, WalletTransparentOutput},
|
||||
zip321::TransactionRequest,
|
||||
ShieldedProtocol,
|
||||
};
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
use {
|
||||
crate::data_api::TransparentInputSource, std::collections::BTreeSet, std::convert::Infallible,
|
||||
std::collections::BTreeSet, std::convert::Infallible,
|
||||
zcash_primitives::transaction::components::OutPoint,
|
||||
};
|
||||
|
||||
|
@ -297,9 +298,9 @@ pub trait InputSelector {
|
|||
/// The type of data source that the input selector expects to access to obtain input Sapling
|
||||
/// notes. This associated type permits input selectors that may use specialized knowledge of
|
||||
/// the internals of a particular backing data store, if the generic API of
|
||||
/// `SaplingInputSource` does not provide sufficiently fine-grained operations for a particular
|
||||
/// `InputSource` does not provide sufficiently fine-grained operations for a particular
|
||||
/// backing store to optimally perform input selection.
|
||||
type InputSource: SaplingInputSource;
|
||||
type InputSource: InputSource;
|
||||
/// The type of the fee rule that this input selector uses when computing fees.
|
||||
type FeeRule: FeeRule;
|
||||
|
||||
|
@ -327,8 +328,8 @@ pub trait InputSelector {
|
|||
account: AccountId,
|
||||
transaction_request: TransactionRequest,
|
||||
) -> Result<
|
||||
Proposal<Self::FeeRule, <Self::InputSource as SaplingInputSource>::NoteRef>,
|
||||
InputSelectorError<<Self::InputSource as SaplingInputSource>::Error, Self::Error>,
|
||||
Proposal<Self::FeeRule, <Self::InputSource as InputSource>::NoteRef>,
|
||||
InputSelectorError<<Self::InputSource as InputSource>::Error, Self::Error>,
|
||||
>
|
||||
where
|
||||
ParamsT: consensus::Parameters;
|
||||
|
@ -344,9 +345,9 @@ pub trait ShieldingSelector {
|
|||
/// The type of data source that the input selector expects to access to obtain input
|
||||
/// transparent UTXOs. This associated type permits input selectors that may use specialized
|
||||
/// knowledge of the internals of a particular backing data store, if the generic API of
|
||||
/// `TransparentInputSource` does not provide sufficiently fine-grained operations for a
|
||||
/// [`InputSource`] does not provide sufficiently fine-grained operations for a
|
||||
/// particular backing store to optimally perform input selection.
|
||||
type InputSource: TransparentInputSource;
|
||||
type InputSource: InputSource;
|
||||
/// The type of the fee rule that this input selector uses when computing fees.
|
||||
type FeeRule: FeeRule;
|
||||
|
||||
|
@ -369,7 +370,7 @@ pub trait ShieldingSelector {
|
|||
min_confirmations: u32,
|
||||
) -> Result<
|
||||
Proposal<Self::FeeRule, Infallible>,
|
||||
InputSelectorError<<Self::InputSource as TransparentInputSource>::Error, Self::Error>,
|
||||
InputSelectorError<<Self::InputSource as InputSource>::Error, Self::Error>,
|
||||
>
|
||||
where
|
||||
ParamsT: consensus::Parameters;
|
||||
|
@ -450,7 +451,7 @@ impl sapling::OutputView for SaplingPayment {
|
|||
/// notes.
|
||||
///
|
||||
/// This implementation performs input selection using methods available via the
|
||||
/// [`SaplingInputSource`] and `TransparentInputSource` interfaces.
|
||||
/// [`InputSource`] interface.
|
||||
pub struct GreedyInputSelector<DbT, ChangeT> {
|
||||
change_strategy: ChangeT,
|
||||
dust_output_policy: DustOutputPolicy,
|
||||
|
@ -471,7 +472,7 @@ impl<DbT, ChangeT: ChangeStrategy> GreedyInputSelector<DbT, ChangeT> {
|
|||
|
||||
impl<DbT, ChangeT> InputSelector for GreedyInputSelector<DbT, ChangeT>
|
||||
where
|
||||
DbT: SaplingInputSource,
|
||||
DbT: InputSource,
|
||||
ChangeT: ChangeStrategy,
|
||||
ChangeT::FeeRule: Clone,
|
||||
{
|
||||
|
@ -490,11 +491,11 @@ where
|
|||
transaction_request: TransactionRequest,
|
||||
) -> Result<
|
||||
Proposal<Self::FeeRule, DbT::NoteRef>,
|
||||
InputSelectorError<<DbT as SaplingInputSource>::Error, Self::Error>,
|
||||
InputSelectorError<<DbT as InputSource>::Error, Self::Error>,
|
||||
>
|
||||
where
|
||||
ParamsT: consensus::Parameters,
|
||||
Self::InputSource: SaplingInputSource,
|
||||
Self::InputSource: InputSource,
|
||||
{
|
||||
let mut transparent_outputs = vec![];
|
||||
let mut sapling_outputs = vec![];
|
||||
|
@ -575,9 +576,10 @@ where
|
|||
}
|
||||
|
||||
sapling_inputs = wallet_db
|
||||
.select_spendable_sapling_notes(
|
||||
.select_spendable_notes(
|
||||
account,
|
||||
amount_required.into(),
|
||||
&[ShieldedProtocol::Sapling],
|
||||
anchor_height,
|
||||
&exclude,
|
||||
)
|
||||
|
@ -606,7 +608,7 @@ where
|
|||
#[cfg(feature = "transparent-inputs")]
|
||||
impl<DbT, ChangeT> ShieldingSelector for GreedyInputSelector<DbT, ChangeT>
|
||||
where
|
||||
DbT: TransparentInputSource,
|
||||
DbT: InputSource,
|
||||
ChangeT: ChangeStrategy,
|
||||
ChangeT::FeeRule: Clone,
|
||||
{
|
||||
|
@ -625,7 +627,7 @@ where
|
|||
min_confirmations: u32,
|
||||
) -> Result<
|
||||
Proposal<Self::FeeRule, Infallible>,
|
||||
InputSelectorError<<DbT as TransparentInputSource>::Error, Self::Error>,
|
||||
InputSelectorError<<DbT as InputSource>::Error, Self::Error>,
|
||||
>
|
||||
where
|
||||
ParamsT: consensus::Parameters,
|
||||
|
|
|
@ -9,17 +9,13 @@ use std::{
|
|||
use incrementalmerkletree::frontier::CommitmentTree;
|
||||
|
||||
use nonempty::NonEmpty;
|
||||
use sapling::{note::ExtractedNoteCommitment, Node, Nullifier, NOTE_COMMITMENT_TREE_DEPTH};
|
||||
use sapling::{self, note::ExtractedNoteCommitment, Node, Nullifier, NOTE_COMMITMENT_TREE_DEPTH};
|
||||
use zcash_primitives::{
|
||||
block::{BlockHash, BlockHeader},
|
||||
consensus::{self, BlockHeight, Parameters},
|
||||
memo::{self, MemoBytes},
|
||||
merkle_tree::read_commitment_tree,
|
||||
transaction::{
|
||||
components::{amount::NonNegativeAmount, OutPoint},
|
||||
fees::StandardFeeRule,
|
||||
TxId,
|
||||
},
|
||||
transaction::{components::amount::NonNegativeAmount, fees::StandardFeeRule, TxId},
|
||||
};
|
||||
|
||||
use zcash_note_encryption::{EphemeralKeyBytes, COMPACT_NOTE_SIZE};
|
||||
|
@ -27,13 +23,16 @@ use zcash_note_encryption::{EphemeralKeyBytes, COMPACT_NOTE_SIZE};
|
|||
use crate::{
|
||||
data_api::{
|
||||
wallet::input_selection::{Proposal, ProposalError, SaplingInputs},
|
||||
SaplingInputSource, TransparentInputSource,
|
||||
InputSource,
|
||||
},
|
||||
fees::{ChangeValue, TransactionBalance},
|
||||
zip321::{TransactionRequest, Zip321Error},
|
||||
PoolType, ShieldedProtocol,
|
||||
};
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
use zcash_primitives::transaction::components::OutPoint;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(unknown_lints)]
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
|
@ -384,7 +383,7 @@ impl proposal::Proposal {
|
|||
wallet_db: &DbT,
|
||||
) -> Result<Proposal<StandardFeeRule, DbT::NoteRef>, ProposalDecodingError<DbError>>
|
||||
where
|
||||
DbT: TransparentInputSource<Error = DbError> + SaplingInputSource<Error = DbError>,
|
||||
DbT: InputSource<Error = DbError>,
|
||||
{
|
||||
match self.proto_version {
|
||||
PROPOSAL_SER_V1 => {
|
||||
|
@ -407,8 +406,17 @@ impl proposal::Proposal {
|
|||
let txid = t_in
|
||||
.parse_txid()
|
||||
.map_err(ProposalDecodingError::TxIdInvalid)?;
|
||||
let outpoint = OutPoint::new(txid.into(), t_in.index);
|
||||
|
||||
#[cfg(not(feature = "transparent-inputs"))]
|
||||
return Err(ProposalDecodingError::InputNotFound(
|
||||
txid,
|
||||
PoolType::Transparent,
|
||||
t_in.index,
|
||||
));
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
{
|
||||
let outpoint = OutPoint::new(txid.into(), t_in.index);
|
||||
wallet_db
|
||||
.get_unspent_transparent_output(&outpoint)
|
||||
.map_err(ProposalDecodingError::InputRetrieval)?
|
||||
|
@ -419,6 +427,7 @@ impl proposal::Proposal {
|
|||
t_in.index,
|
||||
)
|
||||
})
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
|
@ -431,7 +440,7 @@ impl proposal::Proposal {
|
|||
.map_err(ProposalDecodingError::TxIdInvalid)?;
|
||||
|
||||
wallet_db
|
||||
.get_spendable_sapling_note(&txid, s_in.index)
|
||||
.get_spendable_note(&txid, ShieldedProtocol::Sapling, s_in.index)
|
||||
.map_err(ProposalDecodingError::InputRetrieval)
|
||||
.and_then(|opt| {
|
||||
opt.ok_or({
|
||||
|
|
|
@ -61,7 +61,7 @@ use zcash_client_backend::{
|
|||
self,
|
||||
chain::{BlockSource, CommitmentTreeRoot},
|
||||
scanning::{ScanPriority, ScanRange},
|
||||
AccountBirthday, BlockMetadata, DecryptedTransaction, NullifierQuery, SaplingInputSource,
|
||||
AccountBirthday, BlockMetadata, DecryptedTransaction, InputSource, NullifierQuery,
|
||||
ScannedBlock, SentTransaction, WalletCommitmentTrees, WalletRead, WalletSummary,
|
||||
WalletWrite, SAPLING_SHARD_HEIGHT,
|
||||
},
|
||||
|
@ -74,10 +74,7 @@ use zcash_client_backend::{
|
|||
use crate::{error::SqliteClientError, wallet::commitment_tree::SqliteShardStore};
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
use {
|
||||
zcash_client_backend::data_api::TransparentInputSource,
|
||||
zcash_primitives::transaction::components::OutPoint,
|
||||
};
|
||||
use zcash_primitives::transaction::components::OutPoint;
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
use {
|
||||
|
@ -164,24 +161,24 @@ impl<P: consensus::Parameters + Clone> WalletDb<Connection, P> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<C: Borrow<rusqlite::Connection>, P: consensus::Parameters> SaplingInputSource
|
||||
for WalletDb<C, P>
|
||||
{
|
||||
impl<C: Borrow<rusqlite::Connection>, P: consensus::Parameters> InputSource for WalletDb<C, P> {
|
||||
type Error = SqliteClientError;
|
||||
type NoteRef = ReceivedNoteId;
|
||||
|
||||
fn get_spendable_sapling_note(
|
||||
fn get_spendable_note(
|
||||
&self,
|
||||
txid: &TxId,
|
||||
_protocol: ShieldedProtocol,
|
||||
index: u32,
|
||||
) -> Result<Option<ReceivedNote<Self::NoteRef>>, Self::Error> {
|
||||
wallet::sapling::get_spendable_sapling_note(self.conn.borrow(), &self.params, txid, index)
|
||||
}
|
||||
|
||||
fn select_spendable_sapling_notes(
|
||||
fn select_spendable_notes(
|
||||
&self,
|
||||
account: AccountId,
|
||||
target_value: Amount,
|
||||
_sources: &[ShieldedProtocol],
|
||||
anchor_height: BlockHeight,
|
||||
exclude: &[Self::NoteRef],
|
||||
) -> Result<Vec<ReceivedNote<Self::NoteRef>>, Self::Error> {
|
||||
|
@ -194,14 +191,8 @@ impl<C: Borrow<rusqlite::Connection>, P: consensus::Parameters> SaplingInputSour
|
|||
exclude,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
impl<C: Borrow<rusqlite::Connection>, P: consensus::Parameters> TransparentInputSource
|
||||
for WalletDb<C, P>
|
||||
{
|
||||
type Error = SqliteClientError;
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
fn get_unspent_transparent_output(
|
||||
&self,
|
||||
outpoint: &OutPoint,
|
||||
|
@ -209,6 +200,7 @@ impl<C: Borrow<rusqlite::Connection>, P: consensus::Parameters> TransparentInput
|
|||
wallet::get_unspent_transparent_output(self.conn.borrow(), outpoint)
|
||||
}
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
fn get_unspent_transparent_outputs(
|
||||
&self,
|
||||
address: &TransparentAddress,
|
||||
|
|
|
@ -41,6 +41,7 @@ use zcash_client_backend::{
|
|||
proto::compact_formats::{
|
||||
self as compact, CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx,
|
||||
},
|
||||
proto::proposal,
|
||||
wallet::OvkPolicy,
|
||||
zip321,
|
||||
};
|
||||
|
@ -71,12 +72,9 @@ use super::BlockDb;
|
|||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
use {
|
||||
zcash_client_backend::{
|
||||
data_api::wallet::{
|
||||
zcash_client_backend::data_api::wallet::{
|
||||
input_selection::ShieldingSelector, propose_shielding, shield_transparent_funds,
|
||||
},
|
||||
proto::proposal,
|
||||
},
|
||||
zcash_primitives::legacy::TransparentAddress,
|
||||
};
|
||||
|
||||
|
@ -571,7 +569,6 @@ impl<Cache> TestState<Cache> {
|
|||
change_memo,
|
||||
);
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
if let Ok(proposal) = &result {
|
||||
check_proposal_serialization_roundtrip(self.wallet(), proposal);
|
||||
}
|
||||
|
@ -1075,7 +1072,6 @@ pub(crate) fn input_selector(
|
|||
|
||||
// Checks that a protobuf proposal serialized from the provided proposal value correctly parses to
|
||||
// the same proposal value.
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
pub(crate) fn check_proposal_serialization_roundtrip(
|
||||
db_data: &WalletDb<rusqlite::Connection, Network>,
|
||||
proposal: &Proposal<StandardFeeRule, ReceivedNoteId>,
|
||||
|
|
|
@ -1993,9 +1993,7 @@ mod tests {
|
|||
},
|
||||
sapling::zip32::ExtendedSpendingKey,
|
||||
zcash_client_backend::{
|
||||
data_api::{
|
||||
wallet::input_selection::GreedyInputSelector, TransparentInputSource, WalletWrite,
|
||||
},
|
||||
data_api::{wallet::input_selection::GreedyInputSelector, InputSource, WalletWrite},
|
||||
encoding::AddressCodec,
|
||||
fees::{fixed, DustOutputPolicy},
|
||||
wallet::WalletTransparentOutput,
|
||||
|
|
Loading…
Reference in New Issue