diff --git a/zcash_client_backend/src/data_api/wallet.rs b/zcash_client_backend/src/data_api/wallet.rs index 226fa85b7..4c1ab4312 100644 --- a/zcash_client_backend/src/data_api/wallet.rs +++ b/zcash_client_backend/src/data_api/wallet.rs @@ -10,9 +10,6 @@ use zcash_primitives::{ }, }; -#[cfg(feature = "transparent-inputs")] -use zcash_primitives::{legacy::keys::IncomingViewingKey, sapling::keys::OutgoingViewingKey}; - use crate::{ address::RecipientAddress, data_api::{ @@ -25,6 +22,9 @@ use crate::{ zip321::{Payment, TransactionRequest}, }; +#[cfg(feature = "transparent-inputs")] +use zcash_primitives::{legacy::keys::IncomingViewingKey, sapling::keys::OutgoingViewingKey}; + /// Scans a [`Transaction`] for any information that can be decrypted by the accounts in /// the wallet, and saves it to the wallet. pub fn decrypt_and_store_transaction( @@ -50,14 +50,10 @@ where .or_else(|| params.activation_height(NetworkUpgrade::Sapling)) .ok_or(Error::SaplingNotActive)?; - let sapling_outputs = decrypt_transaction(params, height, tx, &ufvks); - - if !(sapling_outputs.is_empty() && tx.transparent_bundle().iter().all(|b| b.vout.is_empty())) { - data.store_decrypted_tx(&DecryptedTransaction { - tx, - sapling_outputs: &sapling_outputs, - })?; - } + data.store_decrypted_tx(&DecryptedTransaction { + tx, + sapling_outputs: &decrypt_transaction(params, height, tx, &ufvks), + })?; Ok(()) } diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs index 21369bb95..afb75c73f 100644 --- a/zcash_client_sqlite/src/lib.rs +++ b/zcash_client_sqlite/src/lib.rs @@ -538,7 +538,6 @@ impl<'a, P: consensus::Parameters> WalletWrite for DataConnStmtCache<'a, P> { &mut self, d_tx: &DecryptedTransaction, ) -> Result { - let nullifiers = self.wallet_db.get_all_nullifiers()?; self.transactionally(|up| { let tx_ref = wallet::put_tx_data(up, d_tx.tx, None, None)?; @@ -579,8 +578,15 @@ impl<'a, P: consensus::Parameters> WalletWrite for DataConnStmtCache<'a, P> { } } + // If any of the utxos spent in the transaction are ours, mark them as spent. + #[cfg(feature = "transparent-inputs")] + for txin in d_tx.tx.transparent_bundle().iter().flat_map(|b| b.vin.iter()) { + wallet::mark_transparent_utxo_spent(up, tx_ref, &txin.prevout)?; + } + // If we have some transparent outputs: if !d_tx.tx.transparent_bundle().iter().any(|b| b.vout.is_empty()) { + let nullifiers = self.wallet_db.get_all_nullifiers()?; // If the transaction contains shielded spends from our wallet, we will store z->t // transactions we observe in the same way they would be stored by // create_spend_to_address.