Provide PoolType to UnsupportedPoolType case; stylistic changes
This commit is contained in:
parent
a9d18ec2ce
commit
94f2240e08
|
@ -7,6 +7,11 @@ and this library adheres to Rust's notion of
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- `zcash_client_backend::data_api::ShieldedProtocol` has a new variant for `Orchard`, allowing for better reporting to callers trying to perform actions using `Orchard` before it is fully supported.
|
||||||
|
- `zcash_client_backend::data_api::error::Error` has new error variant:
|
||||||
|
- `Error::UnsupportedPoolType(zcash_client_backend::data_api::PoolType)`
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- `zcash_client_backend::data_api::chain::scan_cached_blocks` now returns
|
- `zcash_client_backend::data_api::chain::scan_cached_blocks` now returns
|
||||||
a `ScanSummary` containing metadata about the scanned blocks on success.
|
a `ScanSummary` containing metadata about the scanned blocks on success.
|
||||||
|
|
|
@ -556,7 +556,8 @@ pub struct SentTransaction<'a> {
|
||||||
pub enum ShieldedProtocol {
|
pub enum ShieldedProtocol {
|
||||||
/// The Sapling protocol
|
/// The Sapling protocol
|
||||||
Sapling,
|
Sapling,
|
||||||
// TODO: Orchard
|
/// The Orchard protocol
|
||||||
|
Orchard
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A unique identifier for a shielded transaction output
|
/// A unique identifier for a shielded transaction output
|
||||||
|
|
|
@ -22,7 +22,7 @@ use zcash_primitives::{legacy::TransparentAddress, zip32::DiversifierIndex};
|
||||||
|
|
||||||
/// Errors that can occur as a consequence of wallet operations.
|
/// Errors that can occur as a consequence of wallet operations.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error<DataSourceError, CommitmentTreeError, SelectionError, FeeError, NoteRef> {
|
pub enum Error<DataSourceError, CommitmentTreeError, SelectionError, FeeError, NoteRef, PoolType> {
|
||||||
/// An error occurred retrieving data from the underlying data source
|
/// An error occurred retrieving data from the underlying data source
|
||||||
DataSource(DataSourceError),
|
DataSource(DataSourceError),
|
||||||
|
|
||||||
|
@ -54,8 +54,8 @@ pub enum Error<DataSourceError, CommitmentTreeError, SelectionError, FeeError, N
|
||||||
/// It is forbidden to provide a memo when constructing a transparent output.
|
/// It is forbidden to provide a memo when constructing a transparent output.
|
||||||
MemoForbidden,
|
MemoForbidden,
|
||||||
|
|
||||||
/// Attempted to create a spend to an unsupported output type (i.e. Orchard)
|
/// Attempted to create a spend to an unsupported pool type (currently, Orchard).
|
||||||
UnsupportedOutputType,
|
UnsupportedPoolType(PoolType),
|
||||||
|
|
||||||
/// A note being spent does not correspond to either the internal or external
|
/// A note being spent does not correspond to either the internal or external
|
||||||
/// full viewing key for an account.
|
/// full viewing key for an account.
|
||||||
|
@ -68,13 +68,14 @@ pub enum Error<DataSourceError, CommitmentTreeError, SelectionError, FeeError, N
|
||||||
ChildIndexOutOfRange(DiversifierIndex),
|
ChildIndexOutOfRange(DiversifierIndex),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DE, CE, SE, FE, N> fmt::Display for Error<DE, CE, SE, FE, N>
|
impl<DE, CE, SE, FE, N, PT> fmt::Display for Error<DE, CE, SE, FE, N, PT>
|
||||||
where
|
where
|
||||||
DE: fmt::Display,
|
DE: fmt::Display,
|
||||||
CE: fmt::Display,
|
CE: fmt::Display,
|
||||||
SE: fmt::Display,
|
SE: fmt::Display,
|
||||||
FE: fmt::Display,
|
FE: fmt::Display,
|
||||||
N: fmt::Display,
|
N: fmt::Display,
|
||||||
|
PT: fmt::Display
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match &self {
|
match &self {
|
||||||
|
@ -114,7 +115,7 @@ where
|
||||||
Error::ScanRequired => write!(f, "Must scan blocks first"),
|
Error::ScanRequired => write!(f, "Must scan blocks first"),
|
||||||
Error::Builder(e) => write!(f, "An error occurred building the transaction: {}", e),
|
Error::Builder(e) => write!(f, "An error occurred building the transaction: {}", e),
|
||||||
Error::MemoForbidden => write!(f, "It is not possible to send a memo to a transparent address."),
|
Error::MemoForbidden => write!(f, "It is not possible to send a memo to a transparent address."),
|
||||||
Error::UnsupportedOutputType => write!(f, "Attempted to create spend to an unsupported output type"),
|
Error::UnsupportedPoolType(t) => write!(f, "Attempted to create spend to an unsupported pool type: {}", t),
|
||||||
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::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),
|
||||||
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
|
@ -133,13 +134,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DE, CE, SE, FE, N> error::Error for Error<DE, CE, SE, FE, N>
|
impl<DE, CE, SE, FE, N, PT> error::Error for Error<DE, CE, SE, FE, N, PT>
|
||||||
where
|
where
|
||||||
DE: Debug + Display + error::Error + 'static,
|
DE: Debug + Display + error::Error + 'static,
|
||||||
CE: Debug + Display + error::Error + 'static,
|
CE: Debug + Display + error::Error + 'static,
|
||||||
SE: Debug + Display + error::Error + 'static,
|
SE: Debug + Display + error::Error + 'static,
|
||||||
FE: Debug + Display + 'static,
|
FE: Debug + Display + 'static,
|
||||||
N: Debug + Display,
|
N: Debug + Display,
|
||||||
|
PT: Debug + Display
|
||||||
{
|
{
|
||||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||||
match &self {
|
match &self {
|
||||||
|
@ -152,19 +154,19 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DE, CE, SE, FE, N> From<builder::Error<FE>> for Error<DE, CE, SE, FE, N> {
|
impl<DE, CE, SE, FE, N, PT> From<builder::Error<FE>> for Error<DE, CE, SE, FE, N, PT> {
|
||||||
fn from(e: builder::Error<FE>) -> Self {
|
fn from(e: builder::Error<FE>) -> Self {
|
||||||
Error::Builder(e)
|
Error::Builder(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DE, CE, SE, FE, N> From<BalanceError> for Error<DE, CE, SE, FE, N> {
|
impl<DE, CE, SE, FE, N, PT> From<BalanceError> for Error<DE, CE, SE, FE, N, PT> {
|
||||||
fn from(e: BalanceError) -> Self {
|
fn from(e: BalanceError) -> Self {
|
||||||
Error::BalanceError(e)
|
Error::BalanceError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DE, CE, SE, FE, N> From<InputSelectorError<DE, SE>> for Error<DE, CE, SE, FE, N> {
|
impl<DE, CE, SE, FE, N, PT> From<InputSelectorError<DE, SE>> for Error<DE, CE, SE, FE, N, PT> {
|
||||||
fn from(e: InputSelectorError<DE, SE>) -> Self {
|
fn from(e: InputSelectorError<DE, SE>) -> Self {
|
||||||
match e {
|
match e {
|
||||||
InputSelectorError::DataSource(e) => Error::DataSource(e),
|
InputSelectorError::DataSource(e) => Error::DataSource(e),
|
||||||
|
@ -181,19 +183,19 @@ impl<DE, CE, SE, FE, N> From<InputSelectorError<DE, SE>> for Error<DE, CE, SE, F
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DE, CE, SE, FE, N> From<sapling::builder::Error> for Error<DE, CE, SE, FE, N> {
|
impl<DE, CE, SE, FE, N, PT> From<sapling::builder::Error> for Error<DE, CE, SE, FE, N, PT> {
|
||||||
fn from(e: sapling::builder::Error) -> Self {
|
fn from(e: sapling::builder::Error) -> Self {
|
||||||
Error::Builder(builder::Error::SaplingBuild(e))
|
Error::Builder(builder::Error::SaplingBuild(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DE, CE, SE, FE, N> From<transparent::builder::Error> for Error<DE, CE, SE, FE, N> {
|
impl<DE, CE, SE, FE, N, PT> From<transparent::builder::Error> for Error<DE, CE, SE, FE, N, PT> {
|
||||||
fn from(e: transparent::builder::Error) -> Self {
|
fn from(e: transparent::builder::Error) -> Self {
|
||||||
Error::Builder(builder::Error::TransparentBuild(e))
|
Error::Builder(builder::Error::TransparentBuild(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DE, CE, SE, FE, N> From<ShardTreeError<CE>> for Error<DE, CE, SE, FE, N> {
|
impl<DE, CE, SE, FE, N, PT> From<ShardTreeError<CE>> for Error<DE, CE, SE, FE, N, PT> {
|
||||||
fn from(e: ShardTreeError<CE>) -> Self {
|
fn from(e: ShardTreeError<CE>) -> Self {
|
||||||
Error::CommitmentTree(e)
|
Error::CommitmentTree(e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,6 +207,7 @@ pub fn create_spend_to_address<DbT, ParamsT>(
|
||||||
GreedyInputSelectorError<BalanceError, DbT::NoteRef>,
|
GreedyInputSelectorError<BalanceError, DbT::NoteRef>,
|
||||||
Infallible,
|
Infallible,
|
||||||
DbT::NoteRef,
|
DbT::NoteRef,
|
||||||
|
PoolType,
|
||||||
>,
|
>,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
|
@ -310,6 +311,7 @@ pub fn spend<DbT, ParamsT, InputsT>(
|
||||||
InputsT::Error,
|
InputsT::Error,
|
||||||
<InputsT::FeeRule as FeeRule>::Error,
|
<InputsT::FeeRule as FeeRule>::Error,
|
||||||
DbT::NoteRef,
|
DbT::NoteRef,
|
||||||
|
PoolType,
|
||||||
>,
|
>,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
|
@ -364,6 +366,7 @@ pub fn propose_transfer<DbT, ParamsT, InputsT, CommitmentTreeErrT>(
|
||||||
InputsT::Error,
|
InputsT::Error,
|
||||||
<InputsT::FeeRule as FeeRule>::Error,
|
<InputsT::FeeRule as FeeRule>::Error,
|
||||||
DbT::NoteRef,
|
DbT::NoteRef,
|
||||||
|
PoolType,
|
||||||
>,
|
>,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
|
@ -444,6 +447,7 @@ pub fn create_proposed_transaction<DbT, ParamsT, InputsErrT, FeeRuleT>(
|
||||||
InputsErrT,
|
InputsErrT,
|
||||||
FeeRuleT::Error,
|
FeeRuleT::Error,
|
||||||
DbT::NoteRef,
|
DbT::NoteRef,
|
||||||
|
PoolType,
|
||||||
>,
|
>,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
|
@ -489,7 +493,7 @@ where
|
||||||
|
|
||||||
let checkpoint_depth = wallet_db.get_checkpoint_depth(min_confirmations)?;
|
let checkpoint_depth = wallet_db.get_checkpoint_depth(min_confirmations)?;
|
||||||
|
|
||||||
wallet_db.with_sapling_tree_mut::<_, _, Error<_, _, _, _, _>>(|sapling_tree| {
|
wallet_db.with_sapling_tree_mut::<_, _, Error<_, _, _, _, _, _>>(|sapling_tree| {
|
||||||
for selected in proposal.sapling_inputs() {
|
for selected in proposal.sapling_inputs() {
|
||||||
let (note, key, merkle_path) = select_key_for_note(
|
let (note, key, merkle_path) = select_key_for_note(
|
||||||
sapling_tree,
|
sapling_tree,
|
||||||
|
@ -547,24 +551,24 @@ where
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or_else(MemoBytes::empty, |m| m.clone());
|
.map_or_else(MemoBytes::empty, |m| m.clone());
|
||||||
|
|
||||||
if ua.sapling().is_some() {
|
if let Some(sapling_receiver) = ua.sapling() {
|
||||||
builder.add_sapling_output(
|
builder.add_sapling_output(
|
||||||
external_ovk,
|
external_ovk,
|
||||||
*ua.sapling().unwrap(),
|
*sapling_receiver,
|
||||||
payment.amount,
|
payment.amount,
|
||||||
memo.clone(),
|
memo.clone(),
|
||||||
)?;
|
)?;
|
||||||
} else if ua.transparent().is_some() {
|
} else if let Some(taddr) = ua.transparent() {
|
||||||
if payment.memo.is_some() {
|
if payment.memo.is_some() {
|
||||||
return Err(Error::MemoForbidden);
|
return Err(Error::MemoForbidden);
|
||||||
} else {
|
} else {
|
||||||
builder.add_transparent_output(
|
builder.add_transparent_output(
|
||||||
ua.transparent().unwrap(),
|
taddr,
|
||||||
payment.amount
|
payment.amount
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::UnsupportedOutputType);
|
return Err(Error::UnsupportedPoolType(PoolType::Shielded(ShieldedProtocol::Orchard)));
|
||||||
}
|
}
|
||||||
sapling_output_meta.push((
|
sapling_output_meta.push((
|
||||||
Recipient::Unified(ua.clone(), PoolType::Shielded(ShieldedProtocol::Sapling)),
|
Recipient::Unified(ua.clone(), PoolType::Shielded(ShieldedProtocol::Sapling)),
|
||||||
|
|
|
@ -7,6 +7,10 @@ and this library adheres to Rust's notion of
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- `zcash_client_sqlite::error::SqliteClientError` has new error variant:
|
||||||
|
- `SqliteClientError::UnsupportedPoolType(zcash_client_backend::data_api::PoolType)`
|
||||||
|
|
||||||
## [0.8.0] - 2023-09-25
|
## [0.8.0] - 2023-09-25
|
||||||
|
|
||||||
### Notable Changes
|
### Notable Changes
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use shardtree::error::ShardTreeError;
|
use shardtree::error::ShardTreeError;
|
||||||
|
use zcash_client_backend::data_api::PoolType;
|
||||||
use zcash_client_backend::encoding::{Bech32DecodeError, TransparentCodecError};
|
use zcash_client_backend::encoding::{Bech32DecodeError, TransparentCodecError};
|
||||||
use zcash_primitives::{consensus::BlockHeight, zip32::AccountId};
|
use zcash_primitives::{consensus::BlockHeight, zip32::AccountId};
|
||||||
|
|
||||||
|
@ -98,6 +99,9 @@ pub enum SqliteClientError {
|
||||||
/// [`WalletWrite::update_chain_tip`]:
|
/// [`WalletWrite::update_chain_tip`]:
|
||||||
/// zcash_client_backend::data_api::WalletWrite::update_chain_tip
|
/// zcash_client_backend::data_api::WalletWrite::update_chain_tip
|
||||||
ChainHeightUnknown,
|
ChainHeightUnknown,
|
||||||
|
|
||||||
|
/// Unsupported pool type
|
||||||
|
UnsupportedPoolType(PoolType)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::Error for SqliteClientError {
|
impl error::Error for SqliteClientError {
|
||||||
|
@ -144,7 +148,8 @@ impl fmt::Display for SqliteClientError {
|
||||||
SqliteClientError::AddressNotRecognized(_) => write!(f, "The address associated with a received txo is not identifiable as belonging to the wallet."),
|
SqliteClientError::AddressNotRecognized(_) => write!(f, "The address associated with a received txo is not identifiable as belonging to the wallet."),
|
||||||
SqliteClientError::CommitmentTree(err) => write!(f, "An error occurred accessing or updating note commitment tree data: {}.", err),
|
SqliteClientError::CommitmentTree(err) => write!(f, "An error occurred accessing or updating note commitment tree data: {}.", err),
|
||||||
SqliteClientError::CacheMiss(height) => write!(f, "Requested height {} does not exist in the block cache.", height),
|
SqliteClientError::CacheMiss(height) => write!(f, "Requested height {} does not exist in the block cache.", height),
|
||||||
SqliteClientError::ChainHeightUnknown => write!(f, "Chain height unknown; please call `update_chain_tip`")
|
SqliteClientError::ChainHeightUnknown => write!(f, "Chain height unknown; please call `update_chain_tip`"),
|
||||||
|
SqliteClientError::UnsupportedPoolType(t) => write!(f, "Pool type is not currently supported: {:?}", t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,7 @@ pub(crate) fn pool_code(pool_type: PoolType) -> i64 {
|
||||||
match pool_type {
|
match pool_type {
|
||||||
PoolType::Transparent => 0i64,
|
PoolType::Transparent => 0i64,
|
||||||
PoolType::Shielded(ShieldedProtocol::Sapling) => 2i64,
|
PoolType::Shielded(ShieldedProtocol::Sapling) => 2i64,
|
||||||
|
PoolType::Shielded(ShieldedProtocol::Orchard) => 4i64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,7 +759,12 @@ pub(crate) fn get_received_memo(
|
||||||
conn: &rusqlite::Connection,
|
conn: &rusqlite::Connection,
|
||||||
note_id: NoteId,
|
note_id: NoteId,
|
||||||
) -> Result<Option<Memo>, SqliteClientError> {
|
) -> Result<Option<Memo>, SqliteClientError> {
|
||||||
let memo_bytes: Option<Vec<_>> = match note_id.protocol() {
|
let protocol = note_id.protocol();
|
||||||
|
if let ShieldedProtocol::Orchard = protocol {
|
||||||
|
return Err(SqliteClientError::UnsupportedPoolType(PoolType::Shielded(protocol)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let memo_bytes: Option<Vec<_>> = match protocol {
|
||||||
ShieldedProtocol::Sapling => conn
|
ShieldedProtocol::Sapling => conn
|
||||||
.query_row(
|
.query_row(
|
||||||
"SELECT memo FROM sapling_received_notes
|
"SELECT memo FROM sapling_received_notes
|
||||||
|
@ -773,6 +779,7 @@ pub(crate) fn get_received_memo(
|
||||||
)
|
)
|
||||||
.optional()?
|
.optional()?
|
||||||
.flatten(),
|
.flatten(),
|
||||||
|
ShieldedProtocol::Orchard => None
|
||||||
};
|
};
|
||||||
|
|
||||||
memo_bytes
|
memo_bytes
|
||||||
|
|
Loading…
Reference in New Issue