diff --git a/Cargo.lock b/Cargo.lock index bb3382b93b..7a53ff25e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,47 +64,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -112,9 +113,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" [[package]] name = "append-only-vec" @@ -158,7 +159,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -169,14 +170,14 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" @@ -460,9 +461,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.95" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" [[package]] name = "cfg-if" @@ -557,9 +558,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "concat-idents" @@ -568,7 +569,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d" dependencies = [ "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -1049,7 +1050,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -1094,9 +1095,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -1575,6 +1576,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.10.5" @@ -1648,9 +1655,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.153" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "libm" @@ -1889,11 +1896,10 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -1915,9 +1921,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -1977,7 +1983,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -2150,7 +2156,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -2205,12 +2211,12 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac2cf0f2e4f42b49f5ffd07dae8d746508ef7526c13940e5f524012ae6c6550" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -2239,9 +2245,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -2293,7 +2299,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.60", + "syn 2.0.61", "tempfile", ] @@ -2307,7 +2313,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -2662,7 +2668,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.60", + "syn 2.0.61", "walkdir", ] @@ -2678,9 +2684,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" @@ -2761,9 +2767,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.5.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" @@ -2777,9 +2783,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" +checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0" [[package]] name = "rusty-fork" @@ -2818,9 +2824,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -2917,11 +2923,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -2930,9 +2936,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -2940,15 +2946,15 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.199" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" dependencies = [ "serde_derive", ] @@ -2965,13 +2971,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.199" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -3166,9 +3172,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" dependencies = [ "proc-macro2", "quote", @@ -3248,7 +3254,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -3259,28 +3265,28 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", "test-case-core", ] [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -3374,7 +3380,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -3421,16 +3427,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes 1.6.0", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -3475,7 +3480,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -3548,7 +3553,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -3812,7 +3817,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", "wasm-bindgen-shared", ] @@ -3846,7 +3851,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4317,7 +4322,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] diff --git a/zingolib/src/blaze/block_management_reorg_detection.rs b/zingolib/src/blaze/block_management_reorg_detection.rs index 2b700eb861..bd15aca0bf 100644 --- a/zingolib/src/blaze/block_management_reorg_detection.rs +++ b/zingolib/src/blaze/block_management_reorg_detection.rs @@ -841,7 +841,9 @@ mod tests { .handle_reorgs_and_populate_block_mangement_data( start_block, end_block, - Arc::new(RwLock::new(TxMapAndMaybeTrees::new_with_witness_trees())), + Arc::new(RwLock::new( + TxMapAndMaybeTrees::new_with_witness_trees_address_free(), + )), reorg_transmitter, ) .await; @@ -890,7 +892,9 @@ mod tests { .handle_reorgs_and_populate_block_mangement_data( start_block, end_block, - Arc::new(RwLock::new(TxMapAndMaybeTrees::new_with_witness_trees())), + Arc::new(RwLock::new( + TxMapAndMaybeTrees::new_with_witness_trees_address_free(), + )), reorg_transmitter, ) .await; @@ -986,7 +990,9 @@ mod tests { .handle_reorgs_and_populate_block_mangement_data( start_block, end_block, - Arc::new(RwLock::new(TxMapAndMaybeTrees::new_with_witness_trees())), + Arc::new(RwLock::new( + TxMapAndMaybeTrees::new_with_witness_trees_address_free(), + )), reorg_transmitter, ) .await; diff --git a/zingolib/src/lightclient/propose.rs b/zingolib/src/lightclient/propose.rs index 5ca5b32191..75d28fd7da 100644 --- a/zingolib/src/lightclient/propose.rs +++ b/zingolib/src/lightclient/propose.rs @@ -170,33 +170,20 @@ impl LightClient { ) .map_err(DoProposeError::Proposal)?; - let mut latest_proposal_lock = self.latest_proposal.write().await; - *latest_proposal_lock = Some(crate::data::proposal::ZingoProposal::Transfer( - proposal.clone(), - )); + self.update_latest_proposal(ZingoProposal::Transfer(proposal.clone())) + .await; Ok(proposal) } fn get_transparent_addresses( &self, ) -> Result, DoProposeError> { - let secp = secp256k1::Secp256k1::new(); Ok(self .wallet .wallet_capability() - .transparent_child_keys() - .map_err(|_e| { - DoProposeError::ShieldProposal( - zcash_client_backend::data_api::error::Error::DataSource( - TxMapAndMaybeTreesTraitError::NoSpendCapability, - ), - ) - })? + .transparent_child_addresses() .iter() - .map(|(_index, sk)| { - #[allow(deprecated)] - zcash_primitives::legacy::keys::pubkey_to_address(&sk.public_key(&secp)) - }) + .map(|(_index, sk)| *sk) .collect::>()) } /// The shield operation consumes a proposal that transfers value @@ -239,16 +226,15 @@ impl LightClient { &input_selector, // don't shield dust NonNegativeAmount::const_from_u64(10_000), - &self.get_transparent_addresses()?, + &dbg!(self.get_transparent_addresses()?), // review! do we want to require confirmations? // make it configurable? 0, ) .map_err(DoProposeError::ShieldProposal)?; - *self.latest_proposal.write().await = Some(crate::data::proposal::ZingoProposal::Shield( - proposed_shield.clone(), - )); + self.update_latest_proposal(ZingoProposal::Shield(proposed_shield.clone())) + .await; Ok(proposed_shield) } /// A helper method that standardizes latest_proposal update diff --git a/zingolib/src/lightclient/send.rs b/zingolib/src/lightclient/send.rs index 3dd0610242..fe3e16004c 100644 --- a/zingolib/src/lightclient/send.rs +++ b/zingolib/src/lightclient/send.rs @@ -1,13 +1,7 @@ //! TODO: Add Mod Description Here! -use std::ops::DerefMut; use nonempty::NonEmpty; -use sapling_crypto::prover::OutputProver; -use sapling_crypto::prover::SpendProver; - -use zcash_keys::keys::UnifiedSpendingKey; - use zcash_client_backend::{proposal::Proposal, zip321::TransactionRequest}; use zcash_primitives::{consensus::BlockHeight, transaction::TxId}; use zcash_proofs::prover::LocalTxProver; @@ -33,38 +27,57 @@ impl LightClient { }) } - async fn iterate_proposal_send_scan( + async fn update_tmamt_and_return_step_result( + &self, + proposal: &Proposal, + step: zcash_client_backend::proposal::Step, + step_results: &[( + &zcash_client_backend::proposal::Step, + zcash_primitives::transaction::builder::BuildResult, + )], + ) -> Result { + let fee_rule = proposal.fee_rule(); + let min_target_height = proposal.min_target_height(); + let unified_spend_key = zcash_keys::keys::UnifiedSpendingKey::try_from( + self.wallet.wallet_capability().as_ref(), + ) + .map_err(DoSendProposedError::UnifiedSpendKey)?; + let (sapling_output, sapling_spend) = self + .read_sapling_params() + .map_err(DoSendProposedError::SaplingParams)?; + let sapling_prover = LocalTxProver::from_bytes(&sapling_spend, &sapling_output); + zcash_client_backend::data_api::wallet::calculate_proposed_transaction( + std::ops::DerefMut::deref_mut( + &mut self + .wallet + .transaction_context + .transaction_metadata_set + .write() + .await, + ), + &self.wallet.transaction_context.config.chain, + &sapling_prover, + &sapling_prover, + &unified_spend_key, + zcash_client_backend::wallet::OvkPolicy::Sender, + fee_rule, + min_target_height, + step_results, + &step, + ) + .map_err(DoSendProposedError::Calculation) + } + async fn iterate_proposal_send_scan( &self, proposal: &Proposal, - sapling_prover: &(impl SpendProver + OutputProver), - unified_spend_key: &UnifiedSpendingKey, submission_height: BlockHeight, ) -> Result, DoSendProposedError> { let mut step_results = Vec::with_capacity(proposal.steps().len()); let mut txids = Vec::with_capacity(proposal.steps().len()); for step in proposal.steps() { - let step_result = { - let mut tmamt = self - .wallet - .transaction_context - .transaction_metadata_set - .write() - .await; - - zcash_client_backend::data_api::wallet::calculate_proposed_transaction( - tmamt.deref_mut(), - &self.wallet.transaction_context.config.chain, - sapling_prover, - sapling_prover, - unified_spend_key, - zcash_client_backend::wallet::OvkPolicy::Sender, - proposal.fee_rule(), - proposal.min_target_height(), - &step_results, - step, - ) - .map_err(DoSendProposedError::Calculation)? - }; + let step_result = self + .update_tmamt_and_return_step_result(proposal, step.clone(), &step_results) + .await?; let txid = self .wallet @@ -108,32 +121,14 @@ impl LightClient { .await .map_err(DoSendProposedError::SubmissionHeight)?; - let (sapling_output, sapling_spend) = self - .read_sapling_params() - .map_err(DoSendProposedError::SaplingParams)?; - let sapling_prover = LocalTxProver::from_bytes(&sapling_spend, &sapling_output); - let unified_spend_key = - UnifiedSpendingKey::try_from(self.wallet.wallet_capability().as_ref()) - .map_err(DoSendProposedError::UnifiedSpendKey)?; - match proposal { crate::lightclient::ZingoProposal::Transfer(transfer_proposal) => { - self.iterate_proposal_send_scan( - transfer_proposal, - &sapling_prover, - &unified_spend_key, - submission_height, - ) - .await + self.iterate_proposal_send_scan(transfer_proposal, submission_height) + .await } crate::lightclient::ZingoProposal::Shield(shield_proposal) => { - self.iterate_proposal_send_scan( - shield_proposal, - &sapling_prover, - &unified_spend_key, - submission_height, - ) - .await + self.iterate_proposal_send_scan(shield_proposal, submission_height) + .await } } } else { @@ -163,10 +158,13 @@ mod test { use zingo_testvectors::seeds::HOSPITAL_MUSEUM_SEED; use zingoconfig::ZingoConfigBuilder; - use crate::{lightclient::LightClient, test_framework::mocks::ProposalBuilder}; + use crate::{ + lightclient::{send::DoSendProposedError, LightClient}, + test_framework::mocks::{ProposalBuilder, StepBuilder}, + }; #[tokio::test] - async fn update_tmamt_and_return_step_result() { + async fn update_tmamt_and_return_step_result_no_receipts() { let config = ZingoConfigBuilder::default().create(); let client = LightClient::create_unconnected( &config, @@ -175,12 +173,39 @@ mod test { ) .await .expect("A client!"); - let proposal = ProposalBuilder::new().build(); - let step = zcash_client_backend::proposal::Step::from_parts(); + let proposal = ProposalBuilder::default().build(); + let step = StepBuilder::default().build(); + let step_results: Vec<( + &zcash_client_backend::proposal::Step, + zcash_primitives::transaction::builder::BuildResult, + )> = vec![]; let step_result = client - .update_tmamt_and_return_step_result(&proposal, step, step_results) + .update_tmamt_and_return_step_result(&proposal, step, &step_results) .await; + dbg!(&step_result); + if let Err(DoSendProposedError::Calculation(e)) = step_result { + if let zcash_client_backend::data_api::error::Error::CommitmentTree(e2) = e { + if let shardtree::error::ShardTreeError::Query(e3) = e2 { + assert_eq!(e3, shardtree::error::QueryError::CheckpointPruned); + } else { + panic!("Wrong Error in layer 3."); + }; + } else { + panic!("Wrong zcash_api error!"); + } + } else { + panic!("Wrong state!"); + } } + /* + match step_result { + Err(DoSendProposedError::Calculation(e)) => { + match e { + zcash_client_backend::data_api::error::Error::CommitmentTree(e) + } + } + _ => panic!(), + */ } /// Errors that can result from do_send_proposed @@ -216,6 +241,6 @@ pub enum DoSendProposedError { pub enum DoQuickSendProposedError { #[error("propose {0}")] Propose(crate::lightclient::propose::DoProposeError), - #[error("No proposal. Call do_propose first.")] + #[error("Can't QuickSend! No proposal. Call do_propose first.")] Send(DoSendProposedError), } diff --git a/zingolib/src/wallet.rs b/zingolib/src/wallet.rs index a5533419f8..ec39b3f62f 100644 --- a/zingolib/src/wallet.rs +++ b/zingolib/src/wallet.rs @@ -370,9 +370,13 @@ impl LightWallet { )); }; let transaction_metadata_set = if wc.can_spend_from_all_pools() { - Arc::new(RwLock::new(TxMapAndMaybeTrees::new_with_witness_trees())) + Arc::new(RwLock::new(TxMapAndMaybeTrees::new_with_witness_trees( + wc.transparent_child_addresses().clone(), + ))) } else { - Arc::new(RwLock::new(TxMapAndMaybeTrees::new_treeless())) + Arc::new(RwLock::new(TxMapAndMaybeTrees::new_treeless( + wc.transparent_child_addresses().clone(), + ))) }; let transaction_context = TransactionContext::new(&config, Arc::new(wc), transaction_metadata_set); diff --git a/zingolib/src/wallet/keys/extended_transparent.rs b/zingolib/src/wallet/keys/extended_transparent.rs index 30cb1cf2b8..3f04e14e46 100644 --- a/zingolib/src/wallet/keys/extended_transparent.rs +++ b/zingolib/src/wallet/keys/extended_transparent.rs @@ -48,18 +48,18 @@ impl KeyIndex { } /// Generate KeyIndex from raw index value. - pub fn from_index(i: u32) -> Result { + pub fn from_index(i: u32) -> Self { if i < HARDENED_KEY_START_INDEX { - Ok(KeyIndex::Normal(i)) + KeyIndex::Normal(i) } else { - Ok(KeyIndex::Hardened(i)) + KeyIndex::Hardened(i) } } } impl From for KeyIndex { fn from(index: u32) -> Self { - KeyIndex::from_index(index).expect("KeyIndex") + KeyIndex::from_index(index) } } @@ -278,7 +278,7 @@ fn test_commutativity_of_key_derivation_mechanisms() { // pk ---> pk_i // initial key derivation material - let i = KeyIndex::from_index(42).unwrap(); + let i = KeyIndex::from_index(42); let sk = ExtendedPrivKey::with_seed(&[0xcd; 64]).unwrap(); // sk -> sk_i -> pk_i derivation diff --git a/zingolib/src/wallet/keys/unified.rs b/zingolib/src/wallet/keys/unified.rs index 6cb12737e0..2cee300b97 100644 --- a/zingolib/src/wallet/keys/unified.rs +++ b/zingolib/src/wallet/keys/unified.rs @@ -1,11 +1,11 @@ //! TODO: Add Mod Discription Here! -use std::marker::PhantomData; use std::sync::atomic; use std::{ collections::{HashMap, HashSet}, io::{self, Read, Write}, sync::atomic::AtomicBool, }; +use std::{marker::PhantomData, sync::Arc}; use append_only_vec::AppendOnlyVec; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; @@ -83,7 +83,7 @@ pub struct WalletCapability { /// TODO: Add Doc Comment Here! pub orchard: Capability, - transparent_child_keys: append_only_vec::AppendOnlyVec<(usize, secp256k1::SecretKey)>, + transparent_child_addresses: Arc>, addresses: append_only_vec::AppendOnlyVec, // Not all diversifier indexes produce valid sapling addresses. // Because of this, the index isn't necessarily equal to addresses.len() @@ -95,7 +95,7 @@ impl Default for WalletCapability { orchard: Capability::None, sapling: Capability::None, transparent: Capability::None, - transparent_child_keys: AppendOnlyVec::new(), + transparent_child_addresses: Arc::new(AppendOnlyVec::new()), addresses: AppendOnlyVec::new(), addresses_write_lock: AtomicBool::new(false), } @@ -174,14 +174,8 @@ impl WalletCapability { } /// TODO: Add Doc Comment Here! - pub fn transparent_child_keys( - &self, - ) -> Result<&AppendOnlyVec<(usize, secp256k1::SecretKey)>, String> { - if self.transparent.can_spend() { - Ok(&self.transparent_child_keys) - } else { - Err("The wallet is not capable of spending transparent funds.".to_string()) - } + pub fn transparent_child_addresses(&self) -> &Arc> { + &self.transparent_child_addresses } /// TODO: Add Doc Comment Here! @@ -261,35 +255,43 @@ impl WalletCapability { }; let transparent_receiver = if desired_receivers.transparent { - let child_index = KeyIndex::from_index(self.addresses.len() as u32).unwrap(); - match &self.transparent { + let child_index = KeyIndex::from_index(self.addresses.len() as u32); + let child_pk = match &self.transparent { Capability::Spend(ext_sk) => { - let child_sk = match ext_sk.derive_private_key(child_index) { - Err(e) => { - self.addresses_write_lock - .swap(false, atomic::Ordering::Release); - return Err(format!("Transparent private key derivation failed: {e}")); - } - Ok(res) => res.private_key, - }; let secp = secp256k1::Secp256k1::new(); - let child_pk = secp256k1::PublicKey::from_secret_key(&secp, &child_sk); - self.transparent_child_keys - .push((self.addresses.len(), child_sk)); - Some(child_pk) - } - Capability::View(ext_pk) => { - let child_pk = match ext_pk.derive_public_key(child_index) { - Err(e) => { - self.addresses_write_lock - .swap(false, atomic::Ordering::Release); - return Err(format!("Transparent public key derivation failed: {e}")); + Some( + match ext_sk.derive_private_key(child_index) { + Err(e) => { + self.addresses_write_lock + .swap(false, atomic::Ordering::Release); + return Err(format!( + "Transparent private key derivation failed: {e}" + )); + } + Ok(res) => res.private_key, } - Ok(res) => res.public_key, - }; - Some(child_pk) + .public_key(&secp), + ) } + Capability::View(ext_pk) => Some(match ext_pk.derive_public_key(child_index) { + Err(e) => { + self.addresses_write_lock + .swap(false, atomic::Ordering::Release); + return Err(format!("Transparent public key derivation failed: {e}")); + } + Ok(res) => res.public_key, + }), Capability::None => None, + }; + if let Some(pk) = child_pk { + self.transparent_child_addresses.push(( + self.addresses.len(), + #[allow(deprecated)] + zcash_primitives::legacy::keys::pubkey_to_address(&pk), + )); + Some(pk) + } else { + None } } else { None @@ -328,29 +330,23 @@ impl WalletCapability { &self, config: &ZingoConfig, ) -> Result, String> { - if self.transparent.can_spend() { - Ok(self - .addresses + if let Capability::Spend(transparent_sk) = &self.transparent { + self.transparent_child_addresses() .iter() - .enumerate() - .filter_map(|(i, ua)| { - ua.transparent().zip( - self.transparent_child_keys - .iter() - .find(|(index, _key)| i == *index), - ) - }) - .map(|(taddr, key)| { + .map(|(i, taddr)| -> Result<_, String> { let hash = match taddr { TransparentAddress::PublicKeyHash(hash) => hash, TransparentAddress::ScriptHash(hash) => hash, }; - ( + Ok(( hash.to_base58check(&config.chain.b58_pubkey_address_prefix(), &[]), - key.1, - ) + transparent_sk + .derive_private_key(KeyIndex::Normal(*i as u32)) + .map_err(|e| e.to_string())? + .private_key, + )) }) - .collect()) + .collect::>() } else { Err("Wallet is no capable to spend transparent funds".to_string()) } @@ -864,11 +860,14 @@ pub async fn get_transparent_secretkey_pubkey_taddr( let child_ext_pk = ext_pk.derive_public_key(KeyIndex::Normal(0)).ok(); (None, child_ext_pk.map(|x| x.public_key)) } - Capability::Spend(_) => { - let sk = wc.transparent_child_keys[0].1; + Capability::Spend(master_sk) => { let secp = secp256k1::Secp256k1::new(); - let pk = secp256k1::PublicKey::from_secret_key(&secp, &sk); - (Some(sk), Some(pk)) + let extsk = master_sk + .derive_private_key(KeyIndex::Normal(wc.transparent_child_addresses[0].0 as u32)) + .unwrap(); + let pk = extsk.private_key.public_key(&secp); + #[allow(deprecated)] + (Some(extsk.private_key), Some(pk)) } }; let taddr = wc.addresses()[0] diff --git a/zingolib/src/wallet/tx_map_and_maybe_trees.rs b/zingolib/src/wallet/tx_map_and_maybe_trees.rs index 2ee7b607eb..d5e58ffdc3 100644 --- a/zingolib/src/wallet/tx_map_and_maybe_trees.rs +++ b/zingolib/src/wallet/tx_map_and_maybe_trees.rs @@ -4,8 +4,14 @@ //! associated types for TxMapAndMaybeTrees that have no relevance elsewhere. use crate::{ - data::witness_trees::WitnessTrees, wallet::transaction_records_by_id::TransactionRecordsById, + data::witness_trees::WitnessTrees, + wallet::transaction_records_by_id::{ + trait_inputsource::InputSourceError, TransactionRecordsById, + }, }; +use std::{fmt::Debug, sync::Arc}; +use thiserror::Error; +use zcash_primitives::legacy::TransparentAddress; /// HashMap of all transactions in a wallet, keyed by txid. /// Note that the parent is expected to hold a RwLock, so we will assume that all accesses to @@ -13,6 +19,8 @@ use crate::{ pub struct TxMapAndMaybeTrees { pub transaction_records_by_id: TransactionRecordsById, witness_trees: Option, + pub(crate) transparent_child_addresses: + Arc>, } pub mod get; @@ -20,16 +28,26 @@ pub mod read_write; pub mod recording; impl TxMapAndMaybeTrees { - pub(crate) fn new_with_witness_trees() -> TxMapAndMaybeTrees { + pub(crate) fn new_with_witness_trees( + transparent_child_addresses: Arc< + append_only_vec::AppendOnlyVec<(usize, TransparentAddress)>, + >, + ) -> TxMapAndMaybeTrees { Self { transaction_records_by_id: TransactionRecordsById::new(), witness_trees: Some(WitnessTrees::default()), + transparent_child_addresses, } } - pub(crate) fn new_treeless() -> TxMapAndMaybeTrees { + pub(crate) fn new_treeless( + transparent_child_addresses: Arc< + append_only_vec::AppendOnlyVec<(usize, TransparentAddress)>, + >, + ) -> TxMapAndMaybeTrees { Self { transaction_records_by_id: TransactionRecordsById::new(), witness_trees: None, + transparent_child_addresses, } } pub fn witness_trees(&self) -> Option<&WitnessTrees> { @@ -43,11 +61,25 @@ impl TxMapAndMaybeTrees { self.witness_trees.as_mut().map(WitnessTrees::clear); } } - -use std::fmt::Debug; -use thiserror::Error; - -use crate::wallet::transaction_records_by_id::trait_inputsource::InputSourceError; +#[cfg(test)] +impl TxMapAndMaybeTrees { + /// For any unit tests that don't require a WalletCapability, where the addresses come from + pub(crate) fn new_with_witness_trees_address_free() -> TxMapAndMaybeTrees { + Self { + transaction_records_by_id: TransactionRecordsById::new(), + witness_trees: Some(WitnessTrees::default()), + transparent_child_addresses: Arc::new(append_only_vec::AppendOnlyVec::new()), + } + } + /// For any unit tests that don't require a WalletCapability, where the addresses come from + pub(crate) fn new_with_treeless_address_free() -> TxMapAndMaybeTrees { + Self { + transaction_records_by_id: TransactionRecordsById::new(), + witness_trees: None, + transparent_child_addresses: Arc::new(append_only_vec::AppendOnlyVec::new()), + } + } +} #[derive(Debug, PartialEq, Error)] pub enum TxMapAndMaybeTreesTraitError { diff --git a/zingolib/src/wallet/tx_map_and_maybe_trees/get.rs b/zingolib/src/wallet/tx_map_and_maybe_trees/get.rs index c3c3685adc..30a04856bb 100644 --- a/zingolib/src/wallet/tx_map_and_maybe_trees/get.rs +++ b/zingolib/src/wallet/tx_map_and_maybe_trees/get.rs @@ -136,7 +136,7 @@ impl TxMapAndMaybeTrees { #[test] fn test_get_some_txid_from_highest_wallet_block() { - let mut tms = TxMapAndMaybeTrees::new_treeless(); + let mut tms = TxMapAndMaybeTrees::new_with_treeless_address_free(); assert_eq!(tms.get_some_txid_from_highest_wallet_block(), None); let txid_bytes_1 = [0u8; 32]; let txid_bytes_2 = [1u8; 32]; diff --git a/zingolib/src/wallet/tx_map_and_maybe_trees/read_write.rs b/zingolib/src/wallet/tx_map_and_maybe_trees/read_write.rs index 2b333223ce..131cc06d38 100644 --- a/zingolib/src/wallet/tx_map_and_maybe_trees/read_write.rs +++ b/zingolib/src/wallet/tx_map_and_maybe_trees/read_write.rs @@ -67,6 +67,7 @@ impl TxMapAndMaybeTrees { Ok(Self { transaction_records_by_id: map, witness_trees, + transparent_child_addresses: wallet_capability.transparent_child_addresses().clone(), }) } @@ -132,6 +133,7 @@ impl TxMapAndMaybeTrees { Ok(Self { transaction_records_by_id: TransactionRecordsById::from_map(map), witness_trees, + transparent_child_addresses: wallet_capability.transparent_child_addresses().clone(), }) } @@ -167,7 +169,7 @@ mod tests { #[tokio::test] async fn test_write() { - let mut tms = TxMapAndMaybeTrees::new_with_witness_trees(); + let mut tms = TxMapAndMaybeTrees::new_with_witness_trees_address_free(); let mut buffer = Cursor::new(Vec::new()); // Perform the write operation diff --git a/zingolib/src/wallet/tx_map_and_maybe_trees/trait_walletread.rs b/zingolib/src/wallet/tx_map_and_maybe_trees/trait_walletread.rs index 28737dc304..1f944b6f98 100644 --- a/zingolib/src/wallet/tx_map_and_maybe_trees/trait_walletread.rs +++ b/zingolib/src/wallet/tx_map_and_maybe_trees/trait_walletread.rs @@ -5,9 +5,13 @@ use shardtree::store::ShardStore; use zcash_client_backend::{ data_api::{Account, WalletRead}, keys::UnifiedFullViewingKey, + wallet::TransparentAddressMetadata, }; -use zcash_primitives::consensus::BlockHeight; -use zip32::AccountId; +use zcash_primitives::{ + consensus::BlockHeight, + legacy::keys::{NonHardenedChildIndex, TransparentKeyScope}, +}; +use zip32::{AccountId, Scope}; use crate::wallet::notes::query::QueryStipulations; @@ -282,6 +286,47 @@ impl WalletRead for TxMapAndMaybeTrees { ) -> Result, Self::Error> { unimplemented!() } + + fn get_transparent_receivers( + &self, + _account: Self::AccountId, + ) -> Result< + std::collections::HashMap< + zcash_primitives::legacy::TransparentAddress, + Option, + >, + Self::Error, + > { + Ok(self + .transparent_child_addresses + .iter() + .map(|(index, taddr)| { + ( + *taddr, + NonHardenedChildIndex::from_index(*index as u32).map(|nhc_index| { + TransparentAddressMetadata::new( + TransparentKeyScope::from(Scope::External), + nhc_index, + ) + }), + ) + }) + .collect()) + } + + fn get_transparent_balances( + &self, + _account: Self::AccountId, + _max_height: BlockHeight, + ) -> Result< + std::collections::HashMap< + zcash_primitives::legacy::TransparentAddress, + zcash_primitives::transaction::components::amount::NonNegativeAmount, + >, + Self::Error, + > { + Ok(std::collections::HashMap::new()) + } } #[cfg(test)] @@ -309,7 +354,8 @@ mod tests { #[test] fn get_target_and_anchor_heights() { - let mut transaction_records_and_maybe_trees = TxMapAndMaybeTrees::new_with_witness_trees(); + let mut transaction_records_and_maybe_trees = + TxMapAndMaybeTrees::new_with_witness_trees_address_free(); transaction_records_and_maybe_trees .witness_trees .as_mut() @@ -327,7 +373,8 @@ mod tests { #[test] fn get_target_and_anchor_heights_none() { - let transaction_records_and_maybe_trees = TxMapAndMaybeTrees::new_with_witness_trees(); + let transaction_records_and_maybe_trees = + TxMapAndMaybeTrees::new_with_witness_trees_address_free(); assert_eq!( transaction_records_and_maybe_trees .get_target_and_anchor_heights(NonZeroU32::new(10).unwrap()) @@ -338,7 +385,8 @@ mod tests { #[test] fn get_target_and_anchor_heights_err() { - let transaction_records_and_maybe_trees = TxMapAndMaybeTrees::new_treeless(); + let transaction_records_and_maybe_trees = + TxMapAndMaybeTrees::new_with_treeless_address_free(); assert_eq!( transaction_records_and_maybe_trees .get_target_and_anchor_heights(NonZeroU32::new(10).unwrap()) @@ -351,7 +399,7 @@ mod tests { proptest! { #[test] fn get_min_unspent_height(sapling_height: u32, orchard_height: u32) { - let mut transaction_records_and_maybe_trees = TxMapAndMaybeTrees::new_with_witness_trees(); + let mut transaction_records_and_maybe_trees = TxMapAndMaybeTrees::new_with_witness_trees_address_free(); // these first three outputs will not trigger min_unspent_note transaction_records_and_maybe_trees @@ -412,7 +460,7 @@ mod tests { #[test] fn get_tx_height(tx_height: u32) { - let mut transaction_records_and_maybe_trees = TxMapAndMaybeTrees::new_with_witness_trees(); + let mut transaction_records_and_maybe_trees = TxMapAndMaybeTrees::new_with_witness_trees_address_free(); let transaction_record = TransactionRecordBuilder::default().randomize_txid().status(Confirmed(tx_height.into())) .clone()