From 94f2240e0890e9844f85fcdde0d7a6647b5bef8f Mon Sep 17 00:00:00 2001 From: Matthew Watt Date: Sun, 8 Oct 2023 19:05:50 -0500 Subject: [PATCH] Provide PoolType to UnsupportedPoolType case; stylistic changes --- zcash_client_backend/CHANGELOG.md | 5 ++++ zcash_client_backend/src/data_api.rs | 3 ++- zcash_client_backend/src/data_api/error.rs | 26 +++++++++++---------- zcash_client_backend/src/data_api/wallet.rs | 16 ++++++++----- zcash_client_sqlite/CHANGELOG.md | 4 ++++ zcash_client_sqlite/src/error.rs | 7 +++++- zcash_client_sqlite/src/wallet.rs | 9 ++++++- 7 files changed, 49 insertions(+), 21 deletions(-) diff --git a/zcash_client_backend/CHANGELOG.md b/zcash_client_backend/CHANGELOG.md index 449efeb5f..0af57a371 100644 --- a/zcash_client_backend/CHANGELOG.md +++ b/zcash_client_backend/CHANGELOG.md @@ -7,6 +7,11 @@ and this library adheres to Rust's notion of ## [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 - `zcash_client_backend::data_api::chain::scan_cached_blocks` now returns a `ScanSummary` containing metadata about the scanned blocks on success. diff --git a/zcash_client_backend/src/data_api.rs b/zcash_client_backend/src/data_api.rs index 875ac614b..2fd0b5b2d 100644 --- a/zcash_client_backend/src/data_api.rs +++ b/zcash_client_backend/src/data_api.rs @@ -556,7 +556,8 @@ pub struct SentTransaction<'a> { pub enum ShieldedProtocol { /// The Sapling protocol Sapling, - // TODO: Orchard + /// The Orchard protocol + Orchard } /// A unique identifier for a shielded transaction output diff --git a/zcash_client_backend/src/data_api/error.rs b/zcash_client_backend/src/data_api/error.rs index f5297116b..88357816f 100644 --- a/zcash_client_backend/src/data_api/error.rs +++ b/zcash_client_backend/src/data_api/error.rs @@ -22,7 +22,7 @@ use zcash_primitives::{legacy::TransparentAddress, zip32::DiversifierIndex}; /// Errors that can occur as a consequence of wallet operations. #[derive(Debug)] -pub enum Error { +pub enum Error { /// An error occurred retrieving data from the underlying data source DataSource(DataSourceError), @@ -54,8 +54,8 @@ pub enum Error fmt::Display for Error +impl fmt::Display for Error where DE: fmt::Display, CE: fmt::Display, SE: fmt::Display, FE: fmt::Display, N: fmt::Display, + PT: fmt::Display { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match &self { @@ -114,7 +115,7 @@ where Error::ScanRequired => write!(f, "Must scan blocks first"), 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::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), #[cfg(feature = "transparent-inputs")] @@ -133,13 +134,14 @@ where } } -impl error::Error for Error +impl error::Error for Error where DE: Debug + Display + error::Error + 'static, CE: Debug + Display + error::Error + 'static, SE: Debug + Display + error::Error + 'static, FE: Debug + Display + 'static, N: Debug + Display, + PT: Debug + Display { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match &self { @@ -152,19 +154,19 @@ where } } -impl From> for Error { +impl From> for Error { fn from(e: builder::Error) -> Self { Error::Builder(e) } } -impl From for Error { +impl From for Error { fn from(e: BalanceError) -> Self { Error::BalanceError(e) } } -impl From> for Error { +impl From> for Error { fn from(e: InputSelectorError) -> Self { match e { InputSelectorError::DataSource(e) => Error::DataSource(e), @@ -181,19 +183,19 @@ impl From> for Error From for Error { +impl From for Error { fn from(e: sapling::builder::Error) -> Self { Error::Builder(builder::Error::SaplingBuild(e)) } } -impl From for Error { +impl From for Error { fn from(e: transparent::builder::Error) -> Self { Error::Builder(builder::Error::TransparentBuild(e)) } } -impl From> for Error { +impl From> for Error { fn from(e: ShardTreeError) -> Self { Error::CommitmentTree(e) } diff --git a/zcash_client_backend/src/data_api/wallet.rs b/zcash_client_backend/src/data_api/wallet.rs index 61da02983..0e2568e3f 100644 --- a/zcash_client_backend/src/data_api/wallet.rs +++ b/zcash_client_backend/src/data_api/wallet.rs @@ -207,6 +207,7 @@ pub fn create_spend_to_address( GreedyInputSelectorError, Infallible, DbT::NoteRef, + PoolType, >, > where @@ -310,6 +311,7 @@ pub fn spend( InputsT::Error, ::Error, DbT::NoteRef, + PoolType, >, > where @@ -364,6 +366,7 @@ pub fn propose_transfer( InputsT::Error, ::Error, DbT::NoteRef, + PoolType, >, > where @@ -444,6 +447,7 @@ pub fn create_proposed_transaction( InputsErrT, FeeRuleT::Error, DbT::NoteRef, + PoolType, >, > where @@ -489,7 +493,7 @@ where 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() { let (note, key, merkle_path) = select_key_for_note( sapling_tree, @@ -547,24 +551,24 @@ where .as_ref() .map_or_else(MemoBytes::empty, |m| m.clone()); - if ua.sapling().is_some() { + if let Some(sapling_receiver) = ua.sapling() { builder.add_sapling_output( external_ovk, - *ua.sapling().unwrap(), + *sapling_receiver, payment.amount, memo.clone(), )?; - } else if ua.transparent().is_some() { + } else if let Some(taddr) = ua.transparent() { if payment.memo.is_some() { return Err(Error::MemoForbidden); } else { builder.add_transparent_output( - ua.transparent().unwrap(), + taddr, payment.amount )?; } } else { - return Err(Error::UnsupportedOutputType); + return Err(Error::UnsupportedPoolType(PoolType::Shielded(ShieldedProtocol::Orchard))); } sapling_output_meta.push(( Recipient::Unified(ua.clone(), PoolType::Shielded(ShieldedProtocol::Sapling)), diff --git a/zcash_client_sqlite/CHANGELOG.md b/zcash_client_sqlite/CHANGELOG.md index 2a044fc2b..f1419da2d 100644 --- a/zcash_client_sqlite/CHANGELOG.md +++ b/zcash_client_sqlite/CHANGELOG.md @@ -7,6 +7,10 @@ and this library adheres to Rust's notion of ## [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 ### Notable Changes diff --git a/zcash_client_sqlite/src/error.rs b/zcash_client_sqlite/src/error.rs index b513fc3d1..177026e5e 100644 --- a/zcash_client_sqlite/src/error.rs +++ b/zcash_client_sqlite/src/error.rs @@ -4,6 +4,7 @@ use std::error; use std::fmt; use shardtree::error::ShardTreeError; +use zcash_client_backend::data_api::PoolType; use zcash_client_backend::encoding::{Bech32DecodeError, TransparentCodecError}; use zcash_primitives::{consensus::BlockHeight, zip32::AccountId}; @@ -98,6 +99,9 @@ pub enum SqliteClientError { /// [`WalletWrite::update_chain_tip`]: /// zcash_client_backend::data_api::WalletWrite::update_chain_tip ChainHeightUnknown, + + /// Unsupported pool type + UnsupportedPoolType(PoolType) } 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::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::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) } } } diff --git a/zcash_client_sqlite/src/wallet.rs b/zcash_client_sqlite/src/wallet.rs index 715d30f7c..41ea48e0f 100644 --- a/zcash_client_sqlite/src/wallet.rs +++ b/zcash_client_sqlite/src/wallet.rs @@ -136,6 +136,7 @@ pub(crate) fn pool_code(pool_type: PoolType) -> i64 { match pool_type { PoolType::Transparent => 0i64, PoolType::Shielded(ShieldedProtocol::Sapling) => 2i64, + PoolType::Shielded(ShieldedProtocol::Orchard) => 4i64 } } @@ -758,7 +759,12 @@ pub(crate) fn get_received_memo( conn: &rusqlite::Connection, note_id: NoteId, ) -> Result, SqliteClientError> { - let memo_bytes: Option> = 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> = match protocol { ShieldedProtocol::Sapling => conn .query_row( "SELECT memo FROM sapling_received_notes @@ -773,6 +779,7 @@ pub(crate) fn get_received_memo( ) .optional()? .flatten(), + ShieldedProtocol::Orchard => None }; memo_bytes