diff --git a/Cargo.lock b/Cargo.lock index 1e0790f40f..8408ea5208 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1827,7 +1827,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.1.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?tag=k-1.4.1#e92443a7bbd1c5e92e00e6deb45b5a33af14cea4" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?branch=add-change-to-unspent#d78f4dfd7adaa259af8f37bb1803a7cad7ec6a1d" dependencies = [ "blake2b_simd", "byteorder", @@ -8235,7 +8235,7 @@ checksum = "0f9079049688da5871a7558ddacb7f04958862c703e68258594cb7a862b5e33f" [[package]] name = "zcash_client_backend" version = "0.5.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?tag=k-1.4.1#e92443a7bbd1c5e92e00e6deb45b5a33af14cea4" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?branch=add-change-to-unspent#d78f4dfd7adaa259af8f37bb1803a7cad7ec6a1d" dependencies = [ "async-trait", "base64 0.13.0", @@ -8260,7 +8260,7 @@ dependencies = [ [[package]] name = "zcash_client_sqlite" version = "0.3.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?tag=k-1.4.1#e92443a7bbd1c5e92e00e6deb45b5a33af14cea4" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?branch=add-change-to-unspent#d78f4dfd7adaa259af8f37bb1803a7cad7ec6a1d" dependencies = [ "async-trait", "bech32", @@ -8282,7 +8282,7 @@ dependencies = [ [[package]] name = "zcash_extras" version = "0.1.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?tag=k-1.4.1#e92443a7bbd1c5e92e00e6deb45b5a33af14cea4" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?branch=add-change-to-unspent#d78f4dfd7adaa259af8f37bb1803a7cad7ec6a1d" dependencies = [ "async-trait", "ff 0.8.0", @@ -8298,7 +8298,7 @@ dependencies = [ [[package]] name = "zcash_note_encryption" version = "0.0.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?tag=k-1.4.1#e92443a7bbd1c5e92e00e6deb45b5a33af14cea4" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?branch=add-change-to-unspent#d78f4dfd7adaa259af8f37bb1803a7cad7ec6a1d" dependencies = [ "blake2b_simd", "byteorder", @@ -8312,7 +8312,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.5.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?tag=k-1.4.1#e92443a7bbd1c5e92e00e6deb45b5a33af14cea4" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?branch=add-change-to-unspent#d78f4dfd7adaa259af8f37bb1803a7cad7ec6a1d" dependencies = [ "aes 0.8.3", "bitvec 0.18.5", @@ -8342,7 +8342,7 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.5.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?tag=k-1.4.1#e92443a7bbd1c5e92e00e6deb45b5a33af14cea4" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?branch=add-change-to-unspent#d78f4dfd7adaa259af8f37bb1803a7cad7ec6a1d" dependencies = [ "bellman", "blake2b_simd", diff --git a/mm2src/coins/Cargo.toml b/mm2src/coins/Cargo.toml index a706d9d22c..27b2bbc338 100644 --- a/mm2src/coins/Cargo.toml +++ b/mm2src/coins/Cargo.toml @@ -110,9 +110,9 @@ uuid = { version = "1.2.2", features = ["fast-rng", "serde", "v4"] } # We don't need the default web3 features at all since we added our own web3 transport using shared HYPER instance. web3 = { git = "https://github.com/KomodoPlatform/rust-web3", tag = "v0.20.0", default-features = false } zbase32 = "0.1.2" -zcash_client_backend = { git = "https://github.com/KomodoPlatform/librustzcash.git", tag = "k-1.4.1" } -zcash_extras = { git = "https://github.com/KomodoPlatform/librustzcash.git", tag = "k-1.4.1" } -zcash_primitives = {features = ["transparent-inputs"], git = "https://github.com/KomodoPlatform/librustzcash.git", tag = "k-1.4.1" } +zcash_client_backend = { git = "https://github.com/KomodoPlatform/librustzcash.git", branch = "add-change-to-unspent" } +zcash_extras = { git = "https://github.com/KomodoPlatform/librustzcash.git", branch = "add-change-to-unspent" } +zcash_primitives = {features = ["transparent-inputs"], git = "https://github.com/KomodoPlatform/librustzcash.git", branch = "add-change-to-unspent" } [target.'cfg(target_arch = "wasm32")'.dependencies] blake2b_simd = "0.5" @@ -131,7 +131,7 @@ wasm-bindgen = "0.2.86" wasm-bindgen-futures = { version = "0.4.1" } wasm-bindgen-test = { version = "0.3.2" } web-sys = { version = "0.3.55", features = ["console", "Headers", "Request", "RequestInit", "RequestMode", "Response", "Window"] } -zcash_proofs = { git = "https://github.com/KomodoPlatform/librustzcash.git", tag = "k-1.4.1", default-features = false, features = ["local-prover"] } +zcash_proofs = { git = "https://github.com/KomodoPlatform/librustzcash.git", branch = "add-change-to-unspent", default-features = false, features = ["local-prover"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] dirs = { version = "1" } @@ -152,8 +152,8 @@ tokio = { version = "1.20" } tokio-rustls = { version = "0.24" } tonic = { version = "0.10", features = ["tls", "tls-webpki-roots", "gzip"] } webpki-roots = { version = "0.25" } -zcash_client_sqlite = { git = "https://github.com/KomodoPlatform/librustzcash.git", tag = "k-1.4.1" } -zcash_proofs = { git = "https://github.com/KomodoPlatform/librustzcash.git", tag = "k-1.4.1", default-features = false, features = ["local-prover", "multicore"] } +zcash_client_sqlite = { git = "https://github.com/KomodoPlatform/librustzcash.git", branch = "add-change-to-unspent" } +zcash_proofs = { git = "https://github.com/KomodoPlatform/librustzcash.git", branch = "add-change-to-unspent", default-features = false, features = ["local-prover", "multicore"] } [target.'cfg(windows)'.dependencies] winapi = "0.3" diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index b8c7c8c944..8f52649a3d 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -93,6 +93,8 @@ use zcash_primitives::{constants::mainnet as z_mainnet_constants, sapling::Payme zip32::ExtendedFullViewingKey, zip32::ExtendedSpendingKey}; use zcash_proofs::prover::LocalTxProver; +use self::storage::store_change_output; + cfg_native!( use common::{async_blocking, sha256_digest}; use zcash_client_sqlite::error::SqliteClientError as ZcashClientError; @@ -208,8 +210,8 @@ pub struct ZCoinFields { z_tx_prover: Arc, light_wallet_db: WalletDbShared, consensus_params: ZcoinConsensusParams, - sync_state_connector: AsyncMutex, z_balance_event_handler: Option, + sync_state_connector: AsyncMutex, } impl Transaction for ZTransaction { @@ -474,6 +476,12 @@ impl ZCoin { .await? .tx_result?; + // Store any change outputs we created in this transaction by decrypting them with our keys + // and saving them to the wallet database for future spends + store_change_output(self.consensus_params_ref(), &self.z_fields.light_wallet_db, &tx) + .await + .map_to_mm(GenTxError::SaveChangeNotesError)?; + let additional_data = AdditionalTxData { received_by_me, spent_by_me: sat_from_big_decimal(&total_input_amount, self.decimals())?, diff --git a/mm2src/coins/z_coin/storage.rs b/mm2src/coins/z_coin/storage.rs index b3c2c108c4..8c29f81f33 100644 --- a/mm2src/coins/z_coin/storage.rs +++ b/mm2src/coins/z_coin/storage.rs @@ -9,6 +9,8 @@ pub mod walletdb; pub(crate) use z_params::ZcashParamsWasmImpl; pub use walletdb::*; +use zcash_extras::wallet::decrypt_and_store_transaction; +use zcash_primitives::transaction::Transaction; use crate::z_coin::z_balance_streaming::ZBalanceEventSender; use mm2_err_handle::mm_error::MmResult; @@ -190,3 +192,18 @@ pub async fn scan_cached_block( // If there are any transactions in the block, return the transaction count Ok(txs.len()) } + +/// Processes and stores any change outputs created in the transaction by: +/// - Decrypting outputs using wallet viewing keys +/// - Adding decrypted change notes to the wallet database +/// - Making change notes available for future spends +pub(crate) async fn store_change_output( + params: &ZcoinConsensusParams, + shared_db: &WalletDbShared, + tx: &Transaction, +) -> Result<(), String> { + let mut data = try_s!(shared_db.db.get_update_ops()); + try_s!(decrypt_and_store_transaction(params, &mut data, tx).await); + + Ok(()) +} diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index 7fcf06cb12..ac4aa8d295 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -129,8 +129,8 @@ pub enum GenTxError { LightClientErr(String), FailedToCreateNote, SpendableNotesError(String), - #[cfg(target_arch = "wasm32")] Internal(String), + SaveChangeNotesError(String), } impl From for GenTxError { @@ -177,9 +177,9 @@ impl From for WithdrawError { | GenTxError::BlockchainScanStopped | GenTxError::LightClientErr(_) | GenTxError::SpendableNotesError(_) - | GenTxError::FailedToCreateNote => WithdrawError::InternalError(gen_tx.to_string()), - #[cfg(target_arch = "wasm32")] - GenTxError::Internal(_) => WithdrawError::InternalError(gen_tx.to_string()), + | GenTxError::FailedToCreateNote + | GenTxError::Internal(_) + | GenTxError::SaveChangeNotesError(_) => WithdrawError::InternalError(gen_tx.to_string()), } } } diff --git a/mm2src/coins/z_coin/z_htlc.rs b/mm2src/coins/z_coin/z_htlc.rs index c2fba37a88..bd32389f51 100644 --- a/mm2src/coins/z_coin/z_htlc.rs +++ b/mm2src/coins/z_coin/z_htlc.rs @@ -5,6 +5,7 @@ // taker payment spend - https://zombie.explorer.lordofthechains.com/tx/af6bb0f99f9a5a070a0c1f53d69e4189b0e9b68f9d66e69f201a6b6d9f93897e // maker payment spend - https://rick.explorer.dexstats.info/tx/6a2dcc866ad75cebecb780a02320073a88bcf5e57ddccbe2657494e7747d591e +use super::storage::store_change_output; use super::{GenTxError, ZCoin}; use crate::utxo::rpc_clients::{UtxoRpcClientEnum, UtxoRpcError}; use crate::utxo::utxo_common::payment_script; @@ -190,6 +191,12 @@ pub async fn z_p2sh_spend( let mut tx_buffer = Vec::with_capacity(1024); zcash_tx.write(&mut tx_buffer)?; + // Store any change outputs we created in this transaction by decrypting them with our keys + // and saving them to the wallet database for future spends + store_change_output(coin.consensus_params_ref(), &coin.z_fields.light_wallet_db, &zcash_tx) + .await + .map_to_mm(|err| ZP2SHSpendError::GenTxError(GenTxError::SaveChangeNotesError(err)))?; + coin.utxo_rpc_client() .send_raw_transaction(tx_buffer.into()) .compat()