From a9d18ec2ce64905202f990e0191693845d07da4f Mon Sep 17 00:00:00 2001 From: Matthew Watt Date: Sat, 7 Oct 2023 15:30:07 -0500 Subject: [PATCH 01/14] Gracefully handle attempted spend to a UA with neither transparent nor sapling recipients --- zcash_client_backend/src/data_api/error.rs | 4 ++++ zcash_client_backend/src/data_api/wallet.rs | 26 ++++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/zcash_client_backend/src/data_api/error.rs b/zcash_client_backend/src/data_api/error.rs index 31a9b39c9..f5297116b 100644 --- a/zcash_client_backend/src/data_api/error.rs +++ b/zcash_client_backend/src/data_api/error.rs @@ -54,6 +54,9 @@ pub enum Error 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::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")] diff --git a/zcash_client_backend/src/data_api/wallet.rs b/zcash_client_backend/src/data_api/wallet.rs index 0d1adda6f..61da02983 100644 --- a/zcash_client_backend/src/data_api/wallet.rs +++ b/zcash_client_backend/src/data_api/wallet.rs @@ -546,12 +546,26 @@ where .memo .as_ref() .map_or_else(MemoBytes::empty, |m| m.clone()); - builder.add_sapling_output( - external_ovk, - *ua.sapling().expect("TODO: Add Orchard support to builder"), - payment.amount, - memo.clone(), - )?; + + if ua.sapling().is_some() { + builder.add_sapling_output( + external_ovk, + *ua.sapling().unwrap(), + payment.amount, + memo.clone(), + )?; + } else if ua.transparent().is_some() { + if payment.memo.is_some() { + return Err(Error::MemoForbidden); + } else { + builder.add_transparent_output( + ua.transparent().unwrap(), + payment.amount + )?; + } + } else { + return Err(Error::UnsupportedOutputType); + } sapling_output_meta.push(( Recipient::Unified(ua.clone(), PoolType::Shielded(ShieldedProtocol::Sapling)), payment.amount, From 94f2240e0890e9844f85fcdde0d7a6647b5bef8f Mon Sep 17 00:00:00 2001 From: Matthew Watt Date: Sun, 8 Oct 2023 19:05:50 -0500 Subject: [PATCH 02/14] 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 From 46ed4964c3612cab98516235b280e968d707ee5e Mon Sep 17 00:00:00 2001 From: Matthew Watt Date: Sun, 8 Oct 2023 19:19:51 -0500 Subject: [PATCH 03/14] Display for PoolType --- zcash_client_backend/src/data_api.rs | 12 +++++++++++- zcash_client_sqlite/src/error.rs | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/zcash_client_backend/src/data_api.rs b/zcash_client_backend/src/data_api.rs index 2fd0b5b2d..7be3321c5 100644 --- a/zcash_client_backend/src/data_api.rs +++ b/zcash_client_backend/src/data_api.rs @@ -2,7 +2,7 @@ use std::{ collections::{BTreeMap, HashMap}, - fmt::Debug, + fmt::{self, Debug}, io, num::{NonZeroU32, TryFromIntError}, }; @@ -604,6 +604,16 @@ pub enum PoolType { Shielded(ShieldedProtocol), } +impl fmt::Display for PoolType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + PoolType::Transparent => f.write_str("Transparent"), + PoolType::Shielded(ShieldedProtocol::Sapling) => f.write_str("Sapling"), + PoolType::Shielded(ShieldedProtocol::Orchard) => f.write_str("Orchard"), + } + } +} + /// A type that represents the recipient of a transaction output; a recipient address (and, for /// unified addresses, the pool to which the payment is sent) in the case of outgoing output, or an /// internal account ID and the pool to which funds were sent in the case of a wallet-internal diff --git a/zcash_client_sqlite/src/error.rs b/zcash_client_sqlite/src/error.rs index 177026e5e..4d9977d76 100644 --- a/zcash_client_sqlite/src/error.rs +++ b/zcash_client_sqlite/src/error.rs @@ -149,7 +149,7 @@ impl fmt::Display for SqliteClientError { 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::UnsupportedPoolType(t) => write!(f, "Pool type is not currently supported: {:?}", t) + SqliteClientError::UnsupportedPoolType(t) => write!(f, "Pool type is not currently supported: {}", t) } } } From 029b7f0d69f5b06e0fb8d799658107f1081b2a1d Mon Sep 17 00:00:00 2001 From: Matthew Watt Date: Sun, 8 Oct 2023 19:27:20 -0500 Subject: [PATCH 04/14] Document fallback behavior for Orchard-only UAs --- zcash_client_backend/src/data_api/wallet.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zcash_client_backend/src/data_api/wallet.rs b/zcash_client_backend/src/data_api/wallet.rs index 0e2568e3f..f58fd0be2 100644 --- a/zcash_client_backend/src/data_api/wallet.rs +++ b/zcash_client_backend/src/data_api/wallet.rs @@ -428,6 +428,9 @@ where /// /// Returns the database identifier for the newly constructed transaction, or an error if /// an error occurs in transaction construction, proving, or signing. +/// +/// Note: If the payment includes a recipient with an Orchard-only UA, this will attempt to fallback +/// to the transparent receiver until full Orchard support is implemented #[allow(clippy::too_many_arguments)] #[allow(clippy::type_complexity)] pub fn create_proposed_transaction( From 9d7ac07b1ab7d1ad15a9e3160b4cebce98ff1a0a Mon Sep 17 00:00:00 2001 From: Matthew Watt Date: Sun, 8 Oct 2023 19:37:02 -0500 Subject: [PATCH 05/14] Fix test build failures --- zcash_client_sqlite/src/testing.rs | 6 +++++- zcash_client_sqlite/src/wallet/sapling.rs | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/zcash_client_sqlite/src/testing.rs b/zcash_client_sqlite/src/testing.rs index 386543c10..0a2db28e7 100644 --- a/zcash_client_sqlite/src/testing.rs +++ b/zcash_client_sqlite/src/testing.rs @@ -15,7 +15,7 @@ use tempfile::NamedTempFile; use tempfile::TempDir; use zcash_client_backend::data_api::chain::ScanSummary; -use zcash_client_backend::data_api::{AccountBalance, WalletRead}; +use zcash_client_backend::data_api::{AccountBalance, WalletRead, PoolType}; #[allow(deprecated)] use zcash_client_backend::{ address::RecipientAddress, @@ -446,6 +446,7 @@ impl TestState { GreedyInputSelectorError, Infallible, ReceivedNoteId, + PoolType, >, > { let params = self.network(); @@ -479,6 +480,7 @@ impl TestState { InputsT::Error, ::Error, ReceivedNoteId, + PoolType, >, > where @@ -513,6 +515,7 @@ impl TestState { InputsT::Error, ::Error, ReceivedNoteId, + PoolType, >, > where @@ -579,6 +582,7 @@ impl TestState { Infallible, FeeRuleT::Error, ReceivedNoteId, + PoolType, >, > where diff --git a/zcash_client_sqlite/src/wallet/sapling.rs b/zcash_client_sqlite/src/wallet/sapling.rs index 6bf84cf00..83fb3e065 100644 --- a/zcash_client_sqlite/src/wallet/sapling.rs +++ b/zcash_client_sqlite/src/wallet/sapling.rs @@ -465,7 +465,7 @@ pub(crate) mod tests { error::Error, wallet::input_selection::{GreedyInputSelector, GreedyInputSelectorError}, AccountBirthday, Ratio, ShieldedProtocol, WalletCommitmentTrees, WalletRead, - WalletWrite, + WalletWrite, PoolType, }, decrypt_transaction, fees::{fixed, zip317, DustOutputPolicy}, @@ -983,6 +983,7 @@ pub(crate) mod tests { GreedyInputSelectorError, Infallible, ReceivedNoteId, + PoolType, >, > { let txid = st.create_spend_to_address( From c4175342ace3549a4e8ae0bfc6a088c4621e85aa Mon Sep 17 00:00:00 2001 From: Matthew Watt Date: Mon, 9 Oct 2023 06:46:12 -0500 Subject: [PATCH 06/14] Cleanup --- zcash_client_backend/src/data_api/error.rs | 23 ++++++++++----------- zcash_client_backend/src/data_api/wallet.rs | 6 +----- zcash_client_sqlite/src/testing.rs | 6 +----- zcash_client_sqlite/src/wallet.rs | 2 +- zcash_client_sqlite/src/wallet/sapling.rs | 3 +-- 5 files changed, 15 insertions(+), 25 deletions(-) diff --git a/zcash_client_backend/src/data_api/error.rs b/zcash_client_backend/src/data_api/error.rs index 88357816f..fff7a730f 100644 --- a/zcash_client_backend/src/data_api/error.rs +++ b/zcash_client_backend/src/data_api/error.rs @@ -15,6 +15,7 @@ use zcash_primitives::{ zip32::AccountId, }; +use crate::data_api::PoolType; use crate::data_api::wallet::input_selection::InputSelectorError; #[cfg(feature = "transparent-inputs")] @@ -22,7 +23,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), @@ -68,14 +69,13 @@ 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 + N: fmt::Display { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match &self { @@ -134,14 +134,13 @@ 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 { @@ -154,19 +153,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), @@ -183,19 +182,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 f58fd0be2..ed8c3ec3c 100644 --- a/zcash_client_backend/src/data_api/wallet.rs +++ b/zcash_client_backend/src/data_api/wallet.rs @@ -207,7 +207,6 @@ pub fn create_spend_to_address( GreedyInputSelectorError, Infallible, DbT::NoteRef, - PoolType, >, > where @@ -311,7 +310,6 @@ pub fn spend( InputsT::Error, ::Error, DbT::NoteRef, - PoolType, >, > where @@ -366,7 +364,6 @@ pub fn propose_transfer( InputsT::Error, ::Error, DbT::NoteRef, - PoolType, >, > where @@ -450,7 +447,6 @@ pub fn create_proposed_transaction( InputsErrT, FeeRuleT::Error, DbT::NoteRef, - PoolType, >, > where @@ -496,7 +492,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, diff --git a/zcash_client_sqlite/src/testing.rs b/zcash_client_sqlite/src/testing.rs index 0a2db28e7..386543c10 100644 --- a/zcash_client_sqlite/src/testing.rs +++ b/zcash_client_sqlite/src/testing.rs @@ -15,7 +15,7 @@ use tempfile::NamedTempFile; use tempfile::TempDir; use zcash_client_backend::data_api::chain::ScanSummary; -use zcash_client_backend::data_api::{AccountBalance, WalletRead, PoolType}; +use zcash_client_backend::data_api::{AccountBalance, WalletRead}; #[allow(deprecated)] use zcash_client_backend::{ address::RecipientAddress, @@ -446,7 +446,6 @@ impl TestState { GreedyInputSelectorError, Infallible, ReceivedNoteId, - PoolType, >, > { let params = self.network(); @@ -480,7 +479,6 @@ impl TestState { InputsT::Error, ::Error, ReceivedNoteId, - PoolType, >, > where @@ -515,7 +513,6 @@ impl TestState { InputsT::Error, ::Error, ReceivedNoteId, - PoolType, >, > where @@ -582,7 +579,6 @@ impl TestState { Infallible, FeeRuleT::Error, ReceivedNoteId, - PoolType, >, > where diff --git a/zcash_client_sqlite/src/wallet.rs b/zcash_client_sqlite/src/wallet.rs index 41ea48e0f..524d3431a 100644 --- a/zcash_client_sqlite/src/wallet.rs +++ b/zcash_client_sqlite/src/wallet.rs @@ -136,7 +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 + PoolType::Shielded(ShieldedProtocol::Orchard) => 3i64 } } diff --git a/zcash_client_sqlite/src/wallet/sapling.rs b/zcash_client_sqlite/src/wallet/sapling.rs index 83fb3e065..6bf84cf00 100644 --- a/zcash_client_sqlite/src/wallet/sapling.rs +++ b/zcash_client_sqlite/src/wallet/sapling.rs @@ -465,7 +465,7 @@ pub(crate) mod tests { error::Error, wallet::input_selection::{GreedyInputSelector, GreedyInputSelectorError}, AccountBirthday, Ratio, ShieldedProtocol, WalletCommitmentTrees, WalletRead, - WalletWrite, PoolType, + WalletWrite, }, decrypt_transaction, fees::{fixed, zip317, DustOutputPolicy}, @@ -983,7 +983,6 @@ pub(crate) mod tests { GreedyInputSelectorError, Infallible, ReceivedNoteId, - PoolType, >, > { let txid = st.create_spend_to_address( From a910fb86b6e2cd24e394731fe33d448c5eabb0d9 Mon Sep 17 00:00:00 2001 From: Matthew Watt Date: Mon, 9 Oct 2023 06:57:40 -0500 Subject: [PATCH 07/14] Revert unnecessary change --- zcash_client_backend/src/data_api/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zcash_client_backend/src/data_api/error.rs b/zcash_client_backend/src/data_api/error.rs index fff7a730f..be60adc20 100644 --- a/zcash_client_backend/src/data_api/error.rs +++ b/zcash_client_backend/src/data_api/error.rs @@ -75,7 +75,7 @@ where CE: fmt::Display, SE: fmt::Display, FE: fmt::Display, - N: fmt::Display + N: fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match &self { From 4bbe658f74fc31b276bc41d8b3e9f6b12f3f8ee7 Mon Sep 17 00:00:00 2001 From: Matthew Watt <66689851+tw0po1nt@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:06:37 -0500 Subject: [PATCH 08/14] Update CHANGELOG.md Co-authored-by: Daira Emma Hopwood --- zcash_client_backend/CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zcash_client_backend/CHANGELOG.md b/zcash_client_backend/CHANGELOG.md index 0af57a371..e95e32e36 100644 --- a/zcash_client_backend/CHANGELOG.md +++ b/zcash_client_backend/CHANGELOG.md @@ -8,7 +8,9 @@ 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::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)` From 13a2d5d7d469225d69c7af6453effe4cd2453fbd Mon Sep 17 00:00:00 2001 From: Matthew Watt <66689851+tw0po1nt@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:07:31 -0500 Subject: [PATCH 09/14] Update wallet.rs Co-authored-by: Daira Emma Hopwood --- zcash_client_backend/src/data_api/wallet.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zcash_client_backend/src/data_api/wallet.rs b/zcash_client_backend/src/data_api/wallet.rs index ed8c3ec3c..587d616ad 100644 --- a/zcash_client_backend/src/data_api/wallet.rs +++ b/zcash_client_backend/src/data_api/wallet.rs @@ -426,8 +426,8 @@ where /// Returns the database identifier for the newly constructed transaction, or an error if /// an error occurs in transaction construction, proving, or signing. /// -/// Note: If the payment includes a recipient with an Orchard-only UA, this will attempt to fallback -/// to the transparent receiver until full Orchard support is implemented +/// Note: If the payment includes a recipient with an Orchard-only UA, this will attempt +/// to fall back to the transparent receiver until full Orchard support is implemented. #[allow(clippy::too_many_arguments)] #[allow(clippy::type_complexity)] pub fn create_proposed_transaction( From 5de3fbb36ba761e500f3160abeb3a48b8e48ccef Mon Sep 17 00:00:00 2001 From: Matthew Watt Date: Tue, 10 Oct 2023 06:35:04 -0500 Subject: [PATCH 10/14] Fix logic error --- zcash_client_backend/src/data_api/wallet.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zcash_client_backend/src/data_api/wallet.rs b/zcash_client_backend/src/data_api/wallet.rs index 587d616ad..13cd76783 100644 --- a/zcash_client_backend/src/data_api/wallet.rs +++ b/zcash_client_backend/src/data_api/wallet.rs @@ -557,6 +557,11 @@ where payment.amount, memo.clone(), )?; + sapling_output_meta.push(( + Recipient::Unified(ua.clone(), PoolType::Shielded(ShieldedProtocol::Sapling)), + payment.amount, + Some(memo), + )); } else if let Some(taddr) = ua.transparent() { if payment.memo.is_some() { return Err(Error::MemoForbidden); @@ -569,11 +574,6 @@ where } else { return Err(Error::UnsupportedPoolType(PoolType::Shielded(ShieldedProtocol::Orchard))); } - sapling_output_meta.push(( - Recipient::Unified(ua.clone(), PoolType::Shielded(ShieldedProtocol::Sapling)), - payment.amount, - Some(memo), - )); } RecipientAddress::Shielded(addr) => { let memo = payment From 0e5a58b0b04689ef5473976b7370dec523588349 Mon Sep 17 00:00:00 2001 From: Matthew Watt <66689851+tw0po1nt@users.noreply.github.com> Date: Tue, 10 Oct 2023 06:36:20 -0500 Subject: [PATCH 11/14] Update zcash_client_sqlite/src/wallet.rs Co-authored-by: Daira Emma Hopwood --- zcash_client_sqlite/src/wallet.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zcash_client_sqlite/src/wallet.rs b/zcash_client_sqlite/src/wallet.rs index 524d3431a..bee78f3d6 100644 --- a/zcash_client_sqlite/src/wallet.rs +++ b/zcash_client_sqlite/src/wallet.rs @@ -779,7 +779,7 @@ pub(crate) fn get_received_memo( ) .optional()? .flatten(), - ShieldedProtocol::Orchard => None + _ => return Err(SqliteClientError::UnsupportedPoolType(PoolType::Shielded(protocol))); }; memo_bytes From b548e00c107c00ba7c8d11b9566ad33faee65d24 Mon Sep 17 00:00:00 2001 From: Matthew Watt <66689851+tw0po1nt@users.noreply.github.com> Date: Tue, 10 Oct 2023 06:36:40 -0500 Subject: [PATCH 12/14] Update zcash_client_sqlite/src/wallet.rs Co-authored-by: Daira Emma Hopwood --- zcash_client_sqlite/src/wallet.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/zcash_client_sqlite/src/wallet.rs b/zcash_client_sqlite/src/wallet.rs index bee78f3d6..896d9fa6d 100644 --- a/zcash_client_sqlite/src/wallet.rs +++ b/zcash_client_sqlite/src/wallet.rs @@ -760,10 +760,6 @@ pub(crate) fn get_received_memo( note_id: NoteId, ) -> Result, SqliteClientError> { 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( From 2a4d9e06da233825aeb22e7617bde8f60df01dfa Mon Sep 17 00:00:00 2001 From: Matthew Watt Date: Tue, 10 Oct 2023 07:47:08 -0500 Subject: [PATCH 13/14] Run fmt --- zcash_client_backend/src/data_api.rs | 2 +- zcash_client_backend/src/data_api/error.rs | 2 +- zcash_client_backend/src/data_api/wallet.rs | 16 +++++++++------- zcash_client_sqlite/src/error.rs | 2 +- zcash_client_sqlite/src/wallet.rs | 8 ++++++-- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/zcash_client_backend/src/data_api.rs b/zcash_client_backend/src/data_api.rs index 7be3321c5..0291700d5 100644 --- a/zcash_client_backend/src/data_api.rs +++ b/zcash_client_backend/src/data_api.rs @@ -557,7 +557,7 @@ pub enum ShieldedProtocol { /// The Sapling protocol Sapling, /// The Orchard protocol - Orchard + 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 be60adc20..c6105ad87 100644 --- a/zcash_client_backend/src/data_api/error.rs +++ b/zcash_client_backend/src/data_api/error.rs @@ -15,8 +15,8 @@ use zcash_primitives::{ zip32::AccountId, }; -use crate::data_api::PoolType; use crate::data_api::wallet::input_selection::InputSelectorError; +use crate::data_api::PoolType; #[cfg(feature = "transparent-inputs")] use zcash_primitives::{legacy::TransparentAddress, zip32::DiversifierIndex}; diff --git a/zcash_client_backend/src/data_api/wallet.rs b/zcash_client_backend/src/data_api/wallet.rs index 13cd76783..6b64ab142 100644 --- a/zcash_client_backend/src/data_api/wallet.rs +++ b/zcash_client_backend/src/data_api/wallet.rs @@ -425,7 +425,7 @@ where /// /// Returns the database identifier for the newly constructed transaction, or an error if /// an error occurs in transaction construction, proving, or signing. -/// +/// /// Note: If the payment includes a recipient with an Orchard-only UA, this will attempt /// to fall back to the transparent receiver until full Orchard support is implemented. #[allow(clippy::too_many_arguments)] @@ -558,7 +558,10 @@ where memo.clone(), )?; sapling_output_meta.push(( - Recipient::Unified(ua.clone(), PoolType::Shielded(ShieldedProtocol::Sapling)), + Recipient::Unified( + ua.clone(), + PoolType::Shielded(ShieldedProtocol::Sapling), + ), payment.amount, Some(memo), )); @@ -566,13 +569,12 @@ where if payment.memo.is_some() { return Err(Error::MemoForbidden); } else { - builder.add_transparent_output( - taddr, - payment.amount - )?; + builder.add_transparent_output(taddr, payment.amount)?; } } else { - return Err(Error::UnsupportedPoolType(PoolType::Shielded(ShieldedProtocol::Orchard))); + return Err(Error::UnsupportedPoolType(PoolType::Shielded( + ShieldedProtocol::Orchard, + ))); } } RecipientAddress::Shielded(addr) => { diff --git a/zcash_client_sqlite/src/error.rs b/zcash_client_sqlite/src/error.rs index 4d9977d76..82104d285 100644 --- a/zcash_client_sqlite/src/error.rs +++ b/zcash_client_sqlite/src/error.rs @@ -101,7 +101,7 @@ pub enum SqliteClientError { ChainHeightUnknown, /// Unsupported pool type - UnsupportedPoolType(PoolType) + UnsupportedPoolType(PoolType), } impl error::Error for SqliteClientError { diff --git a/zcash_client_sqlite/src/wallet.rs b/zcash_client_sqlite/src/wallet.rs index 896d9fa6d..35d9c0a84 100644 --- a/zcash_client_sqlite/src/wallet.rs +++ b/zcash_client_sqlite/src/wallet.rs @@ -136,7 +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) => 3i64 + PoolType::Shielded(ShieldedProtocol::Orchard) => 3i64, } } @@ -775,7 +775,11 @@ pub(crate) fn get_received_memo( ) .optional()? .flatten(), - _ => return Err(SqliteClientError::UnsupportedPoolType(PoolType::Shielded(protocol))); + _ => { + return Err(SqliteClientError::UnsupportedPoolType(PoolType::Shielded( + protocol, + ))) + } }; memo_bytes From 73f263682ec2715da3804bb134aab68cdc5f63ca Mon Sep 17 00:00:00 2001 From: Matthew Watt Date: Tue, 10 Oct 2023 07:50:07 -0500 Subject: [PATCH 14/14] Remove unnecessary local --- zcash_client_sqlite/src/wallet.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/zcash_client_sqlite/src/wallet.rs b/zcash_client_sqlite/src/wallet.rs index 35d9c0a84..01ec36faa 100644 --- a/zcash_client_sqlite/src/wallet.rs +++ b/zcash_client_sqlite/src/wallet.rs @@ -759,8 +759,7 @@ pub(crate) fn get_received_memo( conn: &rusqlite::Connection, note_id: NoteId, ) -> Result, SqliteClientError> { - let protocol = note_id.protocol(); - let memo_bytes: Option> = match protocol { + let memo_bytes: Option> = match note_id.protocol() { ShieldedProtocol::Sapling => conn .query_row( "SELECT memo FROM sapling_received_notes @@ -777,7 +776,7 @@ pub(crate) fn get_received_memo( .flatten(), _ => { return Err(SqliteClientError::UnsupportedPoolType(PoolType::Shielded( - protocol, + note_id.protocol(), ))) } };