From bbbff8cb8ea475fe1721d9bfba42263a6102e6ee Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 28 Sep 2023 11:02:30 +0100 Subject: [PATCH 01/68] save dev state Signed-off-by: borngraced --- Cargo.lock | 37 ++++++++++++++ mm2src/coins/Cargo.toml | 4 +- mm2src/coins/test_coin.rs | 4 +- mm2src/coins/z_coin/storage/blockdb/mod.rs | 17 +++++++ mm2src/coins/z_coin/z_rpc.rs | 59 +++++++++++++++++----- 5 files changed, 104 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0f31f911ec..0c6b4970d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1077,6 +1077,7 @@ dependencies = [ "tokio-rustls", "tonic", "tonic-build", + "tonic-web-wasm-client", "url", "utxo_signer", "uuid 1.2.2", @@ -8018,6 +8019,29 @@ dependencies = [ "syn 1.0.95", ] +[[package]] +name = "tonic-web-wasm-client" +version = "0.4.0" +source = "git+https://github.com/borngraced/tonic-web-wasm-client?rev=cd49d00#cd49d003b337e053878ab8070c63e0b77963a7c5" +dependencies = [ + "base64 0.21.2", + "byteorder 1.4.3", + "bytes 1.1.0", + "futures-util", + "http 0.2.7", + "http-body 0.4.5", + "httparse", + "js-sys", + "pin-project 1.0.10", + "thiserror", + "tonic", + "tower-service", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + [[package]] name = "tower" version = "0.4.13" @@ -8625,6 +8649,19 @@ dependencies = [ "quote 1.0.27", ] +[[package]] +name = "wasm-streams" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wasm-timer" version = "0.2.5" diff --git a/mm2src/coins/Cargo.toml b/mm2src/coins/Cargo.toml index 3934a467fd..d31e2d54d8 100644 --- a/mm2src/coins/Cargo.toml +++ b/mm2src/coins/Cargo.toml @@ -125,6 +125,8 @@ mm2_db = { path = "../mm2_db" } mm2_metamask = { path = "../mm2_metamask" } mm2_test_helpers = { path = "../mm2_test_helpers" } time = { version = "0.3" } +tonic = { version = "0.7", default-features = false, features = ["prost", "codegen"] } +tonic-web-wasm-client = { git = "https://github.com/borngraced/tonic-web-wasm-client", rev = "cd49d00" } wasm-bindgen = "0.2.86" wasm-bindgen-futures = { version = "0.4.1" } wasm-bindgen-test = { version = "0.3.2" } @@ -160,4 +162,4 @@ mm2_test_helpers = { path = "../mm2_test_helpers" } [build-dependencies] prost-build = { version = "0.10.4", default-features = false } -tonic-build = { version = "0.7", features = ["prost", "compression"] } +tonic-build = { version = "0.7", default-features = false, features = ["prost", "compression"] } diff --git a/mm2src/coins/test_coin.rs b/mm2src/coins/test_coin.rs index c731b12b01..7f5435a576 100644 --- a/mm2src/coins/test_coin.rs +++ b/mm2src/coins/test_coin.rs @@ -143,14 +143,14 @@ impl SwapOps for TestCoin { async fn search_for_swap_tx_spend_my( &self, - _: SearchForSwapTxSpendInput<'_>, + _input: SearchForSwapTxSpendInput<'_>, ) -> Result, String> { unimplemented!() } async fn search_for_swap_tx_spend_other( &self, - _: SearchForSwapTxSpendInput<'_>, + _input: SearchForSwapTxSpendInput<'_>, ) -> Result, String> { unimplemented!() } diff --git a/mm2src/coins/z_coin/storage/blockdb/mod.rs b/mm2src/coins/z_coin/storage/blockdb/mod.rs index 15503db889..9c8589e0f0 100644 --- a/mm2src/coins/z_coin/storage/blockdb/mod.rs +++ b/mm2src/coins/z_coin/storage/blockdb/mod.rs @@ -102,6 +102,11 @@ mod native_tests { mod wasm_tests { use crate::z_coin::storage::blockdb::block_db_storage_tests::{test_insert_block_and_get_latest_block_impl, test_rewind_to_height_impl}; + use crate::z_coin::z_rpc::z_coin_grpc::ChainSpec; + use crate::z_coin::z_rpc::LightRpcClient; + use crate::RpcCommonOps; + use common::log::info; + use common::log::wasm_log::register_wasm_log; use wasm_bindgen_test::*; wasm_bindgen_test_configure!(run_in_browser); @@ -111,4 +116,16 @@ mod wasm_tests { #[wasm_bindgen_test] async fn test_rewind_to_height() { test_rewind_to_height_impl().await } + + #[wasm_bindgen_test] + async fn test_transport() { + register_wasm_log(); + let client = LightRpcClient { + urls: vec!["https://pirate.spyglass.quest:9447".to_string()], + }; + let mut client = client.get_live_client().await.unwrap(); + let request = tonic::Request::new(ChainSpec {}); + let latest = client.get_latest_block(request).await; + info!("{latest:?}"); + } } diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 703e91918a..7c73b58d88 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -1,8 +1,10 @@ use super::{z_coin_errors::*, BlockDbImpl, WalletDbShared, ZCoinBuilder, ZcoinConsensusParams}; use crate::utxo::rpc_clients::NativeClient; use crate::z_coin::SyncStartPoint; +use crate::{RpcCommonOps, ZTransaction}; use async_trait::async_trait; use common::executor::{spawn_abortable, AbortOnDropHandle}; +use common::log::info; use futures::channel::mpsc::{Receiver as AsyncReceiver, Sender as AsyncSender}; use futures::channel::oneshot::{channel as oneshot_channel, Sender as OneshotSender}; use futures::lock::{Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard}; @@ -14,9 +16,14 @@ use zcash_primitives::consensus::BlockHeight; use zcash_primitives::transaction::TxId; use zcash_primitives::zip32::ExtendedSpendingKey; +pub(crate) mod z_coin_grpc { + tonic::include_proto!("cash.z.wallet.sdk.rpc"); +} +use z_coin_grpc::compact_tx_streamer_client::CompactTxStreamerClient; +use z_coin_grpc::ChainSpec; + cfg_native!( use super::CheckPointBlockInfo; - use crate::{RpcCommonOps, ZTransaction}; use crate::utxo::rpc_clients::{UtxoRpcClientOps, NO_TX_ERROR_CODE}; use crate::z_coin::storage::{BlockProcessingMode, DataConnStmtCacheWrapper}; use crate::z_coin::z_coin_errors::{ZcoinStorageError, ValidateBlocksError}; @@ -24,7 +31,7 @@ cfg_native!( use common::{now_sec}; use common::executor::Timer; - use common::log::{debug, error, info, LogOnError}; + use common::log::{debug, error, LogOnError}; use futures::channel::mpsc::channel; use futures::compat::Future01CompatExt; use group::GroupEncoding; @@ -36,16 +43,16 @@ cfg_native!( use std::pin::Pin; use std::str::FromStr; use tonic::transport::{Channel, ClientTlsConfig}; + use tonic::codegen::StdError; use zcash_extras::{WalletRead, WalletWrite}; - mod z_coin_grpc { - tonic::include_proto!("cash.z.wallet.sdk.rpc"); - } use z_coin_grpc::TreeState; - use z_coin_grpc::compact_tx_streamer_client::CompactTxStreamerClient; - use z_coin_grpc::{BlockId, BlockRange, ChainSpec, CompactBlock as TonicCompactBlock, - CompactOutput as TonicCompactOutput, CompactSpend as TonicCompactSpend, CompactTx as TonicCompactTx, - TxFilter}; + use z_coin_grpc::{BlockId, BlockRange, CompactBlock as TonicCompactBlock, CompactOutput as TonicCompactOutput, + CompactSpend as TonicCompactSpend, CompactTx as TonicCompactTx, TxFilter}; +); + +cfg_wasm32!( + use tonic_web_wasm_client::Client as WasmClient; ); /// ZRpcOps trait provides asynchronous methods for performing various operations related to @@ -86,17 +93,32 @@ pub trait ZRpcOps { ) -> MmResult, UpdateBlocksCacheErr>; } -#[cfg(not(target_arch = "wasm32"))] -struct LightRpcClient { +pub struct LightRpcClient { + #[cfg(not(target_arch = "wasm32"))] rpc_clients: AsyncMutex>>, + pub urls: Vec, } +/// Attempt to create a new client by connecting to a given endpoint. #[cfg(not(target_arch = "wasm32"))] +pub async fn connect_endpoint(dst: D) -> Result, tonic::transport::Error> +where + D: std::convert::TryInto, + D::Error: Into, +{ + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(CompactTxStreamerClient::new(conn)) +} + #[async_trait] impl RpcCommonOps for LightRpcClient { + #[cfg(not(target_arch = "wasm32"))] type RpcClient = CompactTxStreamerClient; + #[cfg(target_arch = "wasm32")] + type RpcClient = CompactTxStreamerClient; type Error = MmError; + #[cfg(not(target_arch = "wasm32"))] async fn get_live_client(&self) -> Result { let mut clients = self.rpc_clients.lock().await; for (i, mut client) in clients.clone().into_iter().enumerate() { @@ -111,6 +133,14 @@ impl RpcCommonOps for LightRpcClient { "All the current light clients are unavailable.".to_string(), ))); } + + #[cfg(target_arch = "wasm32")] + async fn get_live_client(&self) -> Result { + let base_url = self.urls[0].clone(); + let wasm_client = WasmClient::new(base_url); + + Ok(CompactTxStreamerClient::new(wasm_client.into())) + } } #[cfg(not(target_arch = "wasm32"))] @@ -366,7 +396,7 @@ pub(super) async fn init_light_client<'a>( if lightwalletd_urls.is_empty() { return MmError::err(ZcoinClientInitError::EmptyLightwalletdUris); } - for url in lightwalletd_urls { + for url in &lightwalletd_urls { let uri = match Uri::from_str(&url) { Ok(uri) => uri, Err(err) => { @@ -381,14 +411,14 @@ pub(super) async fn init_light_client<'a>( continue; }, }; - let tonic_channel = match endpoint.connect().await { + let tonic_channel = match connect_endpoint(endpoint).await { Ok(tonic_channel) => tonic_channel, Err(err) => { errors.push(UrlIterError::ConnectionFailure(err)); continue; }, }; - rpc_clients.push(CompactTxStreamerClient::new(tonic_channel)); + rpc_clients.push(tonic_channel); } drop_mutability!(errors); drop_mutability!(rpc_clients); @@ -399,6 +429,7 @@ pub(super) async fn init_light_client<'a>( let mut light_rpc_clients = LightRpcClient { rpc_clients: AsyncMutex::new(rpc_clients), + urls: lightwalletd_urls, }; let current_block_height = light_rpc_clients From 36921f7fc0dc3239be9c76ca7d2c9d2b79cbbc2f Mon Sep 17 00:00:00 2001 From: borngraced Date: Mon, 2 Oct 2023 11:37:14 +0100 Subject: [PATCH 02/68] save dev state Signed-off-by: borngraced --- mm2src/coins/z_coin/storage/blockdb/mod.rs | 12 +---- mm2src/coins/z_coin/z_rpc.rs | 57 +++++++++++----------- 2 files changed, 29 insertions(+), 40 deletions(-) diff --git a/mm2src/coins/z_coin/storage/blockdb/mod.rs b/mm2src/coins/z_coin/storage/blockdb/mod.rs index 9c8589e0f0..6736a359a2 100644 --- a/mm2src/coins/z_coin/storage/blockdb/mod.rs +++ b/mm2src/coins/z_coin/storage/blockdb/mod.rs @@ -102,10 +102,6 @@ mod native_tests { mod wasm_tests { use crate::z_coin::storage::blockdb::block_db_storage_tests::{test_insert_block_and_get_latest_block_impl, test_rewind_to_height_impl}; - use crate::z_coin::z_rpc::z_coin_grpc::ChainSpec; - use crate::z_coin::z_rpc::LightRpcClient; - use crate::RpcCommonOps; - use common::log::info; use common::log::wasm_log::register_wasm_log; use wasm_bindgen_test::*; @@ -120,12 +116,6 @@ mod wasm_tests { #[wasm_bindgen_test] async fn test_transport() { register_wasm_log(); - let client = LightRpcClient { - urls: vec!["https://pirate.spyglass.quest:9447".to_string()], - }; - let mut client = client.get_live_client().await.unwrap(); - let request = tonic::Request::new(ChainSpec {}); - let latest = client.get_latest_block(request).await; - info!("{latest:?}"); + todo!() } } diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 7c73b58d88..8a3d5dab92 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -1,10 +1,9 @@ use super::{z_coin_errors::*, BlockDbImpl, WalletDbShared, ZCoinBuilder, ZcoinConsensusParams}; use crate::utxo::rpc_clients::NativeClient; use crate::z_coin::SyncStartPoint; -use crate::{RpcCommonOps, ZTransaction}; +use crate::RpcCommonOps; use async_trait::async_trait; use common::executor::{spawn_abortable, AbortOnDropHandle}; -use common::log::info; use futures::channel::mpsc::{Receiver as AsyncReceiver, Sender as AsyncSender}; use futures::channel::oneshot::{channel as oneshot_channel, Sender as OneshotSender}; use futures::lock::{Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard}; @@ -24,6 +23,7 @@ use z_coin_grpc::ChainSpec; cfg_native!( use super::CheckPointBlockInfo; + use crate::ZTransaction; use crate::utxo::rpc_clients::{UtxoRpcClientOps, NO_TX_ERROR_CODE}; use crate::z_coin::storage::{BlockProcessingMode, DataConnStmtCacheWrapper}; use crate::z_coin::z_coin_errors::{ZcoinStorageError, ValidateBlocksError}; @@ -93,10 +93,13 @@ pub trait ZRpcOps { ) -> MmResult, UpdateBlocksCacheErr>; } +#[cfg(not(target_arch = "wasm32"))] +type RpcClientsType = CompactTxStreamerClient; +#[cfg(target_arch = "wasm32")] +type RpcClientsType = CompactTxStreamerClient; + pub struct LightRpcClient { - #[cfg(not(target_arch = "wasm32"))] - rpc_clients: AsyncMutex>>, - pub urls: Vec, + rpc_clients: AsyncMutex>, } /// Attempt to create a new client by connecting to a given endpoint. @@ -112,13 +115,9 @@ where #[async_trait] impl RpcCommonOps for LightRpcClient { - #[cfg(not(target_arch = "wasm32"))] - type RpcClient = CompactTxStreamerClient; - #[cfg(target_arch = "wasm32")] - type RpcClient = CompactTxStreamerClient; + type RpcClient = RpcClientsType; type Error = MmError; - #[cfg(not(target_arch = "wasm32"))] async fn get_live_client(&self) -> Result { let mut clients = self.rpc_clients.lock().await; for (i, mut client) in clients.clone().into_iter().enumerate() { @@ -133,14 +132,6 @@ impl RpcCommonOps for LightRpcClient { "All the current light clients are unavailable.".to_string(), ))); } - - #[cfg(target_arch = "wasm32")] - async fn get_live_client(&self) -> Result { - let base_url = self.urls[0].clone(); - let wasm_client = WasmClient::new(base_url); - - Ok(CompactTxStreamerClient::new(wasm_client.into())) - } } #[cfg(not(target_arch = "wasm32"))] @@ -397,28 +388,37 @@ pub(super) async fn init_light_client<'a>( return MmError::err(ZcoinClientInitError::EmptyLightwalletdUris); } for url in &lightwalletd_urls { - let uri = match Uri::from_str(&url) { + let uri = match Uri::from_str(url) { Ok(uri) => uri, Err(err) => { errors.push(UrlIterError::InvalidUri(err)); continue; }, }; - let endpoint = match Channel::builder(uri).tls_config(ClientTlsConfig::new()) { + + cfg_native!( + let endpoint = match Channel::builder(uri).tls_config(ClientTlsConfig::new()) { Ok(endpoint) => endpoint, Err(err) => { errors.push(UrlIterError::TlsConfigFailure(err)); continue; }, }; - let tonic_channel = match connect_endpoint(endpoint).await { - Ok(tonic_channel) => tonic_channel, - Err(err) => { - errors.push(UrlIterError::ConnectionFailure(err)); - continue; - }, - }; - rpc_clients.push(tonic_channel); + let client = match connect_endpoint(endpoint).await { + Ok(tonic_channel) => tonic_channel, + Err(err) => { + errors.push(UrlIterError::ConnectionFailure(err)); + continue; + }, + }; + ); + + cfg_wasm32!( + let client = WasmClient::new(uri.to_string()); + let client = CompactTxStreamerClient::new(client.intoo()); + ); + + rpc_clients.push(client); } drop_mutability!(errors); drop_mutability!(rpc_clients); @@ -429,7 +429,6 @@ pub(super) async fn init_light_client<'a>( let mut light_rpc_clients = LightRpcClient { rpc_clients: AsyncMutex::new(rpc_clients), - urls: lightwalletd_urls, }; let current_block_height = light_rpc_clients From 287461c36a09d4f7398b1e30a1ac650891c02eee Mon Sep 17 00:00:00 2001 From: borngraced Date: Tue, 3 Oct 2023 13:12:46 +0100 Subject: [PATCH 03/68] revert changes Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 3 ++- mm2src/coins/z_coin/z_rpc.rs | 15 ++++++--------- mm2src/coins/z_coin/z_wasm_transport.rs | 0 mm2src/crypto/src/hw_rpc_task.rs | 3 +-- 4 files changed, 9 insertions(+), 12 deletions(-) create mode 100644 mm2src/coins/z_coin/z_wasm_transport.rs diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 956c07b800..cc8f8b1309 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -105,6 +105,7 @@ pub use z_coin_errors::*; pub mod storage; #[cfg(all(test, feature = "zhtlc-native-tests"))] mod z_coin_native_tests; +#[cfg(target_arch = "wasm32")] pub mod z_wasm_transport; /// `ZP2SHSpendError` compatible `TransactionErr` handling macro. macro_rules! try_ztx_s { @@ -774,7 +775,7 @@ pub enum SyncStartPoint { Date(u64), /// Synchronize from a specific block height. Height(u64), - /// Synchronize from the earliest available data(`sapling_activation_height` from coin config). + /// Synchronize from the earliest available data(sapling_activation_height from coin config). Earliest, } diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 8a3d5dab92..09b64eab12 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -94,12 +94,8 @@ pub trait ZRpcOps { } #[cfg(not(target_arch = "wasm32"))] -type RpcClientsType = CompactTxStreamerClient; -#[cfg(target_arch = "wasm32")] -type RpcClientsType = CompactTxStreamerClient; - pub struct LightRpcClient { - rpc_clients: AsyncMutex>, + rpc_clients: AsyncMutex>>, } /// Attempt to create a new client by connecting to a given endpoint. @@ -113,9 +109,10 @@ where Ok(CompactTxStreamerClient::new(conn)) } +#[cfg(not(target_arch = "wasm32"))] #[async_trait] impl RpcCommonOps for LightRpcClient { - type RpcClient = RpcClientsType; + type RpcClient = CompactTxStreamerClient; type Error = MmError; async fn get_live_client(&self) -> Result { @@ -414,9 +411,9 @@ pub(super) async fn init_light_client<'a>( ); cfg_wasm32!( - let client = WasmClient::new(uri.to_string()); - let client = CompactTxStreamerClient::new(client.intoo()); - ); + // let client = WasmClient::new(uri.to_string()); + // let client = CompactTxStreamerClient::new(client.intoo()); + ); rpc_clients.push(client); } diff --git a/mm2src/coins/z_coin/z_wasm_transport.rs b/mm2src/coins/z_coin/z_wasm_transport.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mm2src/crypto/src/hw_rpc_task.rs b/mm2src/crypto/src/hw_rpc_task.rs index 41a0516ab6..11596889df 100644 --- a/mm2src/crypto/src/hw_rpc_task.rs +++ b/mm2src/crypto/src/hw_rpc_task.rs @@ -23,8 +23,7 @@ pub enum HwRpcTaskAwaitingStatus { EnterTrezorPassphrase, } -/// When it comes to interacting with a HW device, -/// this is a common user action in answer to awaiting RPC task status. +/// When it comes to interacting with a HW device, this is a common user action in answer to awaiting RPC task status. #[derive(Deserialize, Serialize)] #[serde(tag = "action_type")] pub enum HwRpcTaskUserAction { From 68cd8524e51583d2944e240a3691e5c30aa37735 Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 19 Oct 2023 04:36:28 +0100 Subject: [PATCH 04/68] save dev state Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 1 - mm2src/coins/z_coin/storage/blockdb/mod.rs | 21 ++- mm2src/coins/z_coin/z_coin_errors.rs | 2 - mm2src/coins/z_coin/z_rpc.rs | 181 +++++++++++---------- mm2src/coins/z_coin/z_wasm_transport.rs | 0 5 files changed, 113 insertions(+), 92 deletions(-) delete mode 100644 mm2src/coins/z_coin/z_wasm_transport.rs diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index cc8f8b1309..658b964418 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -105,7 +105,6 @@ pub use z_coin_errors::*; pub mod storage; #[cfg(all(test, feature = "zhtlc-native-tests"))] mod z_coin_native_tests; -#[cfg(target_arch = "wasm32")] pub mod z_wasm_transport; /// `ZP2SHSpendError` compatible `TransactionErr` handling macro. macro_rules! try_ztx_s { diff --git a/mm2src/coins/z_coin/storage/blockdb/mod.rs b/mm2src/coins/z_coin/storage/blockdb/mod.rs index 6736a359a2..42e11fb202 100644 --- a/mm2src/coins/z_coin/storage/blockdb/mod.rs +++ b/mm2src/coins/z_coin/storage/blockdb/mod.rs @@ -102,9 +102,15 @@ mod native_tests { mod wasm_tests { use crate::z_coin::storage::blockdb::block_db_storage_tests::{test_insert_block_and_get_latest_block_impl, test_rewind_to_height_impl}; + use crate::z_coin::z_rpc::{LightRpcClient, ZRpcOps}; + use common::log::info; use common::log::wasm_log::register_wasm_log; use wasm_bindgen_test::*; + use crate::z_coin::z_rpc::z_coin_grpc::compact_tx_streamer_client::CompactTxStreamerClient; + use crate::z_coin::z_rpc::z_coin_grpc::ChainSpec; + use tonic_web_wasm_client::Client; + wasm_bindgen_test_configure!(run_in_browser); #[wasm_bindgen_test] @@ -116,6 +122,19 @@ mod wasm_tests { #[wasm_bindgen_test] async fn test_transport() { register_wasm_log(); - todo!() + let mut client = LightRpcClient::new(vec!["http://localhost:8081".to_string()]) + .await + .unwrap(); + let latest_block = client.get_block_height().await; + info!("LATEST BLOCK: {latest_block:?}"); + } + + #[wasm_bindgen_test] + async fn test_transport2() { + register_wasm_log(); + let client = Client::new("http://127.0.0.1:8081".to_string()); + let mut client = CompactTxStreamerClient::new(client); + let latest = client.get_latest_block(tonic::Request::new(ChainSpec {})).await; + info!("LATEST BLOCK2: {latest:?}"); } } diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index ed69f99202..34419dec13 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -22,7 +22,6 @@ use zcash_primitives::transaction::builder::Error as ZTxBuilderError; #[derive(Debug, Display)] #[non_exhaustive] pub enum UpdateBlocksCacheErr { - #[cfg(not(target_arch = "wasm32"))] GrpcError(tonic::Status), UtxoRpcError(UtxoRpcError), InternalError(String), @@ -32,7 +31,6 @@ pub enum UpdateBlocksCacheErr { DecodeError(String), } -#[cfg(not(target_arch = "wasm32"))] impl From for UpdateBlocksCacheErr { fn from(err: tonic::Status) -> Self { UpdateBlocksCacheErr::GrpcError(err) } } diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 09b64eab12..142e001fad 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -1,16 +1,25 @@ -use super::{z_coin_errors::*, BlockDbImpl, WalletDbShared, ZCoinBuilder, ZcoinConsensusParams}; +use super::{z_coin_errors::*, BlockDbImpl, CheckPointBlockInfo, WalletDbShared, ZCoinBuilder, ZcoinConsensusParams}; use crate::utxo::rpc_clients::NativeClient; +use crate::utxo::rpc_clients::NO_TX_ERROR_CODE; use crate::z_coin::SyncStartPoint; -use crate::RpcCommonOps; use async_trait::async_trait; +use common::executor::Timer; use common::executor::{spawn_abortable, AbortOnDropHandle}; +use common::log::{debug, error, info}; use futures::channel::mpsc::{Receiver as AsyncReceiver, Sender as AsyncSender}; use futures::channel::oneshot::{channel as oneshot_channel, Sender as OneshotSender}; use futures::lock::{Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard}; use futures::StreamExt; +use hex::{FromHex, FromHexError}; use mm2_err_handle::prelude::*; use parking_lot::Mutex; +use prost::Message; +use rpc::v1::types::{Bytes, H256 as H256Json}; +use std::convert::TryFrom; +use std::pin::Pin; +use std::str::FromStr; use std::sync::Arc; +use z_coin_grpc::{BlockId, BlockRange, TreeState, TxFilter}; use zcash_primitives::consensus::BlockHeight; use zcash_primitives::transaction::TxId; use zcash_primitives::zip32::ExtendedSpendingKey; @@ -22,33 +31,24 @@ use z_coin_grpc::compact_tx_streamer_client::CompactTxStreamerClient; use z_coin_grpc::ChainSpec; cfg_native!( - use super::CheckPointBlockInfo; use crate::ZTransaction; - use crate::utxo::rpc_clients::{UtxoRpcClientOps, NO_TX_ERROR_CODE}; + use crate::utxo::rpc_clients::{UtxoRpcClientOps}; use crate::z_coin::storage::{BlockProcessingMode, DataConnStmtCacheWrapper}; use crate::z_coin::z_coin_errors::{ZcoinStorageError, ValidateBlocksError}; use crate::utxo::utxo_builder::{UtxoCoinBuilderCommonOps, DAY_IN_SECONDS}; - use common::{now_sec}; - use common::executor::Timer; - use common::log::{debug, error, LogOnError}; use futures::channel::mpsc::channel; use futures::compat::Future01CompatExt; use group::GroupEncoding; - use hex::{FromHex, FromHexError}; + use common::now_sec; use http::Uri; - use prost::Message; - use std::convert::TryFrom; - use rpc::v1::types::{Bytes, H256 as H256Json}; - use std::pin::Pin; - use std::str::FromStr; + use common::log::LogOnError; use tonic::transport::{Channel, ClientTlsConfig}; use tonic::codegen::StdError; use zcash_extras::{WalletRead, WalletWrite}; - use z_coin_grpc::TreeState; - use z_coin_grpc::{BlockId, BlockRange, CompactBlock as TonicCompactBlock, CompactOutput as TonicCompactOutput, - CompactSpend as TonicCompactSpend, CompactTx as TonicCompactTx, TxFilter}; + use z_coin_grpc::{CompactBlock as TonicCompactBlock, CompactOutput as TonicCompactOutput, + CompactSpend as TonicCompactSpend, CompactTx as TonicCompactTx}; ); cfg_wasm32!( @@ -57,13 +57,12 @@ cfg_wasm32!( /// ZRpcOps trait provides asynchronous methods for performing various operations related to /// Zcoin blockchain and wallet synchronization. -#[async_trait] +#[async_trait(?Send)] pub trait ZRpcOps { /// Asynchronously retrieve the current block height from the Zcoin network. async fn get_block_height(&mut self) -> Result>; /// Asynchronously retrieve the tree state for a specific block height from the Zcoin network. - #[cfg(not(target_arch = "wasm32"))] async fn get_tree_state(&mut self, height: u64) -> Result>; /// Asynchronously scan and process blocks within a specified block height range. @@ -86,7 +85,6 @@ pub trait ZRpcOps { /// checkpoint_block_from_height retrieves tree state information from rpc corresponding to the given /// height and constructs a `CheckPointBlockInfo` struct containing some needed details such as /// block height, hash, time, and sapling tree. - #[cfg(not(target_arch = "wasm32"))] async fn checkpoint_block_from_height( &mut self, height: u64, @@ -94,33 +92,78 @@ pub trait ZRpcOps { } #[cfg(not(target_arch = "wasm32"))] +type RpcClientType = Channel; +#[cfg(target_arch = "wasm32")] +type RpcClientType = WasmClient; + pub struct LightRpcClient { - rpc_clients: AsyncMutex>>, + rpc_clients: AsyncMutex>>, } -/// Attempt to create a new client by connecting to a given endpoint. -#[cfg(not(target_arch = "wasm32"))] -pub async fn connect_endpoint(dst: D) -> Result, tonic::transport::Error> -where - D: std::convert::TryInto, - D::Error: Into, -{ - let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; - Ok(CompactTxStreamerClient::new(conn)) -} +impl LightRpcClient { + #[allow(unused_mut)] + pub async fn new(lightwalletd_urls: Vec) -> Result> { + let mut rpc_clients = Vec::new(); + if lightwalletd_urls.is_empty() { + return MmError::err(ZcoinClientInitError::EmptyLightwalletdUris); + } -#[cfg(not(target_arch = "wasm32"))] -#[async_trait] -impl RpcCommonOps for LightRpcClient { - type RpcClient = CompactTxStreamerClient; - type Error = MmError; + let mut errors = Vec::new(); + for url in &lightwalletd_urls { + cfg_native!( + let uri = match Uri::from_str(url) { + Ok(uri) => uri, + Err(err) => { + errors.push(UrlIterError::InvalidUri(err)); + continue; + }, + }; - async fn get_live_client(&self) -> Result { + let endpoint = match Channel::builder(uri).tls_config(ClientTlsConfig::new()) { + Ok(endpoint) => endpoint, + Err(err) => { + errors.push(UrlIterError::TlsConfigFailure(err)); + continue; + }, + }; + let client = match connect_endpoint(endpoint).await { + Ok(tonic_channel) => tonic_channel, + Err(err) => { + errors.push(UrlIterError::ConnectionFailure(err)); + continue; + }, + }; + ); + + cfg_wasm32!( + let client = WasmClient::new(url.to_string()); + let client = CompactTxStreamerClient::new(client.into()); + ); + + rpc_clients.push(client); + } + + #[cfg(not(target_arch = "wasm32"))] + drop_mutability!(errors); + drop_mutability!(rpc_clients); + // check if rpc_clients is empty, then for loop wasn't successful + if rpc_clients.is_empty() { + return MmError::err(ZcoinClientInitError::UrlIterFailure(errors)); + } + + Ok(LightRpcClient { + rpc_clients: AsyncMutex::new(rpc_clients), + }) + } + + async fn get_live_client(&self) -> Result, MmError> { let mut clients = self.rpc_clients.lock().await; for (i, mut client) in clients.clone().into_iter().enumerate() { let request = tonic::Request::new(ChainSpec {}); // use get_latest_block method as a health check - if client.get_latest_block(request).await.is_ok() { + let latest = client.get_latest_block(request).await; + info!("LATEEEE: {latest:?} "); + if latest.is_ok() { clients.rotate_left(i); return Ok(client); } @@ -131,8 +174,18 @@ impl RpcCommonOps for LightRpcClient { } } +/// Attempt to create a new client by connecting to a given endpoint. #[cfg(not(target_arch = "wasm32"))] -#[async_trait] +pub async fn connect_endpoint(dst: D) -> Result, tonic::transport::Error> +where + D: std::convert::TryInto, + D::Error: Into, +{ + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(CompactTxStreamerClient::new(conn)) +} + +#[async_trait(?Send)] impl ZRpcOps for LightRpcClient { async fn get_block_height(&mut self) -> Result> { let request = tonic::Request::new(ChainSpec {}); @@ -147,7 +200,6 @@ impl ZRpcOps for LightRpcClient { Ok(block.height) } - #[cfg(not(target_arch = "wasm32"))] async fn get_tree_state(&mut self, height: u64) -> Result> { let request = tonic::Request::new(BlockId { height, hash: vec![] }); @@ -224,7 +276,6 @@ impl ZRpcOps for LightRpcClient { true } - #[cfg(not(target_arch = "wasm32"))] async fn checkpoint_block_from_height( &mut self, height: u64, @@ -248,7 +299,7 @@ impl ZRpcOps for LightRpcClient { } #[cfg(not(target_arch = "wasm32"))] -#[async_trait] +#[async_trait(?Send)] impl ZRpcOps for NativeClient { async fn get_block_height(&mut self) -> Result> { Ok(self.get_block_count().compat().await?) @@ -379,54 +430,8 @@ pub(super) async fn init_light_client<'a>( let coin = builder.ticker.to_string(); let (sync_status_notifier, sync_watcher) = channel(1); let (on_tx_gen_notifier, on_tx_gen_watcher) = channel(1); - let mut rpc_clients = Vec::new(); - let mut errors = Vec::new(); - if lightwalletd_urls.is_empty() { - return MmError::err(ZcoinClientInitError::EmptyLightwalletdUris); - } - for url in &lightwalletd_urls { - let uri = match Uri::from_str(url) { - Ok(uri) => uri, - Err(err) => { - errors.push(UrlIterError::InvalidUri(err)); - continue; - }, - }; - - cfg_native!( - let endpoint = match Channel::builder(uri).tls_config(ClientTlsConfig::new()) { - Ok(endpoint) => endpoint, - Err(err) => { - errors.push(UrlIterError::TlsConfigFailure(err)); - continue; - }, - }; - let client = match connect_endpoint(endpoint).await { - Ok(tonic_channel) => tonic_channel, - Err(err) => { - errors.push(UrlIterError::ConnectionFailure(err)); - continue; - }, - }; - ); - cfg_wasm32!( - // let client = WasmClient::new(uri.to_string()); - // let client = CompactTxStreamerClient::new(client.intoo()); - ); - - rpc_clients.push(client); - } - drop_mutability!(errors); - drop_mutability!(rpc_clients); - // check if rpc_clients is empty, then for loop wasn't successful - if rpc_clients.is_empty() { - return MmError::err(ZcoinClientInitError::UrlIterFailure(errors)); - } - - let mut light_rpc_clients = LightRpcClient { - rpc_clients: AsyncMutex::new(rpc_clients), - }; + let mut light_rpc_clients = LightRpcClient::new(lightwalletd_urls).await?; let current_block_height = light_rpc_clients .get_block_height() diff --git a/mm2src/coins/z_coin/z_wasm_transport.rs b/mm2src/coins/z_coin/z_wasm_transport.rs deleted file mode 100644 index e69de29bb2..0000000000 From 4c7588e468571eacbadc3a002971e11fef7c526d Mon Sep 17 00:00:00 2001 From: borngraced Date: Fri, 20 Oct 2023 05:59:48 +0100 Subject: [PATCH 05/68] =?UTF-8?q?save=20dev=20state=20=E2=80=94=20finish?= =?UTF-8?q?=20impl=20zcoin=20transport=20layer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: borngraced --- Cargo.lock | 34 +- mm2src/coins/Cargo.toml | 3 +- .../eth/web3_transport/http_transport.rs | 2 +- mm2src/coins/lp_price.rs | 2 +- mm2src/coins/nft.rs | 2 +- .../tendermint/rpc/tendermint_wasm_rpc.rs | 2 +- mm2src/coins/utxo/rpc_clients.rs | 2 +- mm2src/coins/z_coin.rs | 6 +- mm2src/coins/z_coin/storage/blockdb/mod.rs | 38 +- .../storage/walletdb/wallet_sql_storage.rs | 8 +- .../z_coin/storage/walletdb/wasm/storage.rs | 2 +- mm2src/coins/z_coin/wasm_transport.rs | 55 +++ mm2src/coins/z_coin/z_coin_errors.rs | 8 +- mm2src/coins/z_coin/z_rpc.rs | 76 ++-- mm2src/common/common.rs | 2 + mm2src/mm2_net/Cargo.toml | 29 +- mm2src/mm2_net/src/grpc_web.rs | 24 +- mm2src/mm2_net/src/lib.rs | 3 +- mm2src/mm2_net/src/transport.rs | 2 +- mm2src/mm2_net/src/wasm/body_stream.rs | 410 ++++++++++++++++++ mm2src/mm2_net/src/wasm/mod.rs | 3 + mm2src/mm2_net/src/{ => wasm}/wasm_http.rs | 85 +++- mm2src/mm2_net/src/{ => wasm}/wasm_ws.rs | 0 23 files changed, 673 insertions(+), 125 deletions(-) create mode 100644 mm2src/coins/z_coin/wasm_transport.rs create mode 100644 mm2src/mm2_net/src/wasm/body_stream.rs create mode 100644 mm2src/mm2_net/src/wasm/mod.rs rename mm2src/mm2_net/src/{ => wasm}/wasm_http.rs (77%) rename mm2src/mm2_net/src/{ => wasm}/wasm_ws.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 0c6b4970d9..e2c00ed7dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1008,6 +1008,7 @@ dependencies = [ "ff 0.8.0", "futures 0.1.29", "futures 0.3.15", + "futures-util", "group 0.8.0", "gstuff", "hex 0.4.3", @@ -1077,7 +1078,7 @@ dependencies = [ "tokio-rustls", "tonic", "tonic-build", - "tonic-web-wasm-client", + "tower-service", "url", "utxo_signer", "uuid 1.2.2", @@ -4376,6 +4377,8 @@ name = "mm2_net" version = "0.1.0" dependencies = [ "async-trait", + "base64 0.21.2", + "byteorder 1.4.3", "bytes 1.1.0", "cfg-if 1.0.0", "common", @@ -4385,21 +4388,27 @@ dependencies = [ "futures-util", "gstuff", "http 0.2.7", + "http-body 0.4.5", + "httparse", "hyper", "js-sys", "lazy_static", "mm2_core", "mm2_err_handle", + "pin-project 1.0.10", "prost", "rand 0.7.3", "rustls 0.20.4", "serde", "serde_json", + "thiserror", "tokio", "tokio-rustls", + "tower-service", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test", + "wasm-streams", "web-sys", ] @@ -8019,29 +8028,6 @@ dependencies = [ "syn 1.0.95", ] -[[package]] -name = "tonic-web-wasm-client" -version = "0.4.0" -source = "git+https://github.com/borngraced/tonic-web-wasm-client?rev=cd49d00#cd49d003b337e053878ab8070c63e0b77963a7c5" -dependencies = [ - "base64 0.21.2", - "byteorder 1.4.3", - "bytes 1.1.0", - "futures-util", - "http 0.2.7", - "http-body 0.4.5", - "httparse", - "js-sys", - "pin-project 1.0.10", - "thiserror", - "tonic", - "tower-service", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", -] - [[package]] name = "tower" version = "0.4.13" diff --git a/mm2src/coins/Cargo.toml b/mm2src/coins/Cargo.toml index d31e2d54d8..bfbb6ffa99 100644 --- a/mm2src/coins/Cargo.toml +++ b/mm2src/coins/Cargo.toml @@ -119,6 +119,7 @@ spl-associated-token-account = { version = "1", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] ff = "0.8" +futures-util = "0.3" jubjub = "0.5.1" js-sys = { version = "0.3.27" } mm2_db = { path = "../mm2_db" } @@ -126,7 +127,7 @@ mm2_metamask = { path = "../mm2_metamask" } mm2_test_helpers = { path = "../mm2_test_helpers" } time = { version = "0.3" } tonic = { version = "0.7", default-features = false, features = ["prost", "codegen"] } -tonic-web-wasm-client = { git = "https://github.com/borngraced/tonic-web-wasm-client", rev = "cd49d00" } +tower-service = "0.3" wasm-bindgen = "0.2.86" wasm-bindgen-futures = { version = "0.4.1" } wasm-bindgen-test = { version = "0.3.2" } diff --git a/mm2src/coins/eth/web3_transport/http_transport.rs b/mm2src/coins/eth/web3_transport/http_transport.rs index 5272974310..61795d635f 100644 --- a/mm2src/coins/eth/web3_transport/http_transport.rs +++ b/mm2src/coins/eth/web3_transport/http_transport.rs @@ -298,7 +298,7 @@ async fn send_request_once( event_handlers: &Vec, ) -> Result { use http::header::ACCEPT; - use mm2_net::wasm_http::FetchRequest; + use mm2_net::wasm::wasm_http::FetchRequest; // account for outgoing traffic event_handlers.on_outgoing_request(request_payload.as_bytes()); diff --git a/mm2src/coins/lp_price.rs b/mm2src/coins/lp_price.rs index c0834c2efe..f4e346c316 100644 --- a/mm2src/coins/lp_price.rs +++ b/mm2src/coins/lp_price.rs @@ -199,7 +199,7 @@ async fn process_price_request(price_url: &str) -> Result Result> { debug!("Fetching price from: {}", price_url); - let (status, headers, body) = mm2_net::wasm_http::slurp_url(price_url).await?; + let (status, headers, body) = mm2_net::wasm::wasm_http::slurp_url(price_url).await?; let (status_code, body, _) = (status, std::str::from_utf8(&body)?.trim().into(), headers); if status_code != StatusCode::OK { return MmError::err(PriceServiceRequestError::HttpProcessError(body)); diff --git a/mm2src/coins/nft.rs b/mm2src/coins/nft.rs index c84d0cbe24..e106de5fe2 100644 --- a/mm2src/coins/nft.rs +++ b/mm2src/coins/nft.rs @@ -415,7 +415,7 @@ async fn send_request_to_uri(uri: &str) -> MmResult { #[cfg(target_arch = "wasm32")] async fn send_request_to_uri(uri: &str) -> MmResult { - use mm2_net::wasm_http::FetchRequest; + use mm2_net::wasm::wasm_http::FetchRequest; macro_rules! try_or { ($exp:expr, $errtype:ident) => { diff --git a/mm2src/coins/tendermint/rpc/tendermint_wasm_rpc.rs b/mm2src/coins/tendermint/rpc/tendermint_wasm_rpc.rs index 036815a25f..9238801774 100644 --- a/mm2src/coins/tendermint/rpc/tendermint_wasm_rpc.rs +++ b/mm2src/coins/tendermint/rpc/tendermint_wasm_rpc.rs @@ -7,7 +7,7 @@ use http::header::{ACCEPT, CONTENT_TYPE}; use http::uri::InvalidUri; use http::{StatusCode, Uri}; use mm2_net::transport::SlurpError; -use mm2_net::wasm_http::FetchRequest; +use mm2_net::wasm::wasm_http::FetchRequest; use std::str::FromStr; use tendermint_rpc::endpoint::{abci_info, broadcast}; pub use tendermint_rpc::endpoint::{abci_query::{AbciQuery, Request as AbciRequest}, diff --git a/mm2src/coins/utxo/rpc_clients.rs b/mm2src/coins/utxo/rpc_clients.rs index c4cb848dde..8227d5e947 100644 --- a/mm2src/coins/utxo/rpc_clients.rs +++ b/mm2src/coins/utxo/rpc_clients.rs @@ -2757,7 +2757,7 @@ async fn connect_loop( static ref CONN_IDX: Arc = Arc::new(AtomicUsize::new(0)); } - use mm2_net::wasm_ws::ws_transport; + use mm2_net::wasm::wasm_ws::ws_transport; let delay = Arc::new(AtomicU64::new(0)); loop { diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 658b964418..1f591f2dd7 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -103,6 +103,7 @@ use crate::z_coin::storage::{BlockDbImpl, WalletDbShared}; pub use z_coin_errors::*; pub mod storage; +#[cfg(target_arch = "wasm32")] pub mod wasm_transport; #[cfg(all(test, feature = "zhtlc-native-tests"))] mod z_coin_native_tests; @@ -1016,9 +1017,8 @@ impl<'a> ZCoinBuilder<'a> { let cache_db_path = self.db_dir_path.join(format!("{}_cache.db", self.ticker)); let ctx = self.ctx.clone(); let ticker = self.ticker.to_string(); - BlockDbImpl::new(ctx, ticker, Some(cache_db_path)) - .map_err(|err| MmError::new(ZcoinClientInitError::ZcashDBError(err.to_string()))) - .await + + Ok(BlockDbImpl::new(ctx, ticker, Some(cache_db_path)).await?) } #[cfg(not(target_arch = "wasm32"))] diff --git a/mm2src/coins/z_coin/storage/blockdb/mod.rs b/mm2src/coins/z_coin/storage/blockdb/mod.rs index 42e11fb202..2d9e586a50 100644 --- a/mm2src/coins/z_coin/storage/blockdb/mod.rs +++ b/mm2src/coins/z_coin/storage/blockdb/mod.rs @@ -102,14 +102,13 @@ mod native_tests { mod wasm_tests { use crate::z_coin::storage::blockdb::block_db_storage_tests::{test_insert_block_and_get_latest_block_impl, test_rewind_to_height_impl}; - use crate::z_coin::z_rpc::{LightRpcClient, ZRpcOps}; - use common::log::info; - use common::log::wasm_log::register_wasm_log; + // use crate::z_coin::z_rpc::{LightRpcClient, ZRpcOps}; + // use common::log::info; + // use common::log::wasm_log::register_wasm_log; use wasm_bindgen_test::*; - use crate::z_coin::z_rpc::z_coin_grpc::compact_tx_streamer_client::CompactTxStreamerClient; - use crate::z_coin::z_rpc::z_coin_grpc::ChainSpec; - use tonic_web_wasm_client::Client; + // use crate::z_coin::z_rpc::z_coin_grpc::compact_tx_streamer_client::CompactTxStreamerClient; + // use crate::z_coin::z_rpc::z_coin_grpc::ChainSpec; wasm_bindgen_test_configure!(run_in_browser); @@ -119,22 +118,13 @@ mod wasm_tests { #[wasm_bindgen_test] async fn test_rewind_to_height() { test_rewind_to_height_impl().await } - #[wasm_bindgen_test] - async fn test_transport() { - register_wasm_log(); - let mut client = LightRpcClient::new(vec!["http://localhost:8081".to_string()]) - .await - .unwrap(); - let latest_block = client.get_block_height().await; - info!("LATEST BLOCK: {latest_block:?}"); - } - - #[wasm_bindgen_test] - async fn test_transport2() { - register_wasm_log(); - let client = Client::new("http://127.0.0.1:8081".to_string()); - let mut client = CompactTxStreamerClient::new(client); - let latest = client.get_latest_block(tonic::Request::new(ChainSpec {})).await; - info!("LATEST BLOCK2: {latest:?}"); - } + // #[wasm_bindgen_test] + // async fn test_transport() { + // register_wasm_log(); + // let mut client = LightRpcClient::new(vec!["http://localhost:8081".to_string()]) + // .await + // .unwrap(); + // let latest_block = client.get_block_height().await; + // info!("LATEST BLOCK: {latest_block:?}"); + // } } diff --git a/mm2src/coins/z_coin/storage/walletdb/wallet_sql_storage.rs b/mm2src/coins/z_coin/storage/walletdb/wallet_sql_storage.rs index cacc4882b9..d2a45f8e5d 100644 --- a/mm2src/coins/z_coin/storage/walletdb/wallet_sql_storage.rs +++ b/mm2src/coins/z_coin/storage/walletdb/wallet_sql_storage.rs @@ -16,7 +16,7 @@ use zcash_primitives::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}; fn run_optimization_pragmas_helper(w: &WalletDbAsync) -> MmResult<(), ZcoinClientInitError> { let conn = w.inner(); let conn = conn.lock().unwrap(); - run_optimization_pragmas(conn.sql_conn()).map_to_mm(|err| ZcoinClientInitError::ZcashDBError(err.to_string()))?; + run_optimization_pragmas(conn.sql_conn()).map_to_mm(|err| ZcoinClientInitError::ZcoinStorageError(err.to_string()))?; Ok(()) } @@ -32,12 +32,12 @@ pub async fn create_wallet_db( continue_from_prev_sync: bool, ) -> Result, MmError> { let db = WalletDbAsync::for_path(wallet_db_path, consensus_params) - .map_to_mm(|err| ZcoinClientInitError::ZcashDBError(err.to_string()))?; + .map_to_mm(|err| ZcoinClientInitError::ZcoinStorageError(err.to_string()))?; run_optimization_pragmas_helper(&db)?; init_wallet_db(&db) .await - .map_to_mm(|err| ZcoinClientInitError::ZcashDBError(err.to_string()))?; + .map_to_mm(|err| ZcoinClientInitError::ZcoinStorageError(err.to_string()))?; let get_evk = db.get_extended_full_viewing_keys().await?; let extrema = db.block_height_extrema().await?; @@ -55,7 +55,7 @@ pub async fn create_wallet_db( wallet_ops .rewind_to_height(u32::MIN.into()) .await - .map_to_mm(|err| ZcoinClientInitError::ZcashDBError(err.to_string()))?; + .map_to_mm(|err| ZcoinClientInitError::ZcoinStorageError(err.to_string()))?; if let Some(block) = checkpoint_block.clone() { init_blocks_table( &db, diff --git a/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs b/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs index e5754c08e2..548d6b7d07 100644 --- a/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs +++ b/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs @@ -53,7 +53,7 @@ macro_rules! num_to_bigint { impl<'a> WalletDbShared { pub async fn new( - builder: ZCoinBuilder<'a>, + builder: &ZCoinBuilder<'a>, checkpoint_block: Option, z_spending_key: &ExtendedSpendingKey, continue_from_prev_sync: bool, diff --git a/mm2src/coins/z_coin/wasm_transport.rs b/mm2src/coins/z_coin/wasm_transport.rs new file mode 100644 index 0000000000..54d4bf4188 --- /dev/null +++ b/mm2src/coins/z_coin/wasm_transport.rs @@ -0,0 +1,55 @@ +use common::{APPLICATION_GRPC_WEB_PROTO, X_GRPC_WEB}; +use futures_util::Future; +use http::header::{ACCEPT, CONTENT_TYPE}; +use http::{Request, Response}; +use mm2_err_handle::prelude::*; +use mm2_net::grpc_web::PostGrpcWebErr; +use mm2_net::wasm::body_stream::ResponseBody; +use mm2_net::wasm::wasm_http::FetchRequest; +use std::{pin::Pin, + task::{Context, Poll}}; +use tonic::body::BoxBody; +use tonic::codegen::Body; +use tower_service::Service; + +#[derive(Clone)] +pub struct Client(String); + +impl Client { + pub fn new(url: String) -> Self { Self(url) } +} + +impl Service> for Client { + type Response = Response; + + type Error = MmError; + + type Future = Pin> + Send + 'static>>; + + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } + + fn call(&mut self, request: Request) -> Self::Future { Box::pin(call(self.0.clone(), request)) } +} + +async fn call(mut base_url: String, request: Request) -> MmResult, PostGrpcWebErr> { + base_url.push_str(&request.uri().to_string()); + + let body = request + .into_body() + .data() + .await + .transpose() + .map_err(|err| PostGrpcWebErr::Status(err.to_string()))?; + let body = body.ok_or(MmError::new(PostGrpcWebErr::InvalidRequest( + "Invalid request body".to_string(), + )))?; + Ok(FetchRequest::post(&base_url) + .body_bytes(body.to_vec()) + .header(CONTENT_TYPE.as_str(), APPLICATION_GRPC_WEB_PROTO) + .header(ACCEPT.as_str(), APPLICATION_GRPC_WEB_PROTO) + // https://github.com/grpc/grpc-web/issues/85#issue-217223001 + .header(X_GRPC_WEB, "1") + .request_stream() + .await? + .1) +} diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index 34419dec13..408015f8c4 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -60,7 +60,7 @@ impl From for UpdateBlocksCacheErr { #[derive(Debug, Display)] #[non_exhaustive] pub enum ZcoinClientInitError { - ZcashDBError(String), + ZcoinStorageError(String), EmptyLightwalletdUris, #[display(fmt = "Fail to init clients while iterating lightwalletd urls {:?}", _0)] UrlIterFailure(Vec), @@ -72,9 +72,13 @@ impl From for ZcoinClientInitError { fn from(err: UpdateBlocksCacheErr) -> Self { ZcoinClientInitError::UpdateBlocksCacheErr(err) } } +impl From for ZcoinClientInitError { + fn from(err: ZcoinStorageError) -> Self { ZcoinClientInitError::ZcoinStorageError(err.to_string()) } +} + #[cfg(not(target_arch = "wasm32"))] impl From for ZcoinClientInitError { - fn from(err: SqliteClientError) -> Self { ZcoinClientInitError::ZcashDBError(err.to_string()) } + fn from(err: SqliteClientError) -> Self { ZcoinClientInitError::ZcoinStorageError(err.to_string()) } } #[derive(Debug, Display)] diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 142e001fad..3c1c94dd88 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -1,11 +1,13 @@ use super::{z_coin_errors::*, BlockDbImpl, CheckPointBlockInfo, WalletDbShared, ZCoinBuilder, ZcoinConsensusParams}; -use crate::utxo::rpc_clients::NativeClient; use crate::utxo::rpc_clients::NO_TX_ERROR_CODE; +use crate::utxo::utxo_builder::{UtxoCoinBuilderCommonOps, DAY_IN_SECONDS}; use crate::z_coin::SyncStartPoint; use async_trait::async_trait; use common::executor::Timer; use common::executor::{spawn_abortable, AbortOnDropHandle}; use common::log::{debug, error, info}; +use common::now_sec; +use futures::channel::mpsc::channel; use futures::channel::mpsc::{Receiver as AsyncReceiver, Sender as AsyncSender}; use futures::channel::oneshot::{channel as oneshot_channel, Sender as OneshotSender}; use futures::lock::{Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard}; @@ -27,6 +29,7 @@ use zcash_primitives::zip32::ExtendedSpendingKey; pub(crate) mod z_coin_grpc { tonic::include_proto!("cash.z.wallet.sdk.rpc"); } +use crate::RpcCommonOps; use z_coin_grpc::compact_tx_streamer_client::CompactTxStreamerClient; use z_coin_grpc::ChainSpec; @@ -35,12 +38,10 @@ cfg_native!( use crate::utxo::rpc_clients::{UtxoRpcClientOps}; use crate::z_coin::storage::{BlockProcessingMode, DataConnStmtCacheWrapper}; use crate::z_coin::z_coin_errors::{ZcoinStorageError, ValidateBlocksError}; - use crate::utxo::utxo_builder::{UtxoCoinBuilderCommonOps, DAY_IN_SECONDS}; + use crate::utxo::rpc_clients::NativeClient; - use futures::channel::mpsc::channel; use futures::compat::Future01CompatExt; use group::GroupEncoding; - use common::now_sec; use http::Uri; use common::log::LogOnError; use tonic::transport::{Channel, ClientTlsConfig}; @@ -52,12 +53,12 @@ cfg_native!( ); cfg_wasm32!( - use tonic_web_wasm_client::Client as WasmClient; + use crate::z_coin::wasm_transport::Client as WasmClient; ); /// ZRpcOps trait provides asynchronous methods for performing various operations related to /// Zcoin blockchain and wallet synchronization. -#[async_trait(?Send)] +#[async_trait] pub trait ZRpcOps { /// Asynchronously retrieve the current block height from the Zcoin network. async fn get_block_height(&mut self) -> Result>; @@ -155,15 +156,19 @@ impl LightRpcClient { rpc_clients: AsyncMutex::new(rpc_clients), }) } +} + +#[async_trait] +impl RpcCommonOps for LightRpcClient { + type RpcClient = CompactTxStreamerClient; + type Error = MmError; - async fn get_live_client(&self) -> Result, MmError> { + async fn get_live_client(&self) -> Result { let mut clients = self.rpc_clients.lock().await; for (i, mut client) in clients.clone().into_iter().enumerate() { let request = tonic::Request::new(ChainSpec {}); // use get_latest_block method as a health check - let latest = client.get_latest_block(request).await; - info!("LATEEEE: {latest:?} "); - if latest.is_ok() { + if client.get_latest_block(request).await.is_ok() { clients.rotate_left(i); return Ok(client); } @@ -185,7 +190,7 @@ where Ok(CompactTxStreamerClient::new(conn)) } -#[async_trait(?Send)] +#[async_trait] impl ZRpcOps for LightRpcClient { async fn get_block_height(&mut self) -> Result> { let request = tonic::Request::new(ChainSpec {}); @@ -299,13 +304,12 @@ impl ZRpcOps for LightRpcClient { } #[cfg(not(target_arch = "wasm32"))] -#[async_trait(?Send)] +#[async_trait] impl ZRpcOps for NativeClient { async fn get_block_height(&mut self) -> Result> { Ok(self.get_block_count().compat().await?) } - #[cfg(not(target_arch = "wasm32"))] async fn get_tree_state(&mut self, _height: u64) -> Result> { todo!() } async fn scan_blocks( @@ -410,7 +414,6 @@ impl ZRpcOps for NativeClient { true } - #[cfg(not(target_arch = "wasm32"))] async fn checkpoint_block_from_height( &mut self, _height: u64, @@ -419,7 +422,6 @@ impl ZRpcOps for NativeClient { } } -#[cfg(not(target_arch = "wasm32"))] pub(super) async fn init_light_client<'a>( builder: &ZCoinBuilder<'a>, lightwalletd_urls: Vec, @@ -456,9 +458,8 @@ pub(super) async fn init_light_client<'a>( let min_height = blocks_db.get_earliest_block().await?; // check if no sync_params was provided and continue syncing from last height in db if it's > 0. let continue_from_prev_sync = min_height > 0 && sync_params.is_none(); - let wallet_db = WalletDbShared::new(builder, maybe_checkpoint_block, z_spending_key, continue_from_prev_sync) - .await - .mm_err(|err| ZcoinClientInitError::ZcashDBError(err.to_string()))?; + let wallet_db = + WalletDbShared::new(builder, maybe_checkpoint_block, z_spending_key, continue_from_prev_sync).await?; // Get min_height in blocks_db and rewind blocks_db to 0 if sync_height != min_height let min_height = blocks_db.get_earliest_block().await?; @@ -467,10 +468,7 @@ pub(super) async fn init_light_client<'a>( if min_height > 0 { info!("Older/Newer sync height detected!, rewinding blocks_db to new height: {sync_height:?}"); } - blocks_db - .rewind_to_height(u32::MIN) - .await - .map_err(|err| ZcoinClientInitError::ZcashDBError(err.to_string()))?; + blocks_db.rewind_to_height(u32::MIN).await?; }; let sync_handle = SaplingSyncLoopHandle { @@ -499,17 +497,17 @@ pub(super) async fn init_light_client<'a>( )) } -#[cfg(target_arch = "wasm32")] -#[allow(unused)] -pub(super) async fn init_light_client<'a>( - _builder: &ZCoinBuilder<'a>, - _lightwalletd_urls: Vec, - _blocks_db: BlockDbImpl, - _sync_params: &Option, - z_spending_key: &ExtendedSpendingKey, -) -> Result<(AsyncMutex, WalletDbShared), MmError> { - todo!() -} +//#[cfg(target_arch = "wasm32")] +//#[allow(unused)] +//pub(super) async fn init_light_client<'a>( +// _builder: &ZCoinBuilder<'a>, +// _lightwalletd_urls: Vec, +// _blocks_db: BlockDbImpl, +// _sync_params: &Option, +// z_spending_key: &ExtendedSpendingKey, +//) -> Result<(AsyncMutex, WalletDbShared), MmError> { +// todo!() +//} #[cfg(not(target_arch = "wasm32"))] pub(super) async fn init_native_client<'a>( @@ -531,7 +529,7 @@ pub(super) async fn init_native_client<'a>( }; let wallet_db = WalletDbShared::new(builder, checkpoint_block, z_spending_key, true) .await - .mm_err(|err| ZcoinClientInitError::ZcashDBError(err.to_string()))?; + .mm_err(|err| ZcoinClientInitError::ZcoinStorageError(err.to_string()))?; let sync_handle = SaplingSyncLoopHandle { coin, @@ -554,16 +552,6 @@ pub(super) async fn init_native_client<'a>( )) } -#[cfg(target_arch = "wasm32")] -pub(super) async fn _init_native_client<'a>( - _builder: &ZCoinBuilder<'a>, - mut _native_client: NativeClient, - _blocks_db: BlockDbImpl, - _z_spending_key: &ExtendedSpendingKey, -) -> Result<(AsyncMutex, WalletDbShared), MmError> { - todo!() -} - pub struct SaplingSyncRespawnGuard { pub(super) sync_handle: Option<(SaplingSyncLoopHandle, Box)>, pub(super) abort_handle: Arc>, diff --git a/mm2src/common/common.rs b/mm2src/common/common.rs index 653ad11353..63fb6c8970 100644 --- a/mm2src/common/common.rs +++ b/mm2src/common/common.rs @@ -183,6 +183,8 @@ pub const X_API_KEY: &str = "X-API-Key"; pub const APPLICATION_JSON: &str = "application/json"; pub const APPLICATION_GRPC_WEB: &str = "application/grpc-web"; pub const APPLICATION_GRPC_WEB_PROTO: &str = "application/grpc-web+proto"; +pub const APPLICATION_GRPC_WEB_TEXT: &str = "application/grpc-web-text"; +pub const APPLICATION_GRPC_WEB_TEXT_PROTO: &str = "application/grpc-web-text+proto"; pub const SATOSHIS: u64 = 100_000_000; diff --git a/mm2src/mm2_net/Cargo.toml b/mm2src/mm2_net/Cargo.toml index e567546f6c..7680f217d8 100644 --- a/mm2src/mm2_net/Cargo.toml +++ b/mm2src/mm2_net/Cargo.toml @@ -8,28 +8,39 @@ doctest = false [dependencies] async-trait = "0.1" -serde = "1" -serde_json = { version = "1", features = ["preserve_order", "raw_value"] } bytes = "1.1" cfg-if = "1.0" +derive_more = "0.99" common = { path = "../common" } ethkey = { git = "https://github.com/KomodoPlatform/mm2-parity-ethereum.git" } -mm2_err_handle = { path = "../mm2_err_handle" } -mm2_core = { path = "../mm2_core" } -derive_more = "0.99" -http = "0.2" -rand = { version = "0.7", features = ["std", "small_rng", "wasm-bindgen"] } futures = { version = "0.3", package = "futures", features = ["compat", "async-await", "thread-pool"] } +http = "0.2" lazy_static = "1.4" +mm2_err_handle = { path = "../mm2_err_handle" } +mm2_core = { path = "../mm2_core" } prost = "0.10" +rand = { version = "0.7", features = ["std", "small_rng", "wasm-bindgen"] } +serde = "1" +serde_json = { version = "1", features = ["preserve_order", "raw_value"] } +thiserror = "1.0.30" [target.'cfg(target_arch = "wasm32")'.dependencies] +base64 = "0.21.2" +byteorder = "1.3" +futures-util = "0.3" gstuff = { version = "0.7", features = ["nightly"] } +http-body = "0.4" +httparse = "1.8.0" +js-sys = "0.3.27" +pin-project = "1.0.10" +tower-service = "0.3" wasm-bindgen = "0.2.86" wasm-bindgen-test = { version = "0.3.2" } wasm-bindgen-futures = "0.4.21" -web-sys = { version = "0.3.55", features = ["console", "CloseEvent", "DomException", "ErrorEvent", "IdbDatabase", "IdbCursor", "IdbCursorWithValue", "IdbFactory", "IdbIndex", "IdbIndexParameters", "IdbObjectStore", "IdbObjectStoreParameters", "IdbOpenDbRequest", "IdbKeyRange", "IdbTransaction", "IdbTransactionMode", "IdbVersionChangeEvent", "MessageEvent", "WebSocket"] } -js-sys = "0.3.27" +web-sys = { version = "0.3.55", features = ["console", "CloseEvent", "DomException", "ErrorEvent", "IdbDatabase", + "IdbCursor", "IdbCursorWithValue", "IdbFactory", "IdbIndex", "IdbIndexParameters", "IdbObjectStore", "IdbObjectStoreParameters", "IdbOpenDbRequest", "IdbKeyRange", "IdbTransaction", "IdbTransactionMode", "IdbVersionChangeEvent", "MessageEvent","ReadableStream", "WebSocket"] } +wasm-streams = "0.3.0" + [target.'cfg(not(target_arch = "wasm32"))'.dependencies] futures-util = { version = "0.3" } diff --git a/mm2src/mm2_net/src/grpc_web.rs b/mm2src/mm2_net/src/grpc_web.rs index 43ba449502..6a294b9acc 100644 --- a/mm2src/mm2_net/src/grpc_web.rs +++ b/mm2src/mm2_net/src/grpc_web.rs @@ -7,6 +7,7 @@ use common::{cfg_native, cfg_wasm32}; use http::header::{ACCEPT, CONTENT_TYPE}; use mm2_err_handle::prelude::*; use prost::DecodeError; +use std::fmt::{Display, Formatter}; cfg_native! { use common::APPLICATION_GRPC_WEB; @@ -15,7 +16,7 @@ cfg_native! { cfg_wasm32! { use common::{X_GRPC_WEB, APPLICATION_GRPC_WEB_PROTO}; - use crate::wasm_http::FetchRequest; + use crate::wasm::wasm_http::FetchRequest; } // one byte for the compression flag plus four bytes for the length @@ -32,7 +33,7 @@ impl From for EncodeBodyError { } #[cfg_attr(target_arch = "wasm32", allow(dead_code))] -fn encode_body(msg: &T) -> Result, MmError> +pub fn encode_body(msg: &T) -> Result, MmError> where T: prost::Message, { @@ -72,7 +73,7 @@ impl From for DecodeBodyError { } #[cfg_attr(target_arch = "wasm32", allow(dead_code))] -fn decode_body(mut body: Bytes) -> Result> +pub fn decode_body(mut body: Bytes) -> Result> where T: Default + prost::Message, { @@ -92,16 +93,31 @@ where Ok(msg) } -#[derive(Debug)] +#[derive(Debug, thiserror::Error)] pub enum PostGrpcWebErr { DecodeBody(String), EncodeBody(String), InvalidRequest(String), Internal(String), PayloadTooShort(String), + Status(String), Transport { uri: String, error: String }, } +impl Display for PostGrpcWebErr { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + PostGrpcWebErr::DecodeBody(msg) => write!(f, "DecodeBody: {msg}"), + PostGrpcWebErr::EncodeBody(msg) => write!(f, "EncodeBody: {msg}"), + PostGrpcWebErr::InvalidRequest(msg) => write!(f, "InvalidRequest: {msg}"), + PostGrpcWebErr::Internal(msg) => write!(f, "Internal: {msg}"), + PostGrpcWebErr::PayloadTooShort(msg) => write!(f, "PayloadTooShort: {msg}"), + PostGrpcWebErr::Status(error) => write!(f, "Status: {error:?}"), + PostGrpcWebErr::Transport { uri, error } => write!(f, "Transport: URI: {uri}, Error: {error}"), + } + } +} + impl From for PostGrpcWebErr { fn from(err: EncodeBodyError) -> Self { PostGrpcWebErr::EncodeBody(format!("{:?}", err)) } } diff --git a/mm2src/mm2_net/src/lib.rs b/mm2src/mm2_net/src/lib.rs index 99935bd25b..133be8f04b 100644 --- a/mm2src/mm2_net/src/lib.rs +++ b/mm2src/mm2_net/src/lib.rs @@ -4,5 +4,4 @@ pub mod transport; #[cfg(not(target_arch = "wasm32"))] pub mod ip_addr; #[cfg(not(target_arch = "wasm32"))] pub mod native_http; #[cfg(not(target_arch = "wasm32"))] pub mod native_tls; -#[cfg(target_arch = "wasm32")] pub mod wasm_http; -#[cfg(target_arch = "wasm32")] pub mod wasm_ws; +#[cfg(target_arch = "wasm32")] pub mod wasm; diff --git a/mm2src/mm2_net/src/transport.rs b/mm2src/mm2_net/src/transport.rs index 2ba04b65e1..f263d12ebb 100644 --- a/mm2src/mm2_net/src/transport.rs +++ b/mm2src/mm2_net/src/transport.rs @@ -10,7 +10,7 @@ use serde_json::{Error, Value as Json}; pub use crate::native_http::{slurp_post_json, slurp_req, slurp_req_body, slurp_url, slurp_url_with_headers}; #[cfg(target_arch = "wasm32")] -pub use crate::wasm_http::{slurp_post_json, slurp_url, slurp_url_with_headers}; +pub use crate::wasm::wasm_http::{slurp_post_json, slurp_url, slurp_url_with_headers}; pub type SlurpResult = Result<(StatusCode, HeaderMap, Vec), MmError>; diff --git a/mm2src/mm2_net/src/wasm/body_stream.rs b/mm2src/mm2_net/src/wasm/body_stream.rs new file mode 100644 index 0000000000..15d6591d81 --- /dev/null +++ b/mm2src/mm2_net/src/wasm/body_stream.rs @@ -0,0 +1,410 @@ +use crate::grpc_web::PostGrpcWebErr; + +use base64::prelude::BASE64_STANDARD; +use base64::Engine; +use byteorder::{BigEndian, ByteOrder}; +use bytes::{BufMut, Bytes, BytesMut}; +use common::{APPLICATION_GRPC_WEB, APPLICATION_GRPC_WEB_PROTO, APPLICATION_GRPC_WEB_TEXT, + APPLICATION_GRPC_WEB_TEXT_PROTO}; +use futures_util::ready; +use futures_util::{stream::empty, Stream, TryStreamExt}; +use http::{header::HeaderName, HeaderMap, HeaderValue}; +use http_body::Body; +use httparse::{Status, EMPTY_HEADER}; +use js_sys::Uint8Array; +use pin_project::pin_project; +use std::ops::{Deref, DerefMut}; +use std::{pin::Pin, + task::{Context, Poll}}; +use wasm_bindgen::JsCast; +use wasm_streams::readable::IntoStream; +use web_sys::ReadableStream; + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Encoding { + Base64, + None, +} + +impl Encoding { + pub fn from_content_type(content_type: &str) -> Result { + match content_type { + APPLICATION_GRPC_WEB_TEXT | APPLICATION_GRPC_WEB_TEXT_PROTO => Ok(Encoding::Base64), + APPLICATION_GRPC_WEB | APPLICATION_GRPC_WEB_PROTO => Ok(Encoding::None), + _ => Err(PostGrpcWebErr::InvalidRequest(content_type.to_owned())), + } + } +} + +/// If 8th MSB of a frame is `0` for data and `1` for trailer +const TRAILER_BIT: u8 = 0b10000000; + +pub struct EncodedBytes { + encoding: Encoding, + raw_buf: BytesMut, + buf: BytesMut, +} + +impl EncodedBytes { + pub fn new(content_type: &str) -> Result { + Ok(Self { + encoding: Encoding::from_content_type(content_type)?, + raw_buf: BytesMut::new(), + buf: BytesMut::new(), + }) + } + + // This is to avoid passing a slice of bytes with a length that the base64 + // decoder would consider invalid. + #[inline] + fn max_decodable(&self) -> usize { (self.raw_buf.len() / 4) * 4 } + + fn decode_base64_chunk(&mut self) -> Result<(), PostGrpcWebErr> { + let index = self.max_decodable(); + + if self.raw_buf.len() >= index { + let decoded = BASE64_STANDARD + .decode(self.buf.split_to(index)) + .map(Bytes::from) + .map_err(|err| PostGrpcWebErr::DecodeBody(err.to_string()))?; + self.buf.put(decoded); + } + + Ok(()) + } + + fn append(&mut self, bytes: Bytes) -> Result<(), PostGrpcWebErr> { + match self.encoding { + Encoding::None => self.buf.put(bytes), + Encoding::Base64 => { + self.raw_buf.put(bytes); + self.decode_base64_chunk()?; + }, + } + + Ok(()) + } + + fn take(&mut self, length: usize) -> BytesMut { + let new_buf = self.buf.split_off(length); + std::mem::replace(&mut self.buf, new_buf) + } +} + +impl Deref for EncodedBytes { + type Target = BytesMut; + + fn deref(&self) -> &Self::Target { &self.buf } +} + +impl DerefMut for EncodedBytes { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.buf } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ReadState { + CompressionFlag, + DataLength, + Data(u32), + TrailerLength, + Trailer(u32), + Done, +} + +impl ReadState { + fn is_done(&self) -> bool { matches!(self, ReadState::Done) } + + fn finished_data(&self) -> bool { + matches!(self, ReadState::TrailerLength) + || matches!(self, ReadState::Trailer(_)) + || matches!(self, ReadState::Done) + } +} + +/// Type to handle HTTP response +#[pin_project] +pub struct ResponseBody { + #[pin] + body_stream: BodyStream, + buf: EncodedBytes, + incomplete_data: BytesMut, + data: Option, + trailer: Option, + state: ReadState, + finished_stream: bool, +} + +impl ResponseBody { + pub(crate) fn new(body_stream: ReadableStream, content_type: &str) -> Result { + let body_stream = wasm_streams::ReadableStream::from_raw(body_stream.unchecked_into()).into_stream(); + + Ok(Self { + body_stream: BodyStream::new(body_stream), + buf: EncodedBytes::new(content_type)?, + incomplete_data: BytesMut::new(), + data: None, + trailer: None, + state: ReadState::CompressionFlag, + finished_stream: false, + }) + } + + fn read_stream(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + if self.finished_stream { + return Poll::Ready(Ok(())); + } + + let this = self.project(); + + match ready!(this.body_stream.poll_data(cx)) { + Some(Ok(data)) => { + if let Err(e) = this.buf.append(data) { + return Poll::Ready(Err(e)); + } + + Poll::Ready(Ok(())) + }, + Some(Err(e)) => Poll::Ready(Err(e)), + None => { + *this.finished_stream = true; + Poll::Ready(Ok(())) + }, + } + } + + fn step(self: Pin<&mut Self>) -> Result<(), PostGrpcWebErr> { + let this = self.project(); + + loop { + match this.state { + ReadState::CompressionFlag => { + if this.buf.is_empty() { + // Can't read compression flag right now + return Ok(()); + } else { + let compression_flag = this.buf.take(1); + + if compression_flag[0] & TRAILER_BIT == 0 { + this.incomplete_data.unsplit(compression_flag); + *this.state = ReadState::DataLength; + } else { + *this.state = ReadState::TrailerLength; + } + } + }, + ReadState::DataLength => { + if this.buf.len() < 4 { + // Can't read data length right now + return Ok(()); + } else { + let data_length_bytes = this.buf.take(4); + let data_length = BigEndian::read_u32(data_length_bytes.as_ref()); + + this.incomplete_data.unsplit(data_length_bytes); + *this.state = ReadState::Data(data_length); + } + }, + ReadState::Data(data_length) => { + let data_length = *data_length as usize; + + if this.buf.len() < data_length { + // Can't read data right now + return Ok(()); + } else { + this.incomplete_data.unsplit(this.buf.take(data_length)); + + let new_data = this.incomplete_data.split(); + + if let Some(data) = this.data { + data.unsplit(new_data); + } else { + *this.data = Some(new_data); + } + + *this.state = ReadState::CompressionFlag; + } + }, + ReadState::TrailerLength => { + if this.buf.len() < 4 { + // Can't read data length right now + return Ok(()); + } else { + let trailer_length_bytes = this.buf.take(4); + let trailer_length = BigEndian::read_u32(trailer_length_bytes.as_ref()); + *this.state = ReadState::Trailer(trailer_length); + } + }, + ReadState::Trailer(trailer_length) => { + let trailer_length = *trailer_length as usize; + + if this.buf.len() < trailer_length { + // Can't read trailer right now + return Ok(()); + } else { + let mut trailer_bytes = this.buf.take(trailer_length); + trailer_bytes.put_u8(b'\n'); + + let mut trailers_buf = [EMPTY_HEADER; 64]; + let parsed_trailers = match httparse::parse_headers(&trailer_bytes, &mut trailers_buf) + .map_err(|err| PostGrpcWebErr::InvalidRequest(err.to_string()))? + { + Status::Complete((_, headers)) => Ok(headers), + Status::Partial => Err(PostGrpcWebErr::InvalidRequest("Invalid".to_string())), + }?; + + let mut trailers = HeaderMap::with_capacity(parsed_trailers.len()); + + for parsed_trailer in parsed_trailers { + let header_name = HeaderName::from_bytes(parsed_trailer.name.as_bytes()) + .map_err(|err| PostGrpcWebErr::InvalidRequest(err.to_string()))?; + let header_value = HeaderValue::from_bytes(parsed_trailer.value) + .map_err(|err| PostGrpcWebErr::InvalidRequest(err.to_string()))?; + trailers.insert(header_name, header_value); + } + + *this.trailer = Some(trailers); + + *this.state = ReadState::Done; + } + }, + ReadState::Done => return Ok(()), + } + } + } +} + +impl Body for ResponseBody { + type Data = Bytes; + + type Error = PostGrpcWebErr; + + fn poll_data(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>> { + // Check if there's already some data in buffer and return that + if self.data.is_some() { + let data = self.data.take().unwrap(); + return Poll::Ready(Some(Ok(data.freeze()))); + } + + // If reading data is finished return `None` + if self.state.finished_data() { + return Poll::Ready(None); + } + + loop { + // Read bytes from stream + if let Err(e) = ready!(self.as_mut().read_stream(cx)) { + return Poll::Ready(Some(Err(e))); + } + + // Step the state machine + if let Err(e) = self.as_mut().step() { + return Poll::Ready(Some(Err(e))); + } + + if self.data.is_some() { + // If data is available in buffer, return that + let data = self.data.take().unwrap(); + return Poll::Ready(Some(Ok(data.freeze()))); + } else if self.state.finished_data() { + // If we finished reading data continue return `None` + return Poll::Ready(None); + } else if self.finished_stream { + // If stream is finished but data is not finished return error + return Poll::Ready(Some(Err(PostGrpcWebErr::InvalidRequest("Bad response".to_string())))); + } + } + } + + fn poll_trailers(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll, Self::Error>> { + // If the state machine is complete, return trailer + if self.state.is_done() { + return Poll::Ready(Ok(self.trailer.take())); + } + + loop { + // Read bytes from stream + if let Err(e) = ready!(self.as_mut().read_stream(cx)) { + return Poll::Ready(Err(e)); + } + + // Step the state machine + if let Err(e) = self.as_mut().step() { + return Poll::Ready(Err(e)); + } + + if self.state.is_done() { + // If state machine is done, return trailer + return Poll::Ready(Ok(self.trailer.take())); + } else if self.finished_stream { + // If stream is finished but state machine is not done, return error + return Poll::Ready(Err(PostGrpcWebErr::InvalidRequest("Bad response".to_string()))); + } + } + } +} + +impl Default for ResponseBody { + fn default() -> Self { + Self { + body_stream: BodyStream::empty(), + buf: EncodedBytes { + encoding: Encoding::None, + raw_buf: BytesMut::new(), + buf: BytesMut::new(), + }, + incomplete_data: BytesMut::new(), + data: None, + trailer: None, + state: ReadState::Done, + finished_stream: true, + } + } +} + +pub struct BodyStream { + body_stream: Pin>>>, +} + +impl BodyStream { + pub fn new(body_stream: IntoStream<'static>) -> Self { + let body_stream = body_stream + .map_ok(|js_value| { + let buffer = Uint8Array::new(&js_value); + + let mut bytes_vec = vec![0; buffer.length() as usize]; + buffer.copy_to(&mut bytes_vec); + + bytes_vec.into() + }) + .map_err(|err| PostGrpcWebErr::InvalidRequest(format!("{err:?}"))); + + Self { + body_stream: Box::pin(body_stream), + } + } + + pub fn empty() -> Self { + let body_stream = empty(); + + Self { + body_stream: Box::pin(body_stream), + } + } +} + +impl Body for BodyStream { + type Data = Bytes; + + type Error = PostGrpcWebErr; + + fn poll_data(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>> { + self.body_stream.as_mut().poll_next(cx) + } + + fn poll_trailers(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll, Self::Error>> { + Poll::Ready(Ok(None)) + } +} + +unsafe impl Send for BodyStream {} +unsafe impl Sync for BodyStream {} diff --git a/mm2src/mm2_net/src/wasm/mod.rs b/mm2src/mm2_net/src/wasm/mod.rs new file mode 100644 index 0000000000..a5583bf87c --- /dev/null +++ b/mm2src/mm2_net/src/wasm/mod.rs @@ -0,0 +1,3 @@ +pub mod body_stream; +pub mod wasm_http; +pub mod wasm_ws; diff --git a/mm2src/mm2_net/src/wasm_http.rs b/mm2src/mm2_net/src/wasm/wasm_http.rs similarity index 77% rename from mm2src/mm2_net/src/wasm_http.rs rename to mm2src/mm2_net/src/wasm/wasm_http.rs index 3767c2f40c..aed5fed32a 100644 --- a/mm2src/mm2_net/src/wasm_http.rs +++ b/mm2src/mm2_net/src/wasm/wasm_http.rs @@ -1,9 +1,12 @@ use crate::transport::{SlurpError, SlurpResult}; +use crate::wasm::body_stream::ResponseBody; use common::executor::spawn_local; use common::{stringify_js_error, APPLICATION_JSON}; use futures::channel::oneshot; use http::header::CONTENT_TYPE; -use http::{HeaderMap, StatusCode}; +use http::response::Builder; +use http::{HeaderMap, Response, StatusCode}; +use js_sys::Array; use js_sys::Uint8Array; use mm2_err_handle::prelude::*; use std::collections::HashMap; @@ -46,6 +49,41 @@ pub async fn slurp_post_json(url: &str, body: String) -> SlurpResult { .map(|(status_code, response)| (status_code, HeaderMap::new(), response.into_bytes())) } +fn set_response_headers( + mut result: Builder, + response: &JsResponse, +) -> Result<(Builder, Option), MmError> { + let headers = response.headers(); + + let header_iter = + js_sys::try_iter(headers.as_ref()).map_to_mm(|err| SlurpError::InvalidRequest(format!("{err:?}")))?; + + let mut content_type = None; + + if let Some(header_iter) = header_iter { + for header in header_iter { + let header = header.map_to_mm(|err| SlurpError::InvalidRequest(format!("{err:?}")))?; + let pair: Array = header.into(); + + let header_name = pair.get(0).as_string(); + let header_value = pair.get(1).as_string(); + + match (header_name, header_value) { + (Some(header_name), Some(header_value)) => { + if header_name == CONTENT_TYPE.as_str() { + content_type = Some(header_value.clone()); + } + + result = result.header(header_name, header_value); + }, + _ => continue, + } + } + } + + Ok((result, content_type)) +} + pub struct FetchRequest { uri: String, method: FetchMethod, @@ -122,6 +160,15 @@ impl FetchRequest { } } + pub async fn request_stream(self) -> FetchResult> { + let (tx, rx) = oneshot::channel(); + Self::spawn_fetch_stream(self, tx); + match rx.await { + Ok(res) => res, + Err(_e) => MmError::err(SlurpError::Internal("Spawned future has been canceled".to_owned())), + } + } + fn spawn_fetch_str(request: Self, tx: oneshot::Sender>) { let fut = async move { let result = Self::fetch_str(request).await; @@ -144,6 +191,17 @@ impl FetchRequest { spawn_local(fut); } + fn spawn_fetch_stream(request: Self, tx: oneshot::Sender>>) { + let fut = async move { + let result = Self::fetch_stream(request).await; + tx.send(result).ok(); + }; + + // The spawned future doesn't capture shared pointers, + // so we can use `spawn_local` here. + spawn_local(fut); + } + async fn fetch(request: Self) -> FetchResult { let window = web_sys::window().expect("!window"); let uri = request.uri; @@ -222,6 +280,31 @@ impl FetchRequest { Ok((status_code, resp_str)) } + /// The private non-Send method that is called in a spawned future. + async fn fetch_stream(request: Self) -> FetchResult> { + let uri = request.uri.clone(); + let (status_code, js_response) = Self::fetch(request).await?; + + let resp_stream = match js_response.body() { + Some(txt) => txt, + None => { + let error = format!("Expected readable stream, found {:?}:", js_response,); + return MmError::err(SlurpError::ErrorDeserializing { uri, error }); + }, + }; + + let builder = Response::builder().status(status_code); + let (builder, content_type) = set_response_headers(builder, &js_response)?; + let content_type = content_type.ok_or(MmError::new(SlurpError::Internal("intaernal Error".to_string())))?; + let body = + ResponseBody::new(resp_stream, &content_type).map_to_mm(|err| SlurpError::Internal(format!("{err:?}")))?; + let res = builder + .body(body) + .map_to_mm(|err| SlurpError::Internal(err.to_string()))?; + + Ok((status_code, res)) + } + /// The private non-Send method that is called in a spawned future. async fn fetch_array(request: Self) -> FetchResult> { let uri = request.uri.clone(); diff --git a/mm2src/mm2_net/src/wasm_ws.rs b/mm2src/mm2_net/src/wasm/wasm_ws.rs similarity index 100% rename from mm2src/mm2_net/src/wasm_ws.rs rename to mm2src/mm2_net/src/wasm/wasm_ws.rs From ae2f775dda21ec64205aae50226c51d4d41f102f Mon Sep 17 00:00:00 2001 From: borngraced Date: Fri, 20 Oct 2023 06:09:23 +0100 Subject: [PATCH 06/68] minor changes Signed-off-by: borngraced --- Cargo.lock | 1 - mm2src/coins/z_coin/z_rpc.rs | 12 ------------ mm2src/mm2_net/Cargo.toml | 2 -- mm2src/mm2_net/src/wasm/wasm_http.rs | 5 ++++- 4 files changed, 4 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e2c00ed7dd..f3f69bc932 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4382,7 +4382,6 @@ dependencies = [ "bytes 1.1.0", "cfg-if 1.0.0", "common", - "derive_more", "ethkey", "futures 0.3.15", "futures-util", diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 3c1c94dd88..7da659e714 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -497,18 +497,6 @@ pub(super) async fn init_light_client<'a>( )) } -//#[cfg(target_arch = "wasm32")] -//#[allow(unused)] -//pub(super) async fn init_light_client<'a>( -// _builder: &ZCoinBuilder<'a>, -// _lightwalletd_urls: Vec, -// _blocks_db: BlockDbImpl, -// _sync_params: &Option, -// z_spending_key: &ExtendedSpendingKey, -//) -> Result<(AsyncMutex, WalletDbShared), MmError> { -// todo!() -//} - #[cfg(not(target_arch = "wasm32"))] pub(super) async fn init_native_client<'a>( builder: &ZCoinBuilder<'a>, diff --git a/mm2src/mm2_net/Cargo.toml b/mm2src/mm2_net/Cargo.toml index 7680f217d8..2708a271ab 100644 --- a/mm2src/mm2_net/Cargo.toml +++ b/mm2src/mm2_net/Cargo.toml @@ -10,7 +10,6 @@ doctest = false async-trait = "0.1" bytes = "1.1" cfg-if = "1.0" -derive_more = "0.99" common = { path = "../common" } ethkey = { git = "https://github.com/KomodoPlatform/mm2-parity-ethereum.git" } futures = { version = "0.3", package = "futures", features = ["compat", "async-await", "thread-pool"] } @@ -41,7 +40,6 @@ web-sys = { version = "0.3.55", features = ["console", "CloseEvent", "DomExcepti "IdbCursor", "IdbCursorWithValue", "IdbFactory", "IdbIndex", "IdbIndexParameters", "IdbObjectStore", "IdbObjectStoreParameters", "IdbOpenDbRequest", "IdbKeyRange", "IdbTransaction", "IdbTransactionMode", "IdbVersionChangeEvent", "MessageEvent","ReadableStream", "WebSocket"] } wasm-streams = "0.3.0" - [target.'cfg(not(target_arch = "wasm32"))'.dependencies] futures-util = { version = "0.3" } hyper = { version = "0.14.26", features = ["client", "http2", "server", "tcp"] } diff --git a/mm2src/mm2_net/src/wasm/wasm_http.rs b/mm2src/mm2_net/src/wasm/wasm_http.rs index aed5fed32a..cf296a4898 100644 --- a/mm2src/mm2_net/src/wasm/wasm_http.rs +++ b/mm2src/mm2_net/src/wasm/wasm_http.rs @@ -295,7 +295,10 @@ impl FetchRequest { let builder = Response::builder().status(status_code); let (builder, content_type) = set_response_headers(builder, &js_response)?; - let content_type = content_type.ok_or(MmError::new(SlurpError::Internal("intaernal Error".to_string())))?; + let content_type = content_type.ok_or(MmError::new(SlurpError::Transport { + uri, + error: "MissingContentType".to_string(), + }))?; let body = ResponseBody::new(resp_stream, &content_type).map_to_mm(|err| SlurpError::Internal(format!("{err:?}")))?; let res = builder From 1c95fa85e945637c49144e9ac5b8c85d65f2db6c Mon Sep 17 00:00:00 2001 From: borngraced Date: Fri, 20 Oct 2023 17:00:00 +0100 Subject: [PATCH 07/68] remove unused Signed-off-by: borngraced --- Cargo.lock | 1 + mm2src/coins/z_coin/storage/blockdb/mod.rs | 30 +++++++------- .../z_coin/storage/walletdb/wasm/storage.rs | 5 ++- mm2src/coins/z_coin/z_coin_errors.rs | 8 ++++ mm2src/coins/z_coin/z_rpc.rs | 40 ++----------------- mm2src/mm2_net/Cargo.toml | 2 + 6 files changed, 34 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f3f69bc932..e2c00ed7dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4382,6 +4382,7 @@ dependencies = [ "bytes 1.1.0", "cfg-if 1.0.0", "common", + "derive_more", "ethkey", "futures 0.3.15", "futures-util", diff --git a/mm2src/coins/z_coin/storage/blockdb/mod.rs b/mm2src/coins/z_coin/storage/blockdb/mod.rs index 2d9e586a50..a8fad19ffe 100644 --- a/mm2src/coins/z_coin/storage/blockdb/mod.rs +++ b/mm2src/coins/z_coin/storage/blockdb/mod.rs @@ -102,14 +102,11 @@ mod native_tests { mod wasm_tests { use crate::z_coin::storage::blockdb::block_db_storage_tests::{test_insert_block_and_get_latest_block_impl, test_rewind_to_height_impl}; - // use crate::z_coin::z_rpc::{LightRpcClient, ZRpcOps}; - // use common::log::info; - // use common::log::wasm_log::register_wasm_log; + use crate::z_coin::z_rpc::{LightRpcClient, ZRpcOps}; + use common::log::info; + use common::log::wasm_log::register_wasm_log; use wasm_bindgen_test::*; - // use crate::z_coin::z_rpc::z_coin_grpc::compact_tx_streamer_client::CompactTxStreamerClient; - // use crate::z_coin::z_rpc::z_coin_grpc::ChainSpec; - wasm_bindgen_test_configure!(run_in_browser); #[wasm_bindgen_test] @@ -118,13 +115,16 @@ mod wasm_tests { #[wasm_bindgen_test] async fn test_rewind_to_height() { test_rewind_to_height_impl().await } - // #[wasm_bindgen_test] - // async fn test_transport() { - // register_wasm_log(); - // let mut client = LightRpcClient::new(vec!["http://localhost:8081".to_string()]) - // .await - // .unwrap(); - // let latest_block = client.get_block_height().await; - // info!("LATEST BLOCK: {latest_block:?}"); - // } + #[wasm_bindgen_test] + async fn test_transport() { + register_wasm_log(); + let mut client = LightRpcClient::new(vec![ + "https://piratelightd4.cryptoforge.cc:443".to_string(), + "https://electrum1.cipig.net:9447".to_string(), + ]) + .await + .unwrap(); + let latest_block = client.get_block_height().await; + info!("LATEST BLOCK: {latest_block:?}"); + } } diff --git a/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs b/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs index 548d6b7d07..6c0ecb752e 100644 --- a/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs +++ b/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs @@ -145,7 +145,6 @@ impl<'a> WalletIndexedDb { Ok(db) } - #[allow(unused)] async fn lock_db(&self) -> WalletDbRes> { self.db .get_or_initialize() @@ -153,6 +152,10 @@ impl<'a> WalletIndexedDb { .mm_err(|err| ZcoinStorageError::DbError(err.to_string())) } + pub fn get_update_ops(&self) -> MmResult { + Ok(DataConnStmtCacheWasm(self.clone())) + } + pub(crate) async fn init_accounts_table( &self, extfvks: &[ExtendedFullViewingKey], diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index 408015f8c4..77457067de 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -31,6 +31,10 @@ pub enum UpdateBlocksCacheErr { DecodeError(String), } +impl From for UpdateBlocksCacheErr { + fn from(err: ZcoinStorageError) -> Self { UpdateBlocksCacheErr::ZcashDBError(err.to_string()) } +} + impl From for UpdateBlocksCacheErr { fn from(err: tonic::Status) -> Self { UpdateBlocksCacheErr::GrpcError(err) } } @@ -403,6 +407,10 @@ pub enum ZcoinStorageError { NotSupported(String), } +impl From for ZcoinStorageError { + fn from(err: UpdateBlocksCacheErr) -> Self { ZcoinStorageError::DbError(err.to_string()) } +} + #[cfg(target_arch = "wasm32")] use mm2_db::indexed_db::{CursorError, DbTransactionError, InitDbError}; use mm2_err_handle::mm_error::MmError; diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 7da659e714..c2495ebed4 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -1,10 +1,13 @@ use super::{z_coin_errors::*, BlockDbImpl, CheckPointBlockInfo, WalletDbShared, ZCoinBuilder, ZcoinConsensusParams}; use crate::utxo::rpc_clients::NO_TX_ERROR_CODE; use crate::utxo::utxo_builder::{UtxoCoinBuilderCommonOps, DAY_IN_SECONDS}; +use crate::z_coin::storage::{BlockProcessingMode, DataConnStmtCacheWrapper}; use crate::z_coin::SyncStartPoint; +use crate::RpcCommonOps; use async_trait::async_trait; use common::executor::Timer; use common::executor::{spawn_abortable, AbortOnDropHandle}; +use common::log::LogOnError; use common::log::{debug, error, info}; use common::now_sec; use futures::channel::mpsc::channel; @@ -22,6 +25,7 @@ use std::pin::Pin; use std::str::FromStr; use std::sync::Arc; use z_coin_grpc::{BlockId, BlockRange, TreeState, TxFilter}; +use zcash_extras::{WalletRead, WalletWrite}; use zcash_primitives::consensus::BlockHeight; use zcash_primitives::transaction::TxId; use zcash_primitives::zip32::ExtendedSpendingKey; @@ -29,24 +33,20 @@ use zcash_primitives::zip32::ExtendedSpendingKey; pub(crate) mod z_coin_grpc { tonic::include_proto!("cash.z.wallet.sdk.rpc"); } -use crate::RpcCommonOps; use z_coin_grpc::compact_tx_streamer_client::CompactTxStreamerClient; use z_coin_grpc::ChainSpec; cfg_native!( use crate::ZTransaction; use crate::utxo::rpc_clients::{UtxoRpcClientOps}; - use crate::z_coin::storage::{BlockProcessingMode, DataConnStmtCacheWrapper}; use crate::z_coin::z_coin_errors::{ZcoinStorageError, ValidateBlocksError}; use crate::utxo::rpc_clients::NativeClient; use futures::compat::Future01CompatExt; use group::GroupEncoding; use http::Uri; - use common::log::LogOnError; use tonic::transport::{Channel, ClientTlsConfig}; use tonic::codegen::StdError; - use zcash_extras::{WalletRead, WalletWrite}; use z_coin_grpc::{CompactBlock as TonicCompactBlock, CompactOutput as TonicCompactOutput, CompactSpend as TonicCompactSpend, CompactTx as TonicCompactTx}; @@ -632,7 +632,6 @@ pub struct SaplingSyncLoopHandle { first_sync_block: FirstSyncBlock, } -#[cfg(not(target_arch = "wasm32"))] impl SaplingSyncLoopHandle { fn first_sync_block(&self) -> FirstSyncBlock { self.first_sync_block.clone() } @@ -772,31 +771,6 @@ impl SaplingSyncLoopHandle { } } -#[cfg(target_arch = "wasm32")] -#[allow(unused)] -impl SaplingSyncLoopHandle { - fn notify_blocks_cache_status(&mut self, _current_scanned_block: u64, _latest_block: u64) { todo!() } - - fn notify_building_wallet_db(&mut self, _current_scanned_block: u64, _latest_block: u64) { todo!() } - - fn notify_on_error(&mut self, _error: String) { todo!() } - - fn notify_sync_finished(&mut self) { todo!() } - - async fn update_blocks_cache( - &mut self, - _rpc: &mut (dyn ZRpcOps + Send), - ) -> Result<(), MmError> { - todo!() - } - - /// Scans cached blocks, validates the chain and updates WalletDb. - /// For more notes on the process, check https://github.com/zcash/librustzcash/blob/master/zcash_client_backend/src/data_api/chain.rs#L2 - fn scan_blocks(&mut self) -> Result<(), MmError> { todo!() } - - async fn check_watch_for_tx_existence(&mut self, _rpc: &mut (dyn ZRpcOps + Send)) { todo!() } -} - /// For more info on shielded light client protocol, please check the https://zips.z.cash/zip-0307 /// /// It's important to note that unlike standard UTXOs, shielded outputs are not spendable until the transaction is confirmed. @@ -818,7 +792,6 @@ impl SaplingSyncLoopHandle { /// 6. Once the transaction is generated and sent, `SaplingSyncRespawnGuard::watch_for_tx` is called to update `SaplingSyncLoopHandle` state. /// 7. Once the loop is respawned, it will check that broadcast tx is imported (or not available anymore) before stopping in favor of /// next wait_for_gen_tx_blockchain_sync call. -#[cfg(not(target_arch = "wasm32"))] async fn light_wallet_db_sync_loop(mut sync_handle: SaplingSyncLoopHandle, mut client: Box) { info!( "(Re)starting light_wallet_db_sync_loop for {}, blocks per iteration {}, interval in ms {}", @@ -868,11 +841,6 @@ async fn light_wallet_db_sync_loop(mut sync_handle: SaplingSyncLoopHandle, mut c } } -#[cfg(target_arch = "wasm32")] -async fn light_wallet_db_sync_loop(mut _sync_handle: SaplingSyncLoopHandle, mut _client: Box) { - todo!() -} - type SyncWatcher = AsyncReceiver; type NewTxNotifier = AsyncSender)>>; diff --git a/mm2src/mm2_net/Cargo.toml b/mm2src/mm2_net/Cargo.toml index 2708a271ab..7680f217d8 100644 --- a/mm2src/mm2_net/Cargo.toml +++ b/mm2src/mm2_net/Cargo.toml @@ -10,6 +10,7 @@ doctest = false async-trait = "0.1" bytes = "1.1" cfg-if = "1.0" +derive_more = "0.99" common = { path = "../common" } ethkey = { git = "https://github.com/KomodoPlatform/mm2-parity-ethereum.git" } futures = { version = "0.3", package = "futures", features = ["compat", "async-await", "thread-pool"] } @@ -40,6 +41,7 @@ web-sys = { version = "0.3.55", features = ["console", "CloseEvent", "DomExcepti "IdbCursor", "IdbCursorWithValue", "IdbFactory", "IdbIndex", "IdbIndexParameters", "IdbObjectStore", "IdbObjectStoreParameters", "IdbOpenDbRequest", "IdbKeyRange", "IdbTransaction", "IdbTransactionMode", "IdbVersionChangeEvent", "MessageEvent","ReadableStream", "WebSocket"] } wasm-streams = "0.3.0" + [target.'cfg(not(target_arch = "wasm32"))'.dependencies] futures-util = { version = "0.3" } hyper = { version = "0.14.26", features = ["client", "http2", "server", "tcp"] } From 3300927963712bae2d9c0846ff57acbf7131fe37 Mon Sep 17 00:00:00 2001 From: borngraced Date: Sat, 21 Oct 2023 01:48:51 +0100 Subject: [PATCH 08/68] minor changes Signed-off-by: borngraced --- .../eth/web3_transport/http_transport.rs | 2 +- mm2src/coins/lp_price.rs | 2 +- mm2src/coins/nft.rs | 2 +- .../tendermint/rpc/tendermint_wasm_rpc.rs | 2 +- mm2src/coins/z_coin/wasm_transport.rs | 2 +- mm2src/mm2_net/src/grpc_web.rs | 2 +- mm2src/mm2_net/src/transport.rs | 2 +- mm2src/mm2_net/src/wasm/body_stream.rs | 41 +++++------ .../src/wasm/{wasm_http.rs => http.rs} | 68 ++++++++++--------- mm2src/mm2_net/src/wasm/mod.rs | 2 +- 10 files changed, 60 insertions(+), 65 deletions(-) rename mm2src/mm2_net/src/wasm/{wasm_http.rs => http.rs} (91%) diff --git a/mm2src/coins/eth/web3_transport/http_transport.rs b/mm2src/coins/eth/web3_transport/http_transport.rs index 61795d635f..823099f8e5 100644 --- a/mm2src/coins/eth/web3_transport/http_transport.rs +++ b/mm2src/coins/eth/web3_transport/http_transport.rs @@ -298,7 +298,7 @@ async fn send_request_once( event_handlers: &Vec, ) -> Result { use http::header::ACCEPT; - use mm2_net::wasm::wasm_http::FetchRequest; + use mm2_net::wasm::http::FetchRequest; // account for outgoing traffic event_handlers.on_outgoing_request(request_payload.as_bytes()); diff --git a/mm2src/coins/lp_price.rs b/mm2src/coins/lp_price.rs index f4e346c316..65e2279616 100644 --- a/mm2src/coins/lp_price.rs +++ b/mm2src/coins/lp_price.rs @@ -199,7 +199,7 @@ async fn process_price_request(price_url: &str) -> Result Result> { debug!("Fetching price from: {}", price_url); - let (status, headers, body) = mm2_net::wasm::wasm_http::slurp_url(price_url).await?; + let (status, headers, body) = mm2_net::wasm::http::slurp_url(price_url).await?; let (status_code, body, _) = (status, std::str::from_utf8(&body)?.trim().into(), headers); if status_code != StatusCode::OK { return MmError::err(PriceServiceRequestError::HttpProcessError(body)); diff --git a/mm2src/coins/nft.rs b/mm2src/coins/nft.rs index e106de5fe2..e028f64e54 100644 --- a/mm2src/coins/nft.rs +++ b/mm2src/coins/nft.rs @@ -415,7 +415,7 @@ async fn send_request_to_uri(uri: &str) -> MmResult { #[cfg(target_arch = "wasm32")] async fn send_request_to_uri(uri: &str) -> MmResult { - use mm2_net::wasm::wasm_http::FetchRequest; + use mm2_net::wasm::http::FetchRequest; macro_rules! try_or { ($exp:expr, $errtype:ident) => { diff --git a/mm2src/coins/tendermint/rpc/tendermint_wasm_rpc.rs b/mm2src/coins/tendermint/rpc/tendermint_wasm_rpc.rs index 9238801774..866912a2e1 100644 --- a/mm2src/coins/tendermint/rpc/tendermint_wasm_rpc.rs +++ b/mm2src/coins/tendermint/rpc/tendermint_wasm_rpc.rs @@ -7,7 +7,7 @@ use http::header::{ACCEPT, CONTENT_TYPE}; use http::uri::InvalidUri; use http::{StatusCode, Uri}; use mm2_net::transport::SlurpError; -use mm2_net::wasm::wasm_http::FetchRequest; +use mm2_net::wasm::http::FetchRequest; use std::str::FromStr; use tendermint_rpc::endpoint::{abci_info, broadcast}; pub use tendermint_rpc::endpoint::{abci_query::{AbciQuery, Request as AbciRequest}, diff --git a/mm2src/coins/z_coin/wasm_transport.rs b/mm2src/coins/z_coin/wasm_transport.rs index 54d4bf4188..786435efe0 100644 --- a/mm2src/coins/z_coin/wasm_transport.rs +++ b/mm2src/coins/z_coin/wasm_transport.rs @@ -5,7 +5,7 @@ use http::{Request, Response}; use mm2_err_handle::prelude::*; use mm2_net::grpc_web::PostGrpcWebErr; use mm2_net::wasm::body_stream::ResponseBody; -use mm2_net::wasm::wasm_http::FetchRequest; +use mm2_net::wasm::http::FetchRequest; use std::{pin::Pin, task::{Context, Poll}}; use tonic::body::BoxBody; diff --git a/mm2src/mm2_net/src/grpc_web.rs b/mm2src/mm2_net/src/grpc_web.rs index 6a294b9acc..ce53a8bc29 100644 --- a/mm2src/mm2_net/src/grpc_web.rs +++ b/mm2src/mm2_net/src/grpc_web.rs @@ -16,7 +16,7 @@ cfg_native! { cfg_wasm32! { use common::{X_GRPC_WEB, APPLICATION_GRPC_WEB_PROTO}; - use crate::wasm::wasm_http::FetchRequest; + use crate::wasm::http::FetchRequest; } // one byte for the compression flag plus four bytes for the length diff --git a/mm2src/mm2_net/src/transport.rs b/mm2src/mm2_net/src/transport.rs index f263d12ebb..c8da959101 100644 --- a/mm2src/mm2_net/src/transport.rs +++ b/mm2src/mm2_net/src/transport.rs @@ -10,7 +10,7 @@ use serde_json::{Error, Value as Json}; pub use crate::native_http::{slurp_post_json, slurp_req, slurp_req_body, slurp_url, slurp_url_with_headers}; #[cfg(target_arch = "wasm32")] -pub use crate::wasm::wasm_http::{slurp_post_json, slurp_url, slurp_url_with_headers}; +pub use crate::wasm::http::{slurp_post_json, slurp_url, slurp_url_with_headers}; pub type SlurpResult = Result<(StatusCode, HeaderMap, Vec), MmError>; diff --git a/mm2src/mm2_net/src/wasm/body_stream.rs b/mm2src/mm2_net/src/wasm/body_stream.rs index 15d6591d81..710905f488 100644 --- a/mm2src/mm2_net/src/wasm/body_stream.rs +++ b/mm2src/mm2_net/src/wasm/body_stream.rs @@ -20,27 +20,11 @@ use wasm_bindgen::JsCast; use wasm_streams::readable::IntoStream; use web_sys::ReadableStream; -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum Encoding { - Base64, - None, -} - -impl Encoding { - pub fn from_content_type(content_type: &str) -> Result { - match content_type { - APPLICATION_GRPC_WEB_TEXT | APPLICATION_GRPC_WEB_TEXT_PROTO => Ok(Encoding::Base64), - APPLICATION_GRPC_WEB | APPLICATION_GRPC_WEB_PROTO => Ok(Encoding::None), - _ => Err(PostGrpcWebErr::InvalidRequest(content_type.to_owned())), - } - } -} - /// If 8th MSB of a frame is `0` for data and `1` for trailer const TRAILER_BIT: u8 = 0b10000000; pub struct EncodedBytes { - encoding: Encoding, + content_type: String, raw_buf: BytesMut, buf: BytesMut, } @@ -48,12 +32,20 @@ pub struct EncodedBytes { impl EncodedBytes { pub fn new(content_type: &str) -> Result { Ok(Self { - encoding: Encoding::from_content_type(content_type)?, + content_type: content_type.to_string(), raw_buf: BytesMut::new(), buf: BytesMut::new(), }) } + fn is_base64_encoding(&self) -> Result { + match self.content_type.as_str() { + APPLICATION_GRPC_WEB_TEXT | APPLICATION_GRPC_WEB_TEXT_PROTO => Ok(true), + APPLICATION_GRPC_WEB | APPLICATION_GRPC_WEB_PROTO => Ok(false), + _ => Err(PostGrpcWebErr::InvalidRequest(self.content_type.to_owned())), + } + } + // This is to avoid passing a slice of bytes with a length that the base64 // decoder would consider invalid. #[inline] @@ -74,12 +66,11 @@ impl EncodedBytes { } fn append(&mut self, bytes: Bytes) -> Result<(), PostGrpcWebErr> { - match self.encoding { - Encoding::None => self.buf.put(bytes), - Encoding::Base64 => { - self.raw_buf.put(bytes); - self.decode_base64_chunk()?; - }, + if self.is_base64_encoding()? == true { + self.raw_buf.put(bytes); + self.decode_base64_chunk()?; + } else { + self.buf.put(bytes) } Ok(()) @@ -348,7 +339,7 @@ impl Default for ResponseBody { Self { body_stream: BodyStream::empty(), buf: EncodedBytes { - encoding: Encoding::None, + content_type: Default::default(), raw_buf: BytesMut::new(), buf: BytesMut::new(), }, diff --git a/mm2src/mm2_net/src/wasm/wasm_http.rs b/mm2src/mm2_net/src/wasm/http.rs similarity index 91% rename from mm2src/mm2_net/src/wasm/wasm_http.rs rename to mm2src/mm2_net/src/wasm/http.rs index cf296a4898..36bfd1cca6 100644 --- a/mm2src/mm2_net/src/wasm/wasm_http.rs +++ b/mm2src/mm2_net/src/wasm/http.rs @@ -49,7 +49,11 @@ pub async fn slurp_post_json(url: &str, body: String) -> SlurpResult { .map(|(status_code, response)| (status_code, HeaderMap::new(), response.into_bytes())) } -fn set_response_headers( +/// Sets the response headers and extracts the content type. +/// +/// This function takes a `Builder` for a response and a `JsResponse` from which it extracts +/// the headers and the content type. +fn set_response_headers_and_content_type( mut result: Builder, response: &JsResponse, ) -> Result<(Builder, Option), MmError> { @@ -162,7 +166,7 @@ impl FetchRequest { pub async fn request_stream(self) -> FetchResult> { let (tx, rx) = oneshot::channel(); - Self::spawn_fetch_stream(self, tx); + Self::spawn_fetch_stream_response(self, tx); match rx.await { Ok(res) => res, Err(_e) => MmError::err(SlurpError::Internal("Spawned future has been canceled".to_owned())), @@ -191,9 +195,9 @@ impl FetchRequest { spawn_local(fut); } - fn spawn_fetch_stream(request: Self, tx: oneshot::Sender>>) { + fn spawn_fetch_stream_response(request: Self, tx: oneshot::Sender>>) { let fut = async move { - let result = Self::fetch_stream(request).await; + let result = Self::fetch_and_stream_response(request).await; tx.send(result).ok(); }; @@ -280,34 +284,6 @@ impl FetchRequest { Ok((status_code, resp_str)) } - /// The private non-Send method that is called in a spawned future. - async fn fetch_stream(request: Self) -> FetchResult> { - let uri = request.uri.clone(); - let (status_code, js_response) = Self::fetch(request).await?; - - let resp_stream = match js_response.body() { - Some(txt) => txt, - None => { - let error = format!("Expected readable stream, found {:?}:", js_response,); - return MmError::err(SlurpError::ErrorDeserializing { uri, error }); - }, - }; - - let builder = Response::builder().status(status_code); - let (builder, content_type) = set_response_headers(builder, &js_response)?; - let content_type = content_type.ok_or(MmError::new(SlurpError::Transport { - uri, - error: "MissingContentType".to_string(), - }))?; - let body = - ResponseBody::new(resp_stream, &content_type).map_to_mm(|err| SlurpError::Internal(format!("{err:?}")))?; - let res = builder - .body(body) - .map_to_mm(|err| SlurpError::Internal(err.to_string()))?; - - Ok((status_code, res)) - } - /// The private non-Send method that is called in a spawned future. async fn fetch_array(request: Self) -> FetchResult> { let uri = request.uri.clone(); @@ -335,6 +311,34 @@ impl FetchRequest { Ok((status_code, array.to_vec())) } + + /// The private non-Send method that is called in a spawned future. + async fn fetch_and_stream_response(request: Self) -> FetchResult> { + let uri = request.uri.clone(); + let (status_code, js_response) = Self::fetch(request).await?; + + let resp_stream = match js_response.body() { + Some(txt) => txt, + None => { + let error = format!("Expected readable stream, found {:?}:", js_response,); + return MmError::err(SlurpError::ErrorDeserializing { uri, error }); + }, + }; + + let builder = Response::builder().status(status_code); + let (builder, content_type) = set_response_headers_and_content_type(builder, &js_response)?; + let content_type = + content_type.ok_or_else(|| MmError::new(SlurpError::InvalidRequest("MissingContentType".to_string())))?; + let body = ResponseBody::new(resp_stream, &content_type) + .map_to_mm(|err| SlurpError::InvalidRequest(format!("{err:?}")))?; + + Ok(( + status_code, + builder + .body(body) + .map_to_mm(|err| SlurpError::InvalidRequest(err.to_string()))?, + )) + } } enum FetchMethod { diff --git a/mm2src/mm2_net/src/wasm/mod.rs b/mm2src/mm2_net/src/wasm/mod.rs index a5583bf87c..7ac6d5aff0 100644 --- a/mm2src/mm2_net/src/wasm/mod.rs +++ b/mm2src/mm2_net/src/wasm/mod.rs @@ -1,3 +1,3 @@ pub mod body_stream; -pub mod wasm_http; +pub mod http; pub mod wasm_ws; From 1af58989a60d0746a2325759d143178f0573c3f7 Mon Sep 17 00:00:00 2001 From: borngraced Date: Sun, 22 Oct 2023 05:03:13 +0100 Subject: [PATCH 09/68] some refactorings to TonicClient imp Signed-off-by: borngraced --- Cargo.lock | 1 + mm2src/coins/z_coin.rs | 1 - mm2src/coins/z_coin/storage/blockdb/mod.rs | 27 +++++----- mm2src/coins/z_coin/wasm_transport.rs | 55 ------------------- mm2src/coins/z_coin/z_rpc.rs | 10 ++-- mm2src/mm2_net/Cargo.toml | 1 + mm2src/mm2_net/src/wasm/http.rs | 63 +++++++++++++++++++--- 7 files changed, 77 insertions(+), 81 deletions(-) delete mode 100644 mm2src/coins/z_coin/wasm_transport.rs diff --git a/Cargo.lock b/Cargo.lock index e2c00ed7dd..14b6f653d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4404,6 +4404,7 @@ dependencies = [ "thiserror", "tokio", "tokio-rustls", + "tonic", "tower-service", "wasm-bindgen", "wasm-bindgen-futures", diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 1f591f2dd7..19a9ca5710 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -103,7 +103,6 @@ use crate::z_coin::storage::{BlockDbImpl, WalletDbShared}; pub use z_coin_errors::*; pub mod storage; -#[cfg(target_arch = "wasm32")] pub mod wasm_transport; #[cfg(all(test, feature = "zhtlc-native-tests"))] mod z_coin_native_tests; diff --git a/mm2src/coins/z_coin/storage/blockdb/mod.rs b/mm2src/coins/z_coin/storage/blockdb/mod.rs index a8fad19ffe..67fc746c47 100644 --- a/mm2src/coins/z_coin/storage/blockdb/mod.rs +++ b/mm2src/coins/z_coin/storage/blockdb/mod.rs @@ -102,9 +102,9 @@ mod native_tests { mod wasm_tests { use crate::z_coin::storage::blockdb::block_db_storage_tests::{test_insert_block_and_get_latest_block_impl, test_rewind_to_height_impl}; - use crate::z_coin::z_rpc::{LightRpcClient, ZRpcOps}; - use common::log::info; - use common::log::wasm_log::register_wasm_log; + // use crate::z_coin::z_rpc::{LightRpcClient, ZRpcOps}; + // use common::log::info; + // use common::log::wasm_log::register_wasm_log; use wasm_bindgen_test::*; wasm_bindgen_test_configure!(run_in_browser); @@ -115,16 +115,13 @@ mod wasm_tests { #[wasm_bindgen_test] async fn test_rewind_to_height() { test_rewind_to_height_impl().await } - #[wasm_bindgen_test] - async fn test_transport() { - register_wasm_log(); - let mut client = LightRpcClient::new(vec![ - "https://piratelightd4.cryptoforge.cc:443".to_string(), - "https://electrum1.cipig.net:9447".to_string(), - ]) - .await - .unwrap(); - let latest_block = client.get_block_height().await; - info!("LATEST BLOCK: {latest_block:?}"); - } + // #[wasm_bindgen_test] + // async fn test_transport() { + // register_wasm_log(); + // let mut client = LightRpcClient::new(vec!["http://127.0.0.1:8082".to_string()]) + // .await + // .unwrap(); + // let tree_state = client.get_tree_state(663164).await; + // info!("LATEST BLOCK: {tree_state:?}"); + // } } diff --git a/mm2src/coins/z_coin/wasm_transport.rs b/mm2src/coins/z_coin/wasm_transport.rs deleted file mode 100644 index 786435efe0..0000000000 --- a/mm2src/coins/z_coin/wasm_transport.rs +++ /dev/null @@ -1,55 +0,0 @@ -use common::{APPLICATION_GRPC_WEB_PROTO, X_GRPC_WEB}; -use futures_util::Future; -use http::header::{ACCEPT, CONTENT_TYPE}; -use http::{Request, Response}; -use mm2_err_handle::prelude::*; -use mm2_net::grpc_web::PostGrpcWebErr; -use mm2_net::wasm::body_stream::ResponseBody; -use mm2_net::wasm::http::FetchRequest; -use std::{pin::Pin, - task::{Context, Poll}}; -use tonic::body::BoxBody; -use tonic::codegen::Body; -use tower_service::Service; - -#[derive(Clone)] -pub struct Client(String); - -impl Client { - pub fn new(url: String) -> Self { Self(url) } -} - -impl Service> for Client { - type Response = Response; - - type Error = MmError; - - type Future = Pin> + Send + 'static>>; - - fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } - - fn call(&mut self, request: Request) -> Self::Future { Box::pin(call(self.0.clone(), request)) } -} - -async fn call(mut base_url: String, request: Request) -> MmResult, PostGrpcWebErr> { - base_url.push_str(&request.uri().to_string()); - - let body = request - .into_body() - .data() - .await - .transpose() - .map_err(|err| PostGrpcWebErr::Status(err.to_string()))?; - let body = body.ok_or(MmError::new(PostGrpcWebErr::InvalidRequest( - "Invalid request body".to_string(), - )))?; - Ok(FetchRequest::post(&base_url) - .body_bytes(body.to_vec()) - .header(CONTENT_TYPE.as_str(), APPLICATION_GRPC_WEB_PROTO) - .header(ACCEPT.as_str(), APPLICATION_GRPC_WEB_PROTO) - // https://github.com/grpc/grpc-web/issues/85#issue-217223001 - .header(X_GRPC_WEB, "1") - .request_stream() - .await? - .1) -} diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index c2495ebed4..b3ace9891c 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -53,7 +53,7 @@ cfg_native!( ); cfg_wasm32!( - use crate::z_coin::wasm_transport::Client as WasmClient; + use mm2_net::wasm::http::TonicClient; ); /// ZRpcOps trait provides asynchronous methods for performing various operations related to @@ -95,7 +95,7 @@ pub trait ZRpcOps { #[cfg(not(target_arch = "wasm32"))] type RpcClientType = Channel; #[cfg(target_arch = "wasm32")] -type RpcClientType = WasmClient; +type RpcClientType = TonicClient; pub struct LightRpcClient { rpc_clients: AsyncMutex>>, @@ -137,7 +137,7 @@ impl LightRpcClient { ); cfg_wasm32!( - let client = WasmClient::new(url.to_string()); + let client = TonicClient::new(url.to_string()); let client = CompactTxStreamerClient::new(client.into()); ); @@ -168,7 +168,9 @@ impl RpcCommonOps for LightRpcClient { for (i, mut client) in clients.clone().into_iter().enumerate() { let request = tonic::Request::new(ChainSpec {}); // use get_latest_block method as a health check - if client.get_latest_block(request).await.is_ok() { + let latest = client.get_latest_block(request).await; + info!("{latest:?}"); + if latest.is_ok() { clients.rotate_left(i); return Ok(client); } diff --git a/mm2src/mm2_net/Cargo.toml b/mm2src/mm2_net/Cargo.toml index 7680f217d8..7895cb70c6 100644 --- a/mm2src/mm2_net/Cargo.toml +++ b/mm2src/mm2_net/Cargo.toml @@ -33,6 +33,7 @@ http-body = "0.4" httparse = "1.8.0" js-sys = "0.3.27" pin-project = "1.0.10" +tonic = { version = "0.7", default-features = false, features = ["prost", "codegen"] } tower-service = "0.3" wasm-bindgen = "0.2.86" wasm-bindgen-test = { version = "0.3.2" } diff --git a/mm2src/mm2_net/src/wasm/http.rs b/mm2src/mm2_net/src/wasm/http.rs index 36bfd1cca6..195708c01d 100644 --- a/mm2src/mm2_net/src/wasm/http.rs +++ b/mm2src/mm2_net/src/wasm/http.rs @@ -1,19 +1,27 @@ +use crate::grpc_web::PostGrpcWebErr; use crate::transport::{SlurpError, SlurpResult}; use crate::wasm::body_stream::ResponseBody; + use common::executor::spawn_local; -use common::{stringify_js_error, APPLICATION_JSON}; +use common::{stringify_js_error, APPLICATION_GRPC_WEB_PROTO, APPLICATION_JSON, X_GRPC_WEB}; use futures::channel::oneshot; -use http::header::CONTENT_TYPE; +use futures_util::Future; +use http::header::{ACCEPT, CONTENT_TYPE}; use http::response::Builder; -use http::{HeaderMap, Response, StatusCode}; +use http::{HeaderMap, Request, Response, StatusCode}; use js_sys::Array; use js_sys::Uint8Array; use mm2_err_handle::prelude::*; use std::collections::HashMap; +use std::{pin::Pin, + task::{Context, Poll}}; +use tonic::body::BoxBody; +use tonic::codegen::Body; +use tower_service::Service; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use wasm_bindgen_futures::JsFuture; -use web_sys::{Request, RequestInit, RequestMode, Response as JsResponse}; +use web_sys::{Request as JsRequest, RequestInit, RequestMode, Response as JsResponse}; /// The result containing either a pair of (HTTP status code, body) or a stringified error. pub type FetchResult = Result<(StatusCode, T), MmError>; @@ -164,7 +172,7 @@ impl FetchRequest { } } - pub async fn request_stream(self) -> FetchResult> { + pub async fn request_stream_response(self) -> FetchResult> { let (tx, rx) = oneshot::channel(); Self::spawn_fetch_stream_response(self, tx); match rx.await { @@ -218,7 +226,7 @@ impl FetchRequest { req_init.mode(mode); } - let js_request = Request::new_with_str_and_init(&uri, &req_init) + let js_request = JsRequest::new_with_str_and_init(&uri, &req_init) .map_to_mm(|e| SlurpError::Internal(stringify_js_error(&e)))?; for (hkey, hval) in request.headers { js_request @@ -372,6 +380,49 @@ impl RequestBody { } } +#[derive(Clone)] +pub struct TonicClient(String); + +impl TonicClient { + pub fn new(url: String) -> Self { Self(url) } +} + +impl Service> for TonicClient { + type Response = Response; + + type Error = MmError; + + type Future = Pin> + Send + 'static>>; + + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } + + fn call(&mut self, request: Request) -> Self::Future { Box::pin(call(self.0.clone(), request)) } +} + +async fn call(mut base_url: String, request: Request) -> MmResult, PostGrpcWebErr> { + base_url.push_str(&request.uri().to_string()); + + let body = request + .into_body() + .data() + .await + .transpose() + .map_err(|err| PostGrpcWebErr::Status(err.to_string()))?; + let body = body.ok_or(MmError::new(PostGrpcWebErr::InvalidRequest( + "Invalid request body".to_string(), + )))?; + + Ok(FetchRequest::post(&base_url) + .body_bytes(body.to_vec()) + .header(CONTENT_TYPE.as_str(), APPLICATION_GRPC_WEB_PROTO) + .header(ACCEPT.as_str(), APPLICATION_GRPC_WEB_PROTO) + // https://github.com/grpc/grpc-web/issues/85#issue-217223001 + .header(X_GRPC_WEB, "1") + .request_stream_response() + .await? + .1) +} + mod tests { use super::*; use wasm_bindgen_test::*; From abb873ef91c5433bacbdaed319c0fe4948a742a6 Mon Sep 17 00:00:00 2001 From: borngraced Date: Sun, 22 Oct 2023 22:20:44 +0100 Subject: [PATCH 10/68] fix wasm clippy warnings Signed-off-by: borngraced --- mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs | 4 ++-- mm2src/coins/z_coin/z_rpc.rs | 3 +-- mm2src/mm2_net/src/wasm/body_stream.rs | 2 +- mm2src/mm2_net/src/wasm/http.rs | 5 +---- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs b/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs index 6c0ecb752e..895d111c14 100644 --- a/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs +++ b/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs @@ -1225,12 +1225,12 @@ impl WalletRead for WalletIndexedDb { let mut unspent_notes = vec![]; for (id, value, note, sum) in &final_note { if **sum < i64::from(target_value) { - unspent_notes.push((*id, *value, note.clone(), *sum)) + unspent_notes.push((*id, *value, *note, *sum)) } } if let Some(note) = final_note.iter().find(|(_, _, _, sum)| **sum >= target_value.into()) { - unspent_notes.push(note.clone()); + unspent_notes.push(*note); }; // Step 4: Get witnesses for selected notes diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index b3ace9891c..d0c5ec52e6 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -137,8 +137,7 @@ impl LightRpcClient { ); cfg_wasm32!( - let client = TonicClient::new(url.to_string()); - let client = CompactTxStreamerClient::new(client.into()); + let client = CompactTxStreamerClient::new(TonicClient::new(url.to_string())); ); rpc_clients.push(client); diff --git a/mm2src/mm2_net/src/wasm/body_stream.rs b/mm2src/mm2_net/src/wasm/body_stream.rs index 710905f488..584d208084 100644 --- a/mm2src/mm2_net/src/wasm/body_stream.rs +++ b/mm2src/mm2_net/src/wasm/body_stream.rs @@ -66,7 +66,7 @@ impl EncodedBytes { } fn append(&mut self, bytes: Bytes) -> Result<(), PostGrpcWebErr> { - if self.is_base64_encoding()? == true { + if self.is_base64_encoding()? { self.raw_buf.put(bytes); self.decode_base64_chunk()?; } else { diff --git a/mm2src/mm2_net/src/wasm/http.rs b/mm2src/mm2_net/src/wasm/http.rs index 195708c01d..2e6f148bfb 100644 --- a/mm2src/mm2_net/src/wasm/http.rs +++ b/mm2src/mm2_net/src/wasm/http.rs @@ -408,15 +408,12 @@ async fn call(mut base_url: String, request: Request) -> MmResult Date: Tue, 24 Oct 2023 19:04:23 +0100 Subject: [PATCH 11/68] activate_z_coin_light unit test wasm Signed-off-by: borngraced --- mm2src/mm2_main/src/wasm_tests.rs | 72 ++++++++++++++++++++++++-- mm2src/mm2_net/src/wasm/body_stream.rs | 22 ++++---- 2 files changed, 79 insertions(+), 15 deletions(-) diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index 680ecb3667..2888c0f6bb 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -1,17 +1,28 @@ use crate::mm2::lp_init; use common::executor::{spawn, Timer}; use common::log::wasm_log::register_wasm_log; +use common::wait_until_ms; use crypto::StandardHDCoinAddress; +use gstuff::now_ms; use mm2_core::mm_ctx::MmArc; +use mm2_number::BigDecimal; use mm2_rpc::data::legacy::OrderbookResponse; use mm2_test_helpers::electrums::{morty_electrums, rick_electrums}; -use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, morty_conf, rick_conf, start_swaps, - test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, MarketMakerIt, - Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, MORTY, RICK}; +use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init_z_coin_light, init_z_coin_status, + morty_conf, rick_conf, start_swaps, test_qrc20_history_impl, + wait_for_swaps_finish_and_check_status, zombie_conf, MarketMakerIt, + Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, MORTY, RICK, + ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, ZOMBIE_TICKER}; use mm2_test_helpers::get_passphrase; +use mm2_test_helpers::structs::{EnableCoinBalance, InitTaskResult, InitZcoinStatus, RpcV2Response, + ZCoinActivationResult}; use serde_json::json; +use serde_json::{self as json}; use wasm_bindgen_test::wasm_bindgen_test; +const ZOMBIE_TEST_BALANCE_SEED: &str = "zombie test seed"; +const ARRR_TEST_ACTIVATION_SEED: &str = "arrr test activation seed"; + /// Starts the WASM version of MM. fn wasm_start(ctx: MmArc) { spawn(async move { @@ -182,3 +193,58 @@ async fn trade_test_rick_and_morty() { ) .await; } + +pub async fn enable_z_coin_light( + mm: &MarketMakerIt, + coin: &str, + electrums: &[&str], + lightwalletd_urls: &[&str], + starting_date: Option, + account: Option, +) -> ZCoinActivationResult { + let init = init_z_coin_light(mm, coin, electrums, lightwalletd_urls, starting_date, account).await; + let init: RpcV2Response = json::from_value(init).unwrap(); + let timeout = wait_until_ms(60000); + + loop { + if now_ms() > timeout { + panic!("{} initialization timed out", coin); + } + + let status = init_z_coin_status(mm, init.result.task_id).await; + println!("Status {}", json::to_string(&status).unwrap()); + let status: RpcV2Response = json::from_value(status).unwrap(); + match status.result { + InitZcoinStatus::Ok(result) => break result, + InitZcoinStatus::Error(e) => panic!("{} initialization error {:?}", coin, e), + _ => Timer::sleep(1.).await, + } + } +} + +#[wasm_bindgen_test] +async fn activate_z_coin_light() { + register_wasm_log(); + let coins = json!([zombie_conf()]); + + let conf = Mm2TestConf::seednode(ZOMBIE_TEST_BALANCE_SEED, &coins); + let mm = MarketMakerIt::start_async(conf.conf, conf.rpc_password, Some(wasm_start)) + .await + .unwrap(); + + let activation_result = enable_z_coin_light( + &mm, + ZOMBIE_TICKER, + ZOMBIE_ELECTRUMS, + ZOMBIE_LIGHTWALLETD_URLS, + None, + None, + ) + .await; + + let balance = match activation_result.wallet_balance { + EnableCoinBalance::Iguana(iguana) => iguana, + _ => panic!("Expected EnableCoinBalance::Iguana"), + }; + assert_eq!(balance.balance.spendable, BigDecimal::default()); +} diff --git a/mm2src/mm2_net/src/wasm/body_stream.rs b/mm2src/mm2_net/src/wasm/body_stream.rs index 584d208084..b1ae0e3c63 100644 --- a/mm2src/mm2_net/src/wasm/body_stream.rs +++ b/mm2src/mm2_net/src/wasm/body_stream.rs @@ -24,28 +24,26 @@ use web_sys::ReadableStream; const TRAILER_BIT: u8 = 0b10000000; pub struct EncodedBytes { - content_type: String, + is_base64: bool, raw_buf: BytesMut, buf: BytesMut, } impl EncodedBytes { pub fn new(content_type: &str) -> Result { + let is_base64 = match content_type { + APPLICATION_GRPC_WEB_TEXT | APPLICATION_GRPC_WEB_TEXT_PROTO => true, + APPLICATION_GRPC_WEB | APPLICATION_GRPC_WEB_PROTO => false, + _ => return Err(PostGrpcWebErr::InvalidRequest(content_type.to_owned())), + }; + Ok(Self { - content_type: content_type.to_string(), + is_base64, raw_buf: BytesMut::new(), buf: BytesMut::new(), }) } - fn is_base64_encoding(&self) -> Result { - match self.content_type.as_str() { - APPLICATION_GRPC_WEB_TEXT | APPLICATION_GRPC_WEB_TEXT_PROTO => Ok(true), - APPLICATION_GRPC_WEB | APPLICATION_GRPC_WEB_PROTO => Ok(false), - _ => Err(PostGrpcWebErr::InvalidRequest(self.content_type.to_owned())), - } - } - // This is to avoid passing a slice of bytes with a length that the base64 // decoder would consider invalid. #[inline] @@ -66,7 +64,7 @@ impl EncodedBytes { } fn append(&mut self, bytes: Bytes) -> Result<(), PostGrpcWebErr> { - if self.is_base64_encoding()? { + if self.is_base64 { self.raw_buf.put(bytes); self.decode_base64_chunk()?; } else { @@ -339,7 +337,7 @@ impl Default for ResponseBody { Self { body_stream: BodyStream::empty(), buf: EncodedBytes { - content_type: Default::default(), + is_base64: Default::default(), raw_buf: BytesMut::new(), buf: BytesMut::new(), }, From 08f2f8d8b3db18755372c87708a7ee25947dc0fa Mon Sep 17 00:00:00 2001 From: borngraced Date: Tue, 24 Oct 2023 21:40:06 +0100 Subject: [PATCH 12/68] enable waasm compilation for zcoin activation Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 5 ++++- mm2src/coins_activation/src/context.rs | 3 --- mm2src/coins_activation/src/lib.rs | 2 +- mm2src/coins_activation/src/prelude.rs | 2 -- mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs | 8 ++++---- mm2src/mm2_main/src/wasm_tests.rs | 4 ++-- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 19a9ca5710..6dcbc4d00d 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -810,7 +810,6 @@ pub struct ZcoinActivationParams { pub account: u32, } -#[cfg(not(target_arch = "wasm32"))] pub async fn z_coin_from_conf_and_params( ctx: &MmArc, ticker: &str, @@ -819,7 +818,11 @@ pub async fn z_coin_from_conf_and_params( protocol_info: ZcoinProtocolInfo, priv_key_policy: PrivKeyBuildPolicy, ) -> Result> { + #[cfg(target_arch = "wasm32")] + let db_dir_path = PathBuf::new(); + #[cfg(not(target_arch = "wasm32"))] let db_dir_path = ctx.dbdir(); + let z_spending_key = None; let builder = ZCoinBuilder::new( ctx, diff --git a/mm2src/coins_activation/src/context.rs b/mm2src/coins_activation/src/context.rs index a86869e7ab..26835ef076 100644 --- a/mm2src/coins_activation/src/context.rs +++ b/mm2src/coins_activation/src/context.rs @@ -1,7 +1,6 @@ #[cfg(not(target_arch = "wasm32"))] use crate::lightning_activation::LightningTaskManagerShared; use crate::utxo_activation::{QtumTaskManagerShared, UtxoStandardTaskManagerShared}; -#[cfg(not(target_arch = "wasm32"))] use crate::z_coin_activation::ZcoinTaskManagerShared; use mm2_core::mm_ctx::{from_ctx, MmArc}; use rpc_task::RpcTaskManager; @@ -10,7 +9,6 @@ use std::sync::Arc; pub struct CoinsActivationContext { pub(crate) init_utxo_standard_task_manager: UtxoStandardTaskManagerShared, pub(crate) init_qtum_task_manager: QtumTaskManagerShared, - #[cfg(not(target_arch = "wasm32"))] pub(crate) init_z_coin_task_manager: ZcoinTaskManagerShared, #[cfg(not(target_arch = "wasm32"))] pub(crate) init_lightning_task_manager: LightningTaskManagerShared, @@ -23,7 +21,6 @@ impl CoinsActivationContext { Ok(CoinsActivationContext { init_utxo_standard_task_manager: RpcTaskManager::new_shared(), init_qtum_task_manager: RpcTaskManager::new_shared(), - #[cfg(not(target_arch = "wasm32"))] init_z_coin_task_manager: RpcTaskManager::new_shared(), #[cfg(not(target_arch = "wasm32"))] init_lightning_task_manager: RpcTaskManager::new_shared(), diff --git a/mm2src/coins_activation/src/lib.rs b/mm2src/coins_activation/src/lib.rs index 34bd11e902..a3475f3d18 100644 --- a/mm2src/coins_activation/src/lib.rs +++ b/mm2src/coins_activation/src/lib.rs @@ -26,7 +26,7 @@ mod tendermint_token_activation; mod tendermint_with_assets_activation; mod token; mod utxo_activation; -#[cfg(not(target_arch = "wasm32"))] mod z_coin_activation; +mod z_coin_activation; pub use l2::{cancel_init_l2, init_l2, init_l2_status, init_l2_user_action}; pub use platform_coin_with_tokens::enable_platform_coin_with_tokens; diff --git a/mm2src/coins_activation/src/prelude.rs b/mm2src/coins_activation/src/prelude.rs index 2126d8bc06..2061509ee4 100644 --- a/mm2src/coins_activation/src/prelude.rs +++ b/mm2src/coins_activation/src/prelude.rs @@ -1,5 +1,4 @@ use coins::utxo::UtxoActivationParams; -#[cfg(not(target_arch = "wasm32"))] use coins::z_coin::ZcoinActivationParams; use coins::{coin_conf, CoinBalance, CoinProtocol, MmCoinEnum}; use mm2_core::mm_ctx::MmArc; @@ -21,7 +20,6 @@ impl TxHistory for UtxoActivationParams { fn tx_history(&self) -> bool { self.tx_history } } -#[cfg(not(target_arch = "wasm32"))] impl TxHistory for ZcoinActivationParams { fn tx_history(&self) -> bool { false } } diff --git a/mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs b/mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs index 5645b9a68f..b69d64541a 100644 --- a/mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs +++ b/mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs @@ -30,6 +30,7 @@ use coins::utxo::bch::BchCoin; use coins::utxo::qtum::QtumCoin; use coins::utxo::slp::SlpToken; use coins::utxo::utxo_standard::UtxoStandardCoin; +use coins::z_coin::ZCoin; use coins::{add_delegation, get_my_address, get_raw_transaction, get_staking_infos, remove_delegation, sign_message, verify_message, withdraw}; #[cfg(all( @@ -56,7 +57,6 @@ use std::net::SocketAddr; cfg_native! { use coins::lightning::LightningCoin; - use coins::z_coin::ZCoin; } pub async fn process_single_request( @@ -260,15 +260,15 @@ async fn rpc_task_dispatcher( "withdraw::init" => handle_mmrpc(ctx, request, init_withdraw).await, "withdraw::status" => handle_mmrpc(ctx, request, withdraw_status).await, "withdraw::user_action" => handle_mmrpc(ctx, request, withdraw_user_action).await, + "enable_z_coin::init" => handle_mmrpc(ctx, request, init_standalone_coin::).await, + "enable_z_coin::status" => handle_mmrpc(ctx, request, init_standalone_coin_status::).await, + "enable_z_coin::cancel" => handle_mmrpc(ctx, request, cancel_init_standalone_coin::).await, #[cfg(not(target_arch = "wasm32"))] native_only_methods => match native_only_methods { "enable_lightning::cancel" => handle_mmrpc(ctx, request, cancel_init_l2::).await, "enable_lightning::init" => handle_mmrpc(ctx, request, init_l2::).await, "enable_lightning::status" => handle_mmrpc(ctx, request, init_l2_status::).await, "enable_lightning::user_action" => handle_mmrpc(ctx, request, init_l2_user_action::).await, - "enable_z_coin::cancel" => handle_mmrpc(ctx, request, cancel_init_standalone_coin::).await, - "enable_z_coin::init" => handle_mmrpc(ctx, request, init_standalone_coin::).await, - "enable_z_coin::status" => handle_mmrpc(ctx, request, init_standalone_coin_status::).await, "enable_z_coin::user_action" => handle_mmrpc(ctx, request, init_standalone_coin_user_action::).await, _ => MmError::err(DispatcherError::NoSuchMethod), }, diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index 2888c0f6bb..533c3ae480 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -1,5 +1,6 @@ use crate::mm2::lp_init; use common::executor::{spawn, Timer}; +use common::log::info; use common::log::wasm_log::register_wasm_log; use common::wait_until_ms; use crypto::StandardHDCoinAddress; @@ -21,7 +22,6 @@ use serde_json::{self as json}; use wasm_bindgen_test::wasm_bindgen_test; const ZOMBIE_TEST_BALANCE_SEED: &str = "zombie test seed"; -const ARRR_TEST_ACTIVATION_SEED: &str = "arrr test activation seed"; /// Starts the WASM version of MM. fn wasm_start(ctx: MmArc) { @@ -204,13 +204,13 @@ pub async fn enable_z_coin_light( ) -> ZCoinActivationResult { let init = init_z_coin_light(mm, coin, electrums, lightwalletd_urls, starting_date, account).await; let init: RpcV2Response = json::from_value(init).unwrap(); + info!("INIT RESULT: {init:?}"); let timeout = wait_until_ms(60000); loop { if now_ms() > timeout { panic!("{} initialization timed out", coin); } - let status = init_z_coin_status(mm, init.result.task_id).await; println!("Status {}", json::to_string(&status).unwrap()); let status: RpcV2Response = json::from_value(status).unwrap(); From 055c0850bb3d4f19119014d5bd54beed9c256388 Mon Sep 17 00:00:00 2001 From: borngraced Date: Tue, 24 Oct 2023 23:13:15 +0100 Subject: [PATCH 13/68] update time crate Signed-off-by: borngraced --- Cargo.lock | 295 +++++++++--------- mm2src/coins/Cargo.toml | 2 +- .../mm2_main/src/rpc/dispatcher/dispatcher.rs | 4 +- 3 files changed, 151 insertions(+), 150 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 14b6f653d6..4944ff0473 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -199,8 +199,8 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -216,8 +216,8 @@ version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -684,7 +684,7 @@ dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", "proc-macro-crate 0.1.5", - "proc-macro2 1.0.58", + "proc-macro2 1.0.69", "syn 1.0.95", ] @@ -694,8 +694,8 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -705,8 +705,8 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -762,8 +762,8 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -1072,7 +1072,7 @@ dependencies = [ "spv_validation", "tendermint-config", "tendermint-rpc", - "time 0.3.11", + "time 0.3.20", "tiny-bip39", "tokio", "tokio-rustls", @@ -1584,7 +1584,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" dependencies = [ - "quote 1.0.27", + "quote 1.0.33", "syn 1.0.95", ] @@ -1665,8 +1665,8 @@ dependencies = [ "cc", "codespan-reporting", "lazy_static", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "scratch", "syn 1.0.95", ] @@ -1683,8 +1683,8 @@ version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -1757,8 +1757,8 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -1768,8 +1768,8 @@ version = "0.99.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -2022,8 +2022,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73" dependencies = [ "heck", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -2034,7 +2034,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c375b9c5eadb68d0a6efee2999fef292f45854c3444c86f09d8ab086ba942b0e" dependencies = [ "num-traits", - "quote 1.0.27", + "quote 1.0.33", "syn 1.0.95", ] @@ -2043,8 +2043,8 @@ name = "enum_from" version = "0.1.0" dependencies = [ "itertools", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -2192,8 +2192,8 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", "synstructure", ] @@ -2440,8 +2440,8 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -3057,8 +3057,8 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5dacb10c5b3bb92d46ba347505a9041e676bb20ad220101326bffb0c93031ee" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -3198,9 +3198,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.55" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" dependencies = [ "wasm-bindgen", ] @@ -3561,7 +3561,7 @@ name = "libp2p-swarm-derive" version = "0.27.2" source = "git+https://github.com/libp2p/rust-libp2p.git?tag=v0.45.1#802d00e645894d8895f2f9f665b921452d992b86" dependencies = [ - "quote 1.0.27", + "quote 1.0.33", "syn 1.0.95", ] @@ -3993,9 +3993,9 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddece26afd34c31585c74a4db0630c376df271c285d682d1e55012197830b6df" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", - "syn 2.0.16", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.38", ] [[package]] @@ -4489,8 +4489,8 @@ version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3048ef3680533a27f9f8e7d6a0bce44dc61e4895ea0f42709337fa1c8616fefe" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -4533,8 +4533,8 @@ checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" dependencies = [ "proc-macro-crate 1.1.3", "proc-macro-error", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", "synstructure", ] @@ -4617,8 +4617,8 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -4681,20 +4681,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "486ea01961c4a818096de679a8b740b26d9033146ac5291b1c98557658f8cdd9" dependencies = [ "proc-macro-crate 1.1.3", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] -[[package]] -name = "num_threads" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" -dependencies = [ - "libc", -] - [[package]] name = "number_prefix" version = "0.4.0" @@ -4756,8 +4747,8 @@ checksum = "44a0b52c2cbaef7dffa5fec1a43274afe8bd2a644fa9fc50a9ef4ff0269b1257" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -4813,8 +4804,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8" dependencies = [ "proc-macro-crate 1.1.3", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -4848,7 +4839,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ - "proc-macro2 1.0.58", + "proc-macro2 1.0.69", "syn 1.0.95", "synstructure", ] @@ -4964,8 +4955,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c" dependencies = [ "peg-runtime", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", ] [[package]] @@ -5023,8 +5014,8 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "044964427019eed9d49d9d5bbce6047ef18f37100ea400912a9fa4a3523ab12a" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -5034,8 +5025,8 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -5115,7 +5106,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f28f53e8b192565862cf99343194579a022eb9c7dd3a8d03134734803c7b3125" dependencies = [ - "proc-macro2 1.0.58", + "proc-macro2 1.0.69", "syn 1.0.95", ] @@ -5169,8 +5160,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", "version_check", ] @@ -5181,8 +5172,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "version_check", ] @@ -5197,9 +5188,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.58" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -5222,8 +5213,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8e12d01b9d66ad9eb4529c57666b6263fc1993cb30261d83ead658fdd932652" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -5267,8 +5258,8 @@ checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc" dependencies = [ "anyhow", "itertools", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -5376,11 +5367,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.27" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ - "proc-macro2 1.0.58", + "proc-macro2 1.0.69", ] [[package]] @@ -5673,7 +5664,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", "ring", - "time 0.3.11", + "time 0.3.20", "yasna", ] @@ -5737,8 +5728,8 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c523ccaed8ac4b0288948849a350b37d3035827413c458b6a40ddb614bb4f72" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -5940,7 +5931,7 @@ dependencies = [ "hashlink", "libsqlite3-sys", "smallvec 1.6.1", - "time 0.3.11", + "time 0.3.20", ] [[package]] @@ -6104,8 +6095,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50e334bb10a245e28e5fd755cabcafd96cfcd167c99ae63a46924ca8d8703a3c" dependencies = [ "proc-macro-crate 1.1.3", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -6259,17 +6250,17 @@ dependencies = [ name = "ser_error_derive" version = "0.1.0" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "ser_error", "syn 1.0.95", ] [[package]] name = "serde" -version = "1.0.164" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" dependencies = [ "serde_derive", ] @@ -6296,13 +6287,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", - "syn 2.0.16", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.38", ] [[package]] @@ -6323,8 +6314,8 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -6794,8 +6785,8 @@ version = "1.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "402fffb54bf5d335e6df26fc1719feecfbd7a22fafdf6649fe78380de3c47384" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "rustc_version 0.4.0", "syn 1.0.95", ] @@ -7096,8 +7087,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c834b4e02ac911b13c13aed08b3f847e722f6be79d31b1c660c1dbd2dee83cdb" dependencies = [ "bs58", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "rustversion", "syn 1.0.95", ] @@ -7220,8 +7211,8 @@ version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d676664972e22a0796176e81e7bec41df461d1edf52090955cdab55f2c956ff2" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -7250,8 +7241,8 @@ checksum = "22ecb916b9664ed9f90abef0ff5a3e61454c1efea5861b2997e03f39b59b955f" dependencies = [ "Inflector", "proc-macro-crate 1.1.3", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -7398,8 +7389,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f9799e6d412271cb2414597581128b03f3285f260ea49f5363d07df6a332b3e" dependencies = [ "Inflector", - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "serde", "serde_json", "unicode-xid 0.2.0", @@ -7478,19 +7469,19 @@ version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.16" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "unicode-ident", ] @@ -7515,8 +7506,8 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", "unicode-xid 0.2.0", ] @@ -7671,7 +7662,7 @@ dependencies = [ "subtle 2.4.0", "subtle-encoding", "tendermint-proto", - "time 0.3.11", + "time 0.3.20", "zeroize", ] @@ -7704,7 +7695,7 @@ dependencies = [ "serde", "serde_bytes", "subtle-encoding", - "time 0.3.11", + "time 0.3.20", ] [[package]] @@ -7726,7 +7717,7 @@ dependencies = [ "tendermint-config", "tendermint-proto", "thiserror", - "time 0.3.11", + "time 0.3.20", "url", "uuid 0.8.2", "walkdir", @@ -7799,8 +7790,8 @@ version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -7816,21 +7807,31 @@ dependencies = [ [[package]] name = "time" -version = "0.3.11" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" dependencies = [ "itoa 1.0.1", - "libc", - "num_threads", + "js-sys", + "serde", + "time-core", "time-macros", ] +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + [[package]] name = "time-macros" -version = "0.2.4" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" +checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +dependencies = [ + "time-core", +] [[package]] name = "tiny-bip39" @@ -7930,8 +7931,8 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -8023,9 +8024,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9263bf4c9bfaae7317c1c2faf7f18491d2fe476f70c414b73bf5d445b00ffa1" dependencies = [ "prettyplease", - "proc-macro2 1.0.58", + "proc-macro2 1.0.69", "prost-build", - "quote 1.0.27", + "quote 1.0.33", "syn 1.0.95", ] @@ -8099,8 +8100,8 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", ] @@ -8565,9 +8566,9 @@ dependencies = [ "bumpalo", "log 0.4.17", "once_cell", - "proc-macro2 1.0.58", - "quote 1.0.27", - "syn 2.0.16", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.38", "wasm-bindgen-shared", ] @@ -8589,7 +8590,7 @@ version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" dependencies = [ - "quote 1.0.27", + "quote 1.0.33", "wasm-bindgen-macro-support", ] @@ -8599,9 +8600,9 @@ version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", - "syn 2.0.16", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.38", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -8632,8 +8633,8 @@ version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c2e18093f11c19ca4e188c177fecc7c372304c311189f12c2f9bea5b7324ac7" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", ] [[package]] @@ -8985,7 +8986,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.11", + "time 0.3.20", ] [[package]] @@ -9015,7 +9016,7 @@ dependencies = [ "protobuf-codegen-pure", "rand_core 0.5.1", "subtle 2.4.0", - "time 0.3.11", + "time 0.3.20", "zcash_note_encryption", "zcash_primitives", ] @@ -9036,7 +9037,7 @@ dependencies = [ "protobuf", "rand_core 0.5.1", "rusqlite", - "time 0.3.11", + "time 0.3.20", "tokio", "zcash_client_backend", "zcash_extras", @@ -9054,7 +9055,7 @@ dependencies = [ "jubjub", "protobuf", "rand_core 0.5.1", - "time 0.3.11", + "time 0.3.20", "zcash_client_backend", "zcash_primitives", ] @@ -9136,8 +9137,8 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ - "proc-macro2 1.0.58", - "quote 1.0.27", + "proc-macro2 1.0.69", + "quote 1.0.33", "syn 1.0.95", "synstructure", ] diff --git a/mm2src/coins/Cargo.toml b/mm2src/coins/Cargo.toml index bfbb6ffa99..2ec2d82a06 100644 --- a/mm2src/coins/Cargo.toml +++ b/mm2src/coins/Cargo.toml @@ -125,7 +125,7 @@ js-sys = { version = "0.3.27" } mm2_db = { path = "../mm2_db" } mm2_metamask = { path = "../mm2_metamask" } mm2_test_helpers = { path = "../mm2_test_helpers" } -time = { version = "0.3" } +time = { version = "0.3.20", features = ["wasm-bindgen"] } tonic = { version = "0.7", default-features = false, features = ["prost", "codegen"] } tower-service = "0.3" wasm-bindgen = "0.2.86" diff --git a/mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs b/mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs index b69d64541a..a67a5853f8 100644 --- a/mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs +++ b/mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs @@ -261,15 +261,15 @@ async fn rpc_task_dispatcher( "withdraw::status" => handle_mmrpc(ctx, request, withdraw_status).await, "withdraw::user_action" => handle_mmrpc(ctx, request, withdraw_user_action).await, "enable_z_coin::init" => handle_mmrpc(ctx, request, init_standalone_coin::).await, - "enable_z_coin::status" => handle_mmrpc(ctx, request, init_standalone_coin_status::).await, "enable_z_coin::cancel" => handle_mmrpc(ctx, request, cancel_init_standalone_coin::).await, + "enable_z_coin::status" => handle_mmrpc(ctx, request, init_standalone_coin_status::).await, + "enable_z_coin::user_action" => handle_mmrpc(ctx, request, init_standalone_coin_user_action::).await, #[cfg(not(target_arch = "wasm32"))] native_only_methods => match native_only_methods { "enable_lightning::cancel" => handle_mmrpc(ctx, request, cancel_init_l2::).await, "enable_lightning::init" => handle_mmrpc(ctx, request, init_l2::).await, "enable_lightning::status" => handle_mmrpc(ctx, request, init_l2_status::).await, "enable_lightning::user_action" => handle_mmrpc(ctx, request, init_l2_user_action::).await, - "enable_z_coin::user_action" => handle_mmrpc(ctx, request, init_standalone_coin_user_action::).await, _ => MmError::err(DispatcherError::NoSuchMethod), }, #[cfg(target_arch = "wasm32")] From 39ae87258a6fd83faeb9502e9f8980a48dbdd172 Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 00:27:51 +0100 Subject: [PATCH 14/68] use now_sec from common crate Signed-off-by: borngraced --- mm2src/mm2_main/src/lib.rs | 2 +- mm2src/mm2_main/src/wasm_tests.rs | 7 +++---- mm2src/mm2_net/src/grpc_web.rs | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/mm2src/mm2_main/src/lib.rs b/mm2src/mm2_main/src/lib.rs index 23c7b65312..14759d0b99 100644 --- a/mm2src/mm2_main/src/lib.rs +++ b/mm2src/mm2_main/src/lib.rs @@ -17,4 +17,4 @@ pub mod mm2; -#[cfg(all(target_arch = "wasm32", test))] mod wasm_tests; +#[cfg(all(target_arch = "wasm32", test))] pub mod wasm_tests; diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index 533c3ae480..9a999e7686 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -2,9 +2,8 @@ use crate::mm2::lp_init; use common::executor::{spawn, Timer}; use common::log::info; use common::log::wasm_log::register_wasm_log; -use common::wait_until_ms; +use common::{now_sec, wait_until_ms, wait_until_sec}; use crypto::StandardHDCoinAddress; -use gstuff::now_ms; use mm2_core::mm_ctx::MmArc; use mm2_number::BigDecimal; use mm2_rpc::data::legacy::OrderbookResponse; @@ -205,10 +204,10 @@ pub async fn enable_z_coin_light( let init = init_z_coin_light(mm, coin, electrums, lightwalletd_urls, starting_date, account).await; let init: RpcV2Response = json::from_value(init).unwrap(); info!("INIT RESULT: {init:?}"); - let timeout = wait_until_ms(60000); + let timeout = wait_until_sec(120); loop { - if now_ms() > timeout { + if now_sec() > timeout { panic!("{} initialization timed out", coin); } let status = init_z_coin_status(mm, init.result.task_id).await; diff --git a/mm2src/mm2_net/src/grpc_web.rs b/mm2src/mm2_net/src/grpc_web.rs index ce53a8bc29..aa79febc2c 100644 --- a/mm2src/mm2_net/src/grpc_web.rs +++ b/mm2src/mm2_net/src/grpc_web.rs @@ -33,7 +33,7 @@ impl From for EncodeBodyError { } #[cfg_attr(target_arch = "wasm32", allow(dead_code))] -pub fn encode_body(msg: &T) -> Result, MmError> +fn encode_body(msg: &T) -> Result, MmError> where T: prost::Message, { @@ -73,7 +73,7 @@ impl From for DecodeBodyError { } #[cfg_attr(target_arch = "wasm32", allow(dead_code))] -pub fn decode_body(mut body: Bytes) -> Result> +fn decode_body(mut body: Bytes) -> Result> where T: Default + prost::Message, { From e668aaa60b41025ce8be6d19c7c4f02880b39850 Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 06:51:07 +0100 Subject: [PATCH 15/68] add ZOMBIE_LIGHTWALLETD_WSS_URLS Signed-off-by: borngraced --- mm2src/coins/z_coin/z_rpc.rs | 1 - mm2src/mm2_main/src/wasm_tests.rs | 9 ++++----- mm2src/mm2_test_helpers/src/for_tests.rs | 1 + 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index d0c5ec52e6..3acbb90077 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -168,7 +168,6 @@ impl RpcCommonOps for LightRpcClient { let request = tonic::Request::new(ChainSpec {}); // use get_latest_block method as a health check let latest = client.get_latest_block(request).await; - info!("{latest:?}"); if latest.is_ok() { clients.rotate_left(i); return Ok(client); diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index 9a999e7686..40333c6cfe 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -2,7 +2,7 @@ use crate::mm2::lp_init; use common::executor::{spawn, Timer}; use common::log::info; use common::log::wasm_log::register_wasm_log; -use common::{now_sec, wait_until_ms, wait_until_sec}; +use common::{now_sec, wait_until_sec}; use crypto::StandardHDCoinAddress; use mm2_core::mm_ctx::MmArc; use mm2_number::BigDecimal; @@ -12,7 +12,7 @@ use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init morty_conf, rick_conf, start_swaps, test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, zombie_conf, MarketMakerIt, Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, MORTY, RICK, - ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, ZOMBIE_TICKER}; + ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_WSS_URLS, ZOMBIE_TICKER}; use mm2_test_helpers::get_passphrase; use mm2_test_helpers::structs::{EnableCoinBalance, InitTaskResult, InitZcoinStatus, RpcV2Response, ZCoinActivationResult}; @@ -193,7 +193,7 @@ async fn trade_test_rick_and_morty() { .await; } -pub async fn enable_z_coin_light( +async fn enable_z_coin_light( mm: &MarketMakerIt, coin: &str, electrums: &[&str], @@ -203,7 +203,6 @@ pub async fn enable_z_coin_light( ) -> ZCoinActivationResult { let init = init_z_coin_light(mm, coin, electrums, lightwalletd_urls, starting_date, account).await; let init: RpcV2Response = json::from_value(init).unwrap(); - info!("INIT RESULT: {init:?}"); let timeout = wait_until_sec(120); loop { @@ -235,7 +234,7 @@ async fn activate_z_coin_light() { &mm, ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, - ZOMBIE_LIGHTWALLETD_URLS, + ZOMBIE_LIGHTWALLETD_WSS_URLS, None, None, ) diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index d6f1d75fbd..d08b5b9503 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -142,6 +142,7 @@ pub const ZOMBIE_TICKER: &str = "ZOMBIE"; pub const ARRR: &str = "ARRR"; pub const ZOMBIE_ELECTRUMS: &[&str] = &["zombie.dragonhound.info:10033"]; pub const ZOMBIE_LIGHTWALLETD_URLS: &[&str] = &["http://zombie.dragonhound.info:443"]; +pub const ZOMBIE_LIGHTWALLETD_WSS_URLS: &[&str] = &["zombie.dragonhound.info:30059"]; pub const PIRATE_ELECTRUMS: &[&str] = &["node1.chainkeeper.pro:10132"]; pub const PIRATE_LIGHTWALLETD_URLS: &[&str] = &["http://node1.chainkeeper.pro:443"]; pub const DEFAULT_RPC_PASSWORD: &str = "pass"; From 1b615bf9c467bb441bf1fa465b434e40d7ae76a1 Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 07:40:49 +0100 Subject: [PATCH 16/68] use correct electrum ZOMBIE_ELECTRUMS_WSS url Signed-off-by: borngraced --- mm2src/mm2_main/src/wasm_tests.rs | 6 +++--- mm2src/mm2_test_helpers/src/for_tests.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index 40333c6cfe..a9f52bde4b 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -12,7 +12,7 @@ use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init morty_conf, rick_conf, start_swaps, test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, zombie_conf, MarketMakerIt, Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, MORTY, RICK, - ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_WSS_URLS, ZOMBIE_TICKER}; + ZOMBIE_ELECTRUMS_WSS, ZOMBIE_LIGHTWALLETD_URLS, ZOMBIE_TICKER}; use mm2_test_helpers::get_passphrase; use mm2_test_helpers::structs::{EnableCoinBalance, InitTaskResult, InitZcoinStatus, RpcV2Response, ZCoinActivationResult}; @@ -233,8 +233,8 @@ async fn activate_z_coin_light() { let activation_result = enable_z_coin_light( &mm, ZOMBIE_TICKER, - ZOMBIE_ELECTRUMS, - ZOMBIE_LIGHTWALLETD_WSS_URLS, + ZOMBIE_ELECTRUMS_WSS, + ZOMBIE_LIGHTWALLETD_URLS, None, None, ) diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index d08b5b9503..c4b7394cf8 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -141,8 +141,8 @@ pub const MORTY_ELECTRUM_ADDRS: &[&str] = &[ pub const ZOMBIE_TICKER: &str = "ZOMBIE"; pub const ARRR: &str = "ARRR"; pub const ZOMBIE_ELECTRUMS: &[&str] = &["zombie.dragonhound.info:10033"]; +pub const ZOMBIE_ELECTRUMS_WSS: &[&str] = &["zombie.dragonhound.info:30059"]; pub const ZOMBIE_LIGHTWALLETD_URLS: &[&str] = &["http://zombie.dragonhound.info:443"]; -pub const ZOMBIE_LIGHTWALLETD_WSS_URLS: &[&str] = &["zombie.dragonhound.info:30059"]; pub const PIRATE_ELECTRUMS: &[&str] = &["node1.chainkeeper.pro:10132"]; pub const PIRATE_LIGHTWALLETD_URLS: &[&str] = &["http://node1.chainkeeper.pro:443"]; pub const DEFAULT_RPC_PASSWORD: &str = "pass"; From a95391dd975a062d52926928d18be19059e9009e Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 08:07:49 +0100 Subject: [PATCH 17/68] impl temp TxProver for WASM Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 13 ++++++++++++- mm2src/mm2_main/src/wasm_tests.rs | 1 - 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 6dcbc4d00d..a74d5e9e82 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -69,6 +69,8 @@ use zcash_primitives::transaction::Transaction as ZTransaction; use zcash_primitives::zip32::ChildIndex as Zip32Child; use zcash_primitives::{constants::mainnet as z_mainnet_constants, sapling::PaymentAddress, zip32::ExtendedFullViewingKey, zip32::ExtendedSpendingKey}; +#[cfg(target_arch = "wasm32")] +use zcash_proofs::parse_parameters; use zcash_proofs::prover::LocalTxProver; mod z_htlc; @@ -1043,7 +1045,16 @@ impl<'a> ZCoinBuilder<'a> { } #[cfg(target_arch = "wasm32")] - async fn z_tx_prover(&self) -> Result> { todo!() } + async fn z_tx_prover(&self) -> Result> { + let (spend_buf, output_buf) = wagyu_zcash_parameters::load_sapling_parameters(); + let p = parse_parameters(&spend_buf[..], &output_buf[..], None); + + Ok(LocalTxProver { + spend_params: p.spend_params, + spend_vk: p.spend_vk, + output_params: p.output_params, + }) + } } /// Initialize `ZCoin` with a forced `z_spending_key`. diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index a9f52bde4b..0fb0c3489a 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -1,6 +1,5 @@ use crate::mm2::lp_init; use common::executor::{spawn, Timer}; -use common::log::info; use common::log::wasm_log::register_wasm_log; use common::{now_sec, wait_until_sec}; use crypto::StandardHDCoinAddress; From 9e1c5652df1a8dc6be9e628d981954a9a027ed9e Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 14:19:26 +0100 Subject: [PATCH 18/68] use proxied lightwalletd url for test Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 76 +++++++++------------- mm2src/coins/z_coin/storage/blockdb/mod.rs | 24 +++---- mm2src/coins/z_coin/z_coin_errors.rs | 7 +- mm2src/mm2_main/src/wasm_tests.rs | 4 +- mm2src/mm2_test_helpers/src/for_tests.rs | 1 + 5 files changed, 53 insertions(+), 59 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index a74d5e9e82..c50d4aa272 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -1,7 +1,6 @@ use crate::coin_errors::MyAddressError; #[cfg(not(target_arch = "wasm32"))] use crate::my_tx_history_v2::{MyTxHistoryErrorV2, MyTxHistoryRequestV2, MyTxHistoryResponseV2}; -#[cfg(not(target_arch = "wasm32"))] use crate::rpc_command::init_withdraw::{InitWithdrawCoin, WithdrawInProgressStatus, WithdrawTaskHandle}; use crate::utxo::rpc_clients::{ElectrumRpcRequest, UnspentInfo, UtxoRpcClientEnum, UtxoRpcError, UtxoRpcFut, UtxoRpcResult}; @@ -9,10 +8,12 @@ use crate::utxo::utxo_builder::UtxoCoinBuildError; use crate::utxo::utxo_builder::{UtxoCoinBuilder, UtxoCoinBuilderCommonOps, UtxoFieldsWithGlobalHDBuilder, UtxoFieldsWithHardwareWalletBuilder, UtxoFieldsWithIguanaSecretBuilder}; use crate::utxo::utxo_common::{big_decimal_from_sat_unsigned, payment_script}; +use crate::utxo::UtxoFeeDetails; use crate::utxo::{sat_from_big_decimal, utxo_common, ActualTxFee, AdditionalTxData, AddrFromStrError, Address, BroadcastTxErr, FeePolicy, GetUtxoListOps, HistoryUtxoTx, HistoryUtxoTxMap, MatureUnspentList, RecentlySpentOutPointsGuard, UtxoActivationParams, UtxoAddressFormat, UtxoArc, UtxoCoinFields, UtxoCommonOps, UtxoRpcMode, UtxoTxBroadcastOps, UtxoTxGenerationOps, VerboseTransactionFrom}; +use crate::TxFeeDetails; use crate::{BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, CoinFutSpawner, ConfirmPaymentInput, FeeApproxStage, FoundSwapTxSpend, HistorySyncState, MakerSwapTakerCoin, MarketCoinOps, MmCoin, MmCoinEnum, NegotiateSwapContractAddrErr, PaymentInstructionArgs, PaymentInstructions, PaymentInstructionsErr, @@ -25,7 +26,9 @@ use crate::{BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, Coi ValidatePaymentError, ValidatePaymentFut, ValidatePaymentInput, VerificationError, VerificationResult, WaitForHTLCTxSpendArgs, WatcherOps, WatcherReward, WatcherRewardError, WatcherSearchForSwapTxSpendInput, WatcherValidatePaymentInput, WatcherValidateTakerFeeInput, WithdrawFut, WithdrawRequest}; +use crate::{NumConversError, TransactionDetails}; use crate::{Transaction, WithdrawError}; + use async_trait::async_trait; use bitcrypto::dhash256; use chain::constants::SEQUENCE_FINAL; @@ -59,16 +62,20 @@ use std::sync::Arc; use z_coin_errors::ZCoinBalanceError; use z_rpc::{SaplingSyncConnector, SaplingSyncGuard}; use zcash_client_backend::encoding::{decode_payment_address, encode_extended_spending_key, encode_payment_address}; -use zcash_client_backend::wallet::SpendableNote; +use zcash_client_backend::wallet::{AccountId, SpendableNote}; +use zcash_extras::WalletRead; +use zcash_primitives::consensus; use zcash_primitives::consensus::{BlockHeight, NetworkUpgrade, Parameters, H0}; use zcash_primitives::memo::MemoBytes; use zcash_primitives::sapling::keys::OutgoingViewingKey; use zcash_primitives::sapling::note_encryption::try_sapling_output_recovery; +use zcash_primitives::transaction::builder::Builder as ZTxBuilder; use zcash_primitives::transaction::components::{Amount, TxOut}; use zcash_primitives::transaction::Transaction as ZTransaction; use zcash_primitives::zip32::ChildIndex as Zip32Child; use zcash_primitives::{constants::mainnet as z_mainnet_constants, sapling::PaymentAddress, zip32::ExtendedFullViewingKey, zip32::ExtendedSpendingKey}; + #[cfg(target_arch = "wasm32")] use zcash_proofs::parse_parameters; use zcash_proofs::prover::LocalTxProver; @@ -81,21 +88,14 @@ use z_rpc::init_light_client; pub use z_rpc::{FirstSyncBlock, SyncStatus}; cfg_native!( - use crate::{NumConversError, TransactionDetails, TxFeeDetails}; - use crate::utxo::UtxoFeeDetails; use crate::utxo::utxo_common::{addresses_from_script, big_decimal_from_sat}; use common::{async_blocking, calc_total_pages, PagingOptionsEnum}; use db_common::sqlite::offset_by_id; use db_common::sqlite::rusqlite::{Error as SqlError, Row}; use db_common::sqlite::sql_builder::{name, SqlBuilder, SqlName}; - use zcash_client_backend::data_api::WalletRead; - use zcash_client_backend::wallet::{AccountId}; use zcash_client_sqlite::error::SqliteClientError as ZcashClientError; - use zcash_client_sqlite::wallet::{get_balance}; - use zcash_client_sqlite::wallet::transact::get_spendable_notes; - use zcash_primitives::consensus; - use zcash_primitives::transaction::builder::Builder as ZTxBuilder; + use zcash_client_sqlite::wallet::get_balance; use zcash_proofs::default_params_folder; use z_rpc::{init_native_client}; ); @@ -358,33 +358,30 @@ impl ZCoin { } #[cfg(target_arch = "wasm32")] - async fn my_balance_sat(&self) -> Result> { todo!() } + async fn my_balance_sat(&self) -> Result> { + let wallet_db = self.z_fields.light_wallet_db.clone(); + Ok(wallet_db.db.get_balance(AccountId::default()).await?.into()) + } - #[cfg(not(target_arch = "wasm32"))] async fn get_spendable_notes(&self) -> Result, MmError> { let wallet_db = self.z_fields.light_wallet_db.clone(); - async_blocking(move || { - let db_guard = wallet_db.db.inner(); - let db_guard = db_guard.lock().unwrap(); - let latest_db_block = match db_guard - .block_height_extrema() - .map_err(|err| SpendableNotesError::DBClientError(err.to_string()))? - { - Some((_, latest)) => latest, - None => return Ok(Vec::new()), - }; - get_spendable_notes(&db_guard, AccountId::default(), latest_db_block) - .map_err(|err| MmError::new(SpendableNotesError::DBClientError(err.to_string()))) - }) - .await - } + let db_guard = wallet_db.db; + let latest_db_block = match db_guard + .block_height_extrema() + .await + .map_err(|err| SpendableNotesError::DBClientError(err.to_string()))? + { + Some((_, latest)) => latest, + None => return Ok(Vec::new()), + }; - #[cfg(target_arch = "wasm32")] - #[allow(unused)] - async fn get_spendable_notes(&self) -> Result, MmError> { todo!() } + db_guard + .get_spendable_notes(AccountId::default(), latest_db_block) + .await + .map_err(|err| MmError::new(SpendableNotesError::DBClientError(err.to_string()))) + } /// Returns spendable notes - #[allow(unused)] async fn spendable_notes_ordered(&self) -> Result, MmError> { let mut unspents = self.get_spendable_notes().await?; @@ -402,7 +399,6 @@ impl ZCoin { } /// Generates a tx sending outputs from our address - #[cfg(not(target_arch = "wasm32"))] async fn gen_tx( &self, t_outputs: Vec, @@ -489,11 +485,14 @@ impl ZCoin { tx_builder.add_tx_out(output); } + #[cfg(not(target_arch = "wasm32"))] let (tx, _) = async_blocking({ let prover = self.z_fields.z_tx_prover.clone(); move || tx_builder.build(consensus::BranchId::Sapling, prover.as_ref()) }) .await?; + #[cfg(target_arch = "wasm32")] + let (tx, _) = tx_builder.build(consensus::BranchId::Sapling, self.z_fields.z_tx_prover.clone().as_ref())?; let additional_data = AdditionalTxData { received_by_me, @@ -505,15 +504,6 @@ impl ZCoin { Ok((tx, additional_data, sync_guard)) } - #[cfg(target_arch = "wasm32")] - async fn gen_tx( - &self, - _t_outputs: Vec, - _z_outputs: Vec, - ) -> Result<(ZTransaction, AdditionalTxData, SaplingSyncGuard<'_>), MmError> { - todo!() - } - pub async fn send_outputs( &self, t_outputs: Vec, @@ -839,14 +829,12 @@ pub async fn z_coin_from_conf_and_params( builder.build().await } -#[allow(unused)] fn verify_checksum_zcash_params(spend_path: &PathBuf, output_path: &PathBuf) -> Result { let spend_hash = sha256_digest(spend_path)?; let out_hash = sha256_digest(output_path)?; Ok(spend_hash == SAPLING_SPEND_EXPECTED_HASH && out_hash == SAPLING_OUTPUT_EXPECTED_HASH) } -#[allow(unused)] fn get_spend_output_paths(params_dir: PathBuf) -> Result<(PathBuf, PathBuf), ZCoinBuildError> { if !params_dir.exists() { return Err(ZCoinBuildError::ZCashParamsNotFound); @@ -1045,6 +1033,7 @@ impl<'a> ZCoinBuilder<'a> { } #[cfg(target_arch = "wasm32")] + // TODO: Implement TxProver for WASM using indexed db after merging transport layer PR. async fn z_tx_prover(&self) -> Result> { let (spend_buf, output_buf) = wagyu_zcash_parameters::load_sapling_parameters(); let p = parse_parameters(&spend_buf[..], &output_buf[..], None); @@ -1929,7 +1918,6 @@ impl UtxoCommonOps for ZCoin { } } -#[cfg(not(target_arch = "wasm32"))] #[async_trait] impl InitWithdrawCoin for ZCoin { async fn init_withdraw( diff --git a/mm2src/coins/z_coin/storage/blockdb/mod.rs b/mm2src/coins/z_coin/storage/blockdb/mod.rs index 67fc746c47..5f1ec9c763 100644 --- a/mm2src/coins/z_coin/storage/blockdb/mod.rs +++ b/mm2src/coins/z_coin/storage/blockdb/mod.rs @@ -102,9 +102,9 @@ mod native_tests { mod wasm_tests { use crate::z_coin::storage::blockdb::block_db_storage_tests::{test_insert_block_and_get_latest_block_impl, test_rewind_to_height_impl}; - // use crate::z_coin::z_rpc::{LightRpcClient, ZRpcOps}; - // use common::log::info; - // use common::log::wasm_log::register_wasm_log; + use crate::z_coin::z_rpc::{LightRpcClient, ZRpcOps}; + use common::log::info; + use common::log::wasm_log::register_wasm_log; use wasm_bindgen_test::*; wasm_bindgen_test_configure!(run_in_browser); @@ -115,13 +115,13 @@ mod wasm_tests { #[wasm_bindgen_test] async fn test_rewind_to_height() { test_rewind_to_height_impl().await } - // #[wasm_bindgen_test] - // async fn test_transport() { - // register_wasm_log(); - // let mut client = LightRpcClient::new(vec!["http://127.0.0.1:8082".to_string()]) - // .await - // .unwrap(); - // let tree_state = client.get_tree_state(663164).await; - // info!("LATEST BLOCK: {tree_state:?}"); - // } + #[wasm_bindgen_test] + async fn test_transport() { + register_wasm_log(); + let mut client = LightRpcClient::new(vec!["http://pirate.spyglass.quest:8081".to_string()]) + .await + .unwrap(); + let tree_state = client.get_block_height().await; + info!("LATEST BLOCK: {tree_state:?}"); + } } diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index 77457067de..8fd5c2e1c2 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -297,8 +297,13 @@ pub enum SpendableNotesError { } #[derive(Debug, Display)] -pub enum ZCoinBalanceError {} +pub enum ZCoinBalanceError { + BalanceError(String), +} +impl From for ZCoinBalanceError { + fn from(value: ZcoinStorageError) -> Self { ZCoinBalanceError::BalanceError(value.to_string()) } +} /// The `ValidateBlocksError` enum encapsulates different types of errors that may occur /// during the validation and scanning process of zcoin blocks. #[derive(Debug, Display)] diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index 0fb0c3489a..b72fa0bcb2 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -11,7 +11,7 @@ use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init morty_conf, rick_conf, start_swaps, test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, zombie_conf, MarketMakerIt, Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, MORTY, RICK, - ZOMBIE_ELECTRUMS_WSS, ZOMBIE_LIGHTWALLETD_URLS, ZOMBIE_TICKER}; + ZOMBIE_ELECTRUMS_WSS, ZOMBIE_LIGHTWALLETD_PROXIED_URLS, ZOMBIE_TICKER}; use mm2_test_helpers::get_passphrase; use mm2_test_helpers::structs::{EnableCoinBalance, InitTaskResult, InitZcoinStatus, RpcV2Response, ZCoinActivationResult}; @@ -233,7 +233,7 @@ async fn activate_z_coin_light() { &mm, ZOMBIE_TICKER, ZOMBIE_ELECTRUMS_WSS, - ZOMBIE_LIGHTWALLETD_URLS, + ZOMBIE_LIGHTWALLETD_PROXIED_URLS, None, None, ) diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index c4b7394cf8..5bb542d333 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -143,6 +143,7 @@ pub const ARRR: &str = "ARRR"; pub const ZOMBIE_ELECTRUMS: &[&str] = &["zombie.dragonhound.info:10033"]; pub const ZOMBIE_ELECTRUMS_WSS: &[&str] = &["zombie.dragonhound.info:30059"]; pub const ZOMBIE_LIGHTWALLETD_URLS: &[&str] = &["http://zombie.dragonhound.info:443"]; +pub const ZOMBIE_LIGHTWALLETD_PROXIED_URLS: &[&str] = &["http://pirate.spyglass.quest:8081"]; pub const PIRATE_ELECTRUMS: &[&str] = &["node1.chainkeeper.pro:10132"]; pub const PIRATE_LIGHTWALLETD_URLS: &[&str] = &["http://node1.chainkeeper.pro:443"]; pub const DEFAULT_RPC_PASSWORD: &str = "pass"; From b45fe2a1f8cfa6c5efbdbeea9f8107899b817b8b Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 14:54:25 +0100 Subject: [PATCH 19/68] fix blockdb get_latest_block Signed-off-by: borngraced --- .../coins/z_coin/storage/blockdb/blockdb_idb_storage.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs index 6209f09987..740c0627b8 100644 --- a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs +++ b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs @@ -98,13 +98,7 @@ impl BlockDbImpl { .next() .await?; - let maybe_height = maybe_height.map(|(_, item)| item.height); - - let Some(height) = maybe_height else { - return MmError::err(ZcoinStorageError::GetFromStorageError(format!("{ticker} block height not found"))); - }; - - Ok(height) + Ok(maybe_height.map(|(_, item)| item.height).unwrap_or_else(|| 0)) } /// Insert new block to BlockDbTable given the provided data. @@ -205,7 +199,6 @@ impl BlockDbImpl { /// /// Processes blocks based on the provided `BlockProcessingMode` and other parameters, /// which may include a starting block height, validation criteria, and a processing limit. - #[allow(unused)] pub(crate) async fn process_blocks_with_mode( &self, params: ZcoinConsensusParams, From 503f76944322b776cd668a4eaa1311650a5e439e Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 15:41:04 +0100 Subject: [PATCH 20/68] log activation info Signed-off-by: borngraced --- mm2src/mm2_main/src/wasm_tests.rs | 3 +- mm2src/mm2_test_helpers/src/for_tests.rs | 45 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index b72fa0bcb2..a1cdf747a8 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -1,5 +1,6 @@ use crate::mm2::lp_init; use common::executor::{spawn, Timer}; +use common::log::info; use common::log::wasm_log::register_wasm_log; use common::{now_sec, wait_until_sec}; use crypto::StandardHDCoinAddress; @@ -209,7 +210,7 @@ async fn enable_z_coin_light( panic!("{} initialization timed out", coin); } let status = init_z_coin_status(mm, init.result.task_id).await; - println!("Status {}", json::to_string(&status).unwrap()); + info!("Status {}", json::to_string(&status).unwrap()); let status: RpcV2Response = json::from_value(status).unwrap(); match status.result { InitZcoinStatus::Ok(result) => break result, diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index 5bb542d333..97d1de95c3 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -2366,6 +2366,51 @@ pub async fn init_z_coin_light( json::from_str(&request.1).unwrap() } +pub async fn init_z_coin_light_with_short_height( + mm: &MarketMakerIt, + coin: &str, + electrums: &[&str], + lightwalletd_urls: &[&str], + starting_date: Option, + account: Option, +) -> Json { + // Number of seconds in a day + let one_day_seconds = 24 * 60 * 60; + let starting_date = starting_date.unwrap_or(now_sec() - one_day_seconds); + + let request = mm + .rpc(&json!({ + "userpass": mm.userpass, + "method": "task::enable_z_coin::init", + "mmrpc": "2.0", + "params": { + "ticker": coin, + "activation_params": { + "mode": { + "rpc": "Light", + "rpc_data": { + "electrum_servers": electrum_servers_rpc(electrums), + "light_wallet_d_servers": lightwalletd_urls, + "sync_params": { + "height": 2626131 + } + }, + }, + "account": account.unwrap_or_default(), + }, + } + })) + .await + .unwrap(); + assert_eq!( + request.0, + StatusCode::OK, + "'task::enable_z_coin::init' failed: {}", + request.1 + ); + json::from_str(&request.1).unwrap() +} + pub async fn init_z_coin_status(mm: &MarketMakerIt, task_id: u64) -> Json { let request = mm .rpc(&json!({ From adc053dc86e645e5225b64543fb02c78d4c71cef Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 16:04:45 +0100 Subject: [PATCH 21/68] fix query_blocks_by_limit block retrieval Signed-off-by: borngraced --- mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs index 740c0627b8..ed8ab50ff9 100644 --- a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs +++ b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs @@ -171,10 +171,12 @@ impl BlockDbImpl { let block_db = db_transaction.table::().await?; // Fetch CompactBlocks block_db are needed for scanning. + let min = u32::from(from_height + 1); + let cursor_limit = limit.unwrap_or(u32::MIN); let mut maybe_blocks = block_db .cursor_builder() .only("ticker", &self.ticker)? - .bound("height", u32::from(from_height + 1), limit.unwrap_or(u32::MAX)) + .bound("height", min, min + cursor_limit) .open_cursor(BlockDbTable::TICKER_HEIGHT_INDEX) .await?; From 3ab3838484d40142aafb0e22d84434b0117ae745 Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 16:59:22 +0100 Subject: [PATCH 22/68] use init_z_coin_light_with_short_height Signed-off-by: borngraced --- mm2src/coins/z_coin/z_rpc.rs | 1 + mm2src/mm2_main/src/wasm_tests.rs | 7 ++++--- mm2src/mm2_test_helpers/src/for_tests.rs | 6 +----- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 3acbb90077..6cb2e6e913 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -285,6 +285,7 @@ impl ZRpcOps for LightRpcClient { &mut self, height: u64, ) -> MmResult, UpdateBlocksCacheErr> { + info!("SYNC STARTING HEIGHT: {height}"); let tree_state = self.get_tree_state(height).await?; let hash = H256Json::from_str(&tree_state.hash) .map_err(|err| UpdateBlocksCacheErr::DecodeError(err.to_string()))? diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index a1cdf747a8..546974c4c6 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -8,8 +8,8 @@ use mm2_core::mm_ctx::MmArc; use mm2_number::BigDecimal; use mm2_rpc::data::legacy::OrderbookResponse; use mm2_test_helpers::electrums::{morty_electrums, rick_electrums}; -use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init_z_coin_light, init_z_coin_status, - morty_conf, rick_conf, start_swaps, test_qrc20_history_impl, +use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init_z_coin_light_with_short_height, + init_z_coin_status, morty_conf, rick_conf, start_swaps, test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, zombie_conf, MarketMakerIt, Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, MORTY, RICK, ZOMBIE_ELECTRUMS_WSS, ZOMBIE_LIGHTWALLETD_PROXIED_URLS, ZOMBIE_TICKER}; @@ -201,7 +201,8 @@ async fn enable_z_coin_light( starting_date: Option, account: Option, ) -> ZCoinActivationResult { - let init = init_z_coin_light(mm, coin, electrums, lightwalletd_urls, starting_date, account).await; + let init = + init_z_coin_light_with_short_height(mm, coin, electrums, lightwalletd_urls, starting_date, account).await; let init: RpcV2Response = json::from_value(init).unwrap(); let timeout = wait_until_sec(120); diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index 97d1de95c3..109a145c41 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -2371,13 +2371,9 @@ pub async fn init_z_coin_light_with_short_height( coin: &str, electrums: &[&str], lightwalletd_urls: &[&str], - starting_date: Option, account: Option, ) -> Json { // Number of seconds in a day - let one_day_seconds = 24 * 60 * 60; - let starting_date = starting_date.unwrap_or(now_sec() - one_day_seconds); - let request = mm .rpc(&json!({ "userpass": mm.userpass, @@ -2392,7 +2388,7 @@ pub async fn init_z_coin_light_with_short_height( "electrum_servers": electrum_servers_rpc(electrums), "light_wallet_d_servers": lightwalletd_urls, "sync_params": { - "height": 2626131 + "height": 2626265 } }, }, From d4c047c7c9991bfdca7aa3d68c8e12012317b99a Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 20:11:46 +0100 Subject: [PATCH 23/68] fix conflicts Signed-off-by: borngraced --- Cargo.lock | 65 ++++--------------- mm2src/coins/z_coin.rs | 13 ++-- .../z_coin/storage/walletdb/wasm/storage.rs | 2 +- mm2src/coins/z_coin/z_rpc.rs | 12 ++-- mm2src/mm2_main/src/wasm_tests.rs | 16 ++--- mm2src/mm2_test_helpers/src/for_tests.rs | 9 ++- 6 files changed, 39 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ec3d9f7e60..a7af241524 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1610,16 +1610,6 @@ dependencies = [ "crypto_api", ] -[[package]] -name = "ctor" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" -dependencies = [ - "quote 1.0.33", - "syn 1.0.95", -] - [[package]] name = "ctr" version = "0.7.0" @@ -2522,7 +2512,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 1.0.95", + "syn 2.0.38", ] [[package]] @@ -3751,7 +3741,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -4550,7 +4540,7 @@ dependencies = [ "async-stream", "async-trait", "base64 0.21.2", - "byteorder 1.4.3", + "byteorder", "bytes 1.4.0", "cfg-if 1.0.0", "common", @@ -4567,11 +4557,11 @@ dependencies = [ "lazy_static", "mm2_core", "mm2_err_handle", - "pin-project 1.0.10", "mm2_event_stream", "mm2_p2p", "mm2_state_machine", "parking_lot 0.12.0", + "pin-project", "prost", "rand 0.7.3", "rustls 0.20.4", @@ -4627,7 +4617,7 @@ dependencies = [ "serde_bytes", "sha2 0.9.9", "smallvec 1.6.1", - "syn 2.0.32", + "syn 2.0.38", "tokio", "void", ] @@ -5283,21 +5273,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.32", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" -dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 1.0.95", - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -5475,9 +5451,9 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70550716265d1ec349c41f70dd4f964b4fd88394efe4405f0c1da679c4799a07" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.32", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.38", ] [[package]] @@ -7434,7 +7410,7 @@ version = "1.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c834b4e02ac911b13c13aed08b3f847e722f6be79d31b1c660c1dbd2dee83cdb" dependencies = [ - "bs58", + "bs58 0.4.0", "proc-macro2 1.0.69", "quote 1.0.33", "rustversion", @@ -8161,7 +8137,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 1.0.95", + "syn 2.0.38", ] [[package]] @@ -8301,7 +8277,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 1.0.95", + "syn 2.0.38", ] [[package]] @@ -8470,7 +8446,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 1.0.95", + "syn 2.0.38", ] [[package]] @@ -9003,21 +8979,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasm-timer" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" -dependencies = [ - "futures 0.3.15", - "js-sys", - "parking_lot 0.11.1", - "pin-utils", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "web-sys" version = "0.3.55" diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 42fea227ae..3d2a962297 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -34,7 +34,6 @@ use bitcrypto::dhash256; use chain::constants::SEQUENCE_FINAL; use chain::{Transaction as UtxoTx, TransactionOutput}; use common::executor::{AbortableSystem, AbortedError}; -use common::sha256_digest; use common::{log, one_thousand_u32}; use crypto::privkey::{key_pair_from_secret, secp_privkey_from_hash}; use crypto::{Bip32DerPathOps, GlobalHDAccountArc}; @@ -91,7 +90,7 @@ pub use z_rpc::{FirstSyncBlock, SyncStatus}; cfg_native!( use crate::utxo::utxo_common::{addresses_from_script, big_decimal_from_sat}; - use common::{async_blocking, calc_total_pages, PagingOptionsEnum}; + use common::{async_blocking, sha256_digest, calc_total_pages, PagingOptionsEnum}; use db_common::sqlite::offset_by_id; use db_common::sqlite::rusqlite::{Error as SqlError, Row}; use db_common::sqlite::sql_builder::{name, SqlBuilder, SqlName}; @@ -130,13 +129,13 @@ macro_rules! try_ztx_s { const DEX_FEE_OVK: OutgoingViewingKey = OutgoingViewingKey([7; 32]); const DEX_FEE_Z_ADDR: &str = "zs1rp6426e9r6jkq2nsanl66tkd34enewrmr0uvj0zelhkcwmsy0uvxz2fhm9eu9rl3ukxvgzy2v9f"; -const SAPLING_SPEND_NAME: &str = "sapling-spend.params"; -const SAPLING_OUTPUT_NAME: &str = "sapling-output.params"; -const SAPLING_SPEND_EXPECTED_HASH: &str = "8e48ffd23abb3a5fd9c5589204f32d9c31285a04b78096ba40a79b75677efc13"; -const SAPLING_OUTPUT_EXPECTED_HASH: &str = "2f0ebbcbb9bb0bcffe95a397e7eba89c29eb4dde6191c339db88570e3f3fb0e4"; cfg_native!( const BLOCKS_TABLE: &str = "blocks"; + const SAPLING_OUTPUT_NAME: &str = "sapling-output.params"; + const SAPLING_SPEND_NAME: &str = "sapling-spend.params"; const TRANSACTIONS_TABLE: &str = "transactions"; + const SAPLING_SPEND_EXPECTED_HASH: &str = "8e48ffd23abb3a5fd9c5589204f32d9c31285a04b78096ba40a79b75677efc13"; + const SAPLING_OUTPUT_EXPECTED_HASH: &str = "2f0ebbcbb9bb0bcffe95a397e7eba89c29eb4dde6191c339db88570e3f3fb0e4"; ); #[derive(Clone, Debug, Serialize, Deserialize)] @@ -830,12 +829,14 @@ pub async fn z_coin_from_conf_and_params( builder.build().await } +#[cfg(not(target_arch = "wasm32"))] fn verify_checksum_zcash_params(spend_path: &PathBuf, output_path: &PathBuf) -> Result { let spend_hash = sha256_digest(spend_path)?; let out_hash = sha256_digest(output_path)?; Ok(spend_hash == SAPLING_SPEND_EXPECTED_HASH && out_hash == SAPLING_OUTPUT_EXPECTED_HASH) } +#[cfg(not(target_arch = "wasm32"))] fn get_spend_output_paths(params_dir: PathBuf) -> Result<(PathBuf, PathBuf), ZCoinBuildError> { if !params_dir.exists() { return Err(ZCoinBuildError::ZCashParamsNotFound); diff --git a/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs b/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs index e8cfe3b170..b1310ec492 100644 --- a/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs +++ b/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs @@ -212,7 +212,7 @@ impl<'a> WalletIndexedDb { }; let index_keys = MultiIndex::new(WalletDbAccountsTable::TICKER_ACCOUNT_INDEX) - .with_value(&ticker)? + .with_value(&self.ticker)? .with_value(account_int)?; walletdb_account_table diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index fb5b1d1c71..270d4dc269 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -31,7 +31,7 @@ use zcash_primitives::transaction::TxId; use zcash_primitives::zip32::ExtendedSpendingKey; pub(crate) mod z_coin_grpc { - tonic::include_proto!("pirate.z.wallet.sdk.rpc"); + tonic::include_proto!("pirate.wallet.sdk.rpc"); } use z_coin_grpc::compact_tx_streamer_client::CompactTxStreamerClient; use z_coin_grpc::ChainSpec; @@ -820,10 +820,12 @@ async fn light_wallet_db_sync_loop(mut sync_handle: SaplingSyncLoopHandle, mut c if let Some(tx_id) = sync_handle.watch_for_tx { let walletdb = &sync_handle.wallet_db; - if !walletdb.is_tx_imported(tx_id).await { - info!("Tx {} is not imported yet", tx_id); - Timer::sleep(10.).await; - continue; + if let Ok(is_tx_imported) = walletdb.is_tx_imported(tx_id).await { + if !is_tx_imported { + info!("Tx {} is not imported yet", tx_id); + Timer::sleep(10.).await; + continue; + } } sync_handle.watch_for_tx = None; } diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index ad0df1da1c..b090efc0d0 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -7,12 +7,12 @@ use crypto::StandardHDCoinAddress; use mm2_core::mm_ctx::MmArc; use mm2_number::BigDecimal; use mm2_rpc::data::legacy::OrderbookResponse; -use mm2_test_helpers::electrums::{morty_electrums, rick_electrums}; +use mm2_test_helpers::electrums::{doc_electrums, marty_electrums}; use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init_z_coin_light_with_short_height, init_z_coin_status, morty_conf, rick_conf, start_swaps, test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, zombie_conf, MarketMakerIt, Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, MORTY, RICK, - ZOMBIE_ELECTRUMS_WSS, ZOMBIE_LIGHTWALLETD_PROXIED_URLS, ZOMBIE_TICKER}; + ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, ZOMBIE_TICKER}; use mm2_test_helpers::get_passphrase; use mm2_test_helpers::structs::{EnableCoinBalance, InitTaskResult, InitZcoinStatus, RpcV2Response, ZCoinActivationResult}; @@ -200,7 +200,6 @@ async fn enable_z_coin_light( coin: &str, electrums: &[&str], lightwalletd_urls: &[&str], - starting_date: Option, account: Option, ) -> ZCoinActivationResult { let init = init_z_coin_light_with_short_height(mm, coin, electrums, lightwalletd_urls, account).await; @@ -232,15 +231,8 @@ async fn activate_z_coin_light() { .await .unwrap(); - let activation_result = enable_z_coin_light( - &mm, - ZOMBIE_TICKER, - ZOMBIE_ELECTRUMS_WSS, - ZOMBIE_LIGHTWALLETD_PROXIED_URLS, - None, - None, - ) - .await; + let activation_result = + enable_z_coin_light(&mm, ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None).await; let balance = match activation_result.wallet_balance { EnableCoinBalance::Iguana(iguana) => iguana, diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index 59444442e6..f02160f9bd 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -159,12 +159,16 @@ pub const MARTY_ELECTRUM_ADDRS: &[&str] = &[ ]; pub const ZOMBIE_TICKER: &str = "ZOMBIE"; pub const ARRR: &str = "ARRR"; +#[cfg(not(target_arch = "wasm32"))] pub const ZOMBIE_ELECTRUMS: &[&str] = &[ "electrum1.cipig.net:10008", "electrum2.cipig.net:10008", "electrum3.cipig.net:10008", ]; -pub const ZOMBIE_ELECTRUMS_WSS: &[&str] = &["zombie.dragonhound.info:30059"]; +#[cfg(target_arch = "wasm32")] +pub const ZOMBIE_ELECTRUMS: &[&str] = &["zombie.dragonhound.info:30059"]; + +#[cfg(not(target_arch = "wasm32"))] pub const ZOMBIE_LIGHTWALLETD_URLS: &[&str] = &[ "https://lightd1.pirate.black:443", "https://piratelightd1.cryptoforge.cc:443", @@ -172,7 +176,8 @@ pub const ZOMBIE_LIGHTWALLETD_URLS: &[&str] = &[ "https://piratelightd3.cryptoforge.cc:443", "https://piratelightd4.cryptoforge.cc:443", ]; -pub const ZOMBIE_LIGHTWALLETD_PROXIED_URLS: &[&str] = &["http://pirate.spyglass.quest:8081"]; +#[cfg(target_arch = "wasm32")] +pub const ZOMBIE_LIGHTWALLETD_URLS: &[&str] = &["http://pirate.spyglass.quest:8081"]; pub const PIRATE_ELECTRUMS: &[&str] = &["node1.chainkeeper.pro:10132"]; pub const PIRATE_LIGHTWALLETD_URLS: &[&str] = &["http://node1.chainkeeper.pro:443"]; pub const DEFAULT_RPC_PASSWORD: &str = "pass"; From ba5018501c0368afd58032a0a16a251c1c7ed99f Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 21:02:21 +0100 Subject: [PATCH 24/68] fix wasm unit test query_blocks_by_limit Signed-off-by: borngraced --- mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs | 3 +-- mm2src/mm2_test_helpers/src/for_tests.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs index ed8ab50ff9..36e579a1a2 100644 --- a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs +++ b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs @@ -172,11 +172,10 @@ impl BlockDbImpl { // Fetch CompactBlocks block_db are needed for scanning. let min = u32::from(from_height + 1); - let cursor_limit = limit.unwrap_or(u32::MIN); let mut maybe_blocks = block_db .cursor_builder() .only("ticker", &self.ticker)? - .bound("height", min, min + cursor_limit) + .bound("height", min + 1, u32::MAX) .open_cursor(BlockDbTable::TICKER_HEIGHT_INDEX) .await?; diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index f02160f9bd..230bf4a690 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -2458,7 +2458,7 @@ pub async fn init_z_coin_light_with_short_height( "electrum_servers": electrum_servers_rpc(electrums), "light_wallet_d_servers": lightwalletd_urls, "sync_params": { - "height": 2626265 + "height": 2626280 } }, }, From a2040b0b4ad26e47b44d7276485a488e0a8034ff Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 23:18:28 +0100 Subject: [PATCH 25/68] additional fixes for query_blocks_by_limit Signed-off-by: borngraced --- mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs index 36e579a1a2..53c8b67419 100644 --- a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs +++ b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs @@ -175,7 +175,7 @@ impl BlockDbImpl { let mut maybe_blocks = block_db .cursor_builder() .only("ticker", &self.ticker)? - .bound("height", min + 1, u32::MAX) + .bound("height", min, u32::MAX) .open_cursor(BlockDbTable::TICKER_HEIGHT_INDEX) .await?; From 207cd893b532130443bc904aa4af95ba027e9c87 Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 25 Oct 2023 23:39:48 +0100 Subject: [PATCH 26/68] use cash.z.wallet.sdk.rpc Signed-off-by: borngraced --- mm2src/coins/z_coin/compact_formats.proto | 2 +- mm2src/coins/z_coin/service.proto | 2 +- mm2src/coins/z_coin/z_rpc.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mm2src/coins/z_coin/compact_formats.proto b/mm2src/coins/z_coin/compact_formats.proto index 9a88707355..e20c05a56b 100644 --- a/mm2src/coins/z_coin/compact_formats.proto +++ b/mm2src/coins/z_coin/compact_formats.proto @@ -1,5 +1,5 @@ syntax = "proto3"; -package pirate.wallet.sdk.rpc; +package cash.z.wallet.sdk.rpc; option go_package = "walletrpc"; option swift_prefix = ""; // Remember that proto3 fields are all optional. A field that is not present will be set to its zero value. diff --git a/mm2src/coins/z_coin/service.proto b/mm2src/coins/z_coin/service.proto index e8cd6f6ea2..d0a7085675 100644 --- a/mm2src/coins/z_coin/service.proto +++ b/mm2src/coins/z_coin/service.proto @@ -3,7 +3,7 @@ // file COPYING or https://www.opensource.org/licenses/mit-license.php . syntax = "proto3"; -package pirate.wallet.sdk.rpc; +package cash.z.wallet.sdk.rpc; option go_package = ".;walletrpc"; option swift_prefix = ""; import "compact_formats.proto"; diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 270d4dc269..186642665a 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -31,7 +31,7 @@ use zcash_primitives::transaction::TxId; use zcash_primitives::zip32::ExtendedSpendingKey; pub(crate) mod z_coin_grpc { - tonic::include_proto!("pirate.wallet.sdk.rpc"); + tonic::include_proto!("cash.z.wallet.sdk.rpc"); } use z_coin_grpc::compact_tx_streamer_client::CompactTxStreamerClient; use z_coin_grpc::ChainSpec; From 25bd013d833d24e35dc7f972034a40f170f7f780 Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 26 Oct 2023 00:15:38 +0100 Subject: [PATCH 27/68] increase timeout and starting height Signed-off-by: borngraced --- mm2src/mm2_main/src/wasm_tests.rs | 2 +- mm2src/mm2_test_helpers/src/for_tests.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index b090efc0d0..e33b5e521f 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -204,7 +204,7 @@ async fn enable_z_coin_light( ) -> ZCoinActivationResult { let init = init_z_coin_light_with_short_height(mm, coin, electrums, lightwalletd_urls, account).await; let init: RpcV2Response = json::from_value(init).unwrap(); - let timeout = wait_until_sec(120); + let timeout = wait_until_sec(240); loop { if now_sec() > timeout { diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index 230bf4a690..944f866107 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -2458,7 +2458,7 @@ pub async fn init_z_coin_light_with_short_height( "electrum_servers": electrum_servers_rpc(electrums), "light_wallet_d_servers": lightwalletd_urls, "sync_params": { - "height": 2626280 + "height": 2626737 } }, }, From 7f6fe581fd270fc55329eb786bdaa91c0673cff1 Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 26 Oct 2023 00:32:57 +0100 Subject: [PATCH 28/68] increase timeout Signed-off-by: borngraced --- mm2src/mm2_main/src/wasm_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index e33b5e521f..a47067fa67 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -204,7 +204,7 @@ async fn enable_z_coin_light( ) -> ZCoinActivationResult { let init = init_z_coin_light_with_short_height(mm, coin, electrums, lightwalletd_urls, account).await; let init: RpcV2Response = json::from_value(init).unwrap(); - let timeout = wait_until_sec(240); + let timeout = wait_until_sec(600); loop { if now_sec() > timeout { From 3b1cacf7341f628e026a198464d4306227ceedff Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 26 Oct 2023 02:21:35 +0100 Subject: [PATCH 29/68] log Signed-off-by: borngraced --- mm2src/coins/z_coin/storage.rs | 3 +++ mm2src/coins/z_coin/z_rpc.rs | 1 + mm2src/mm2_main/src/wasm_tests.rs | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mm2src/coins/z_coin/storage.rs b/mm2src/coins/z_coin/storage.rs index 8acb7778ca..d75a86b42e 100644 --- a/mm2src/coins/z_coin/storage.rs +++ b/mm2src/coins/z_coin/storage.rs @@ -6,6 +6,7 @@ pub use blockdb::*; pub mod walletdb; pub use walletdb::*; +use common::log::info; #[cfg(target_arch = "wasm32")] use walletdb::wasm::storage::DataConnStmtCacheWasm; #[cfg(debug_assertions)] @@ -183,6 +184,8 @@ pub async fn scan_cached_block( ) .await?; + info!("INSERTED: {current_height}"); + let spent_nf: Vec = txs .iter() .flat_map(|tx| tx.shielded_spends.iter().map(|spend| spend.nf)) diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 186642665a..80c986fee0 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -716,6 +716,7 @@ impl SaplingSyncLoopHandle { ) .await; if let Err(e) = validate_chain { + info!("ERROR: {e:?}"); match e.into_inner() { ZcoinStorageError::ValidateBlocksError(ValidateBlocksError::ChainInvalid { height, .. }) => { let lower_bound = height; diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index a47067fa67..b491d21a4e 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -204,7 +204,7 @@ async fn enable_z_coin_light( ) -> ZCoinActivationResult { let init = init_z_coin_light_with_short_height(mm, coin, electrums, lightwalletd_urls, account).await; let init: RpcV2Response = json::from_value(init).unwrap(); - let timeout = wait_until_sec(600); + let timeout = wait_until_sec(300); loop { if now_sec() > timeout { From 2775bb55c38875c6b327a108723aaaa84f112b82 Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 26 Oct 2023 04:22:38 +0100 Subject: [PATCH 30/68] minor fixes to block_idb mod Signed-off-by: borngraced --- .../storage/blockdb/blockdb_idb_storage.rs | 38 +++++++++++++++---- mm2src/coins/z_coin/z_rpc.rs | 5 +-- mm2src/mm2_main/src/wasm_tests.rs | 13 +++---- mm2src/mm2_test_helpers/src/for_tests.rs | 2 +- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs index 53c8b67419..89c35aee36 100644 --- a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs +++ b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs @@ -29,7 +29,7 @@ pub struct BlockDbTable { } impl BlockDbTable { - pub const TICKER_HEIGHT_INDEX: &str = "block_height_ticker_index"; + pub const TICKER_HEIGHT_INDEX: &str = "ticker_height_index"; } impl TableSignature for BlockDbTable { @@ -217,22 +217,44 @@ impl BlockDbImpl { })?, }; - let blocks = self.query_blocks_by_limit(from_height, limit).await?; + let locked_db = self.lock_db().await?; + let db_transaction = locked_db.get_inner().transaction().await?; + let block_db = db_transaction.table::().await?; + + // Fetch CompactBlocks block_db are needed for scanning. + let min = u32::from(from_height + 1); + let mut maybe_blocks = block_db + .cursor_builder() + .only("ticker", &self.ticker)? + .bound("height", min, u32::MAX) + .open_cursor(BlockDbTable::TICKER_HEIGHT_INDEX) + .await?; + + let mut blocks_to_scan = vec![]; + while let Some((_, block)) = maybe_blocks.next().await? { + if let Some(limit) = limit { + if blocks_to_scan.len() > limit as usize { + break; + } + }; + + blocks_to_scan.push(CompactBlockRow { + height: block.height.into(), + data: block.data, + }); + } let mut prev_height = from_height; let mut prev_hash: Option = validate_from.map(|(_, hash)| hash); - for block in blocks { + let blocks_len = blocks_to_scan.len(); + for block in blocks_to_scan { if let Some(limit) = limit { - if u32::from(block.height) > limit { + if blocks_len > limit as usize { break; } } - if block.height < from_height { - continue; - } - let cbr = block; let block = CompactBlock::parse_from_bytes(&cbr.data) .map_to_mm(|err| ZcoinStorageError::DecodingError(err.to_string()))?; diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 80c986fee0..df290919b6 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -701,7 +701,6 @@ impl SaplingSyncLoopHandle { /// Scans cached blocks, validates the chain and updates WalletDb. /// For more notes on the process, check https://github.com/zcash/librustzcash/blob/master/zcash_client_backend/src/data_api/chain.rs#L2 async fn scan_validate_and_update_blocks(&mut self) -> Result<(), MmError> { - // required to avoid immutable borrow of self let wallet_db = self.wallet_db.clone().db; let wallet_ops_guard = wallet_db.get_update_ops().expect("get_update_ops always returns Ok"); let mut wallet_ops_guard_clone = wallet_ops_guard.clone(); @@ -716,7 +715,6 @@ impl SaplingSyncLoopHandle { ) .await; if let Err(e) = validate_chain { - info!("ERROR: {e:?}"); match e.into_inner() { ZcoinStorageError::ValidateBlocksError(ValidateBlocksError::ChainInvalid { height, .. }) => { let lower_bound = height; @@ -748,6 +746,7 @@ impl SaplingSyncLoopHandle { let wallet_ops_guard = wallet_db.get_update_ops().expect("get_update_ops always returns Ok"); let scan = DataConnStmtCacheWrapper::new(wallet_ops_guard); + info!("START SCANNING WALLETDB"); blocks_db .process_blocks_with_mode( self.consensus_params.clone(), @@ -799,7 +798,7 @@ async fn light_wallet_db_sync_loop(mut sync_handle: SaplingSyncLoopHandle, mut c "(Re)starting light_wallet_db_sync_loop for {}, blocks per iteration {}, interval in ms {}", sync_handle.coin, sync_handle.scan_blocks_per_iteration, sync_handle.scan_interval_ms ); - // this loop is spawned as standalone task so it's safe to use block_in_place here + loop { if let Err(e) = sync_handle.update_blocks_cache(client.as_mut()).await { error!("Error {} on blocks cache update", e); diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index b491d21a4e..b7dc7e1716 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -9,10 +9,10 @@ use mm2_number::BigDecimal; use mm2_rpc::data::legacy::OrderbookResponse; use mm2_test_helpers::electrums::{doc_electrums, marty_electrums}; use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init_z_coin_light_with_short_height, - init_z_coin_status, morty_conf, rick_conf, start_swaps, test_qrc20_history_impl, - wait_for_swaps_finish_and_check_status, zombie_conf, MarketMakerIt, - Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, MORTY, RICK, - ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, ZOMBIE_TICKER}; + init_z_coin_status, morty_conf, pirate_conf, rick_conf, start_swaps, + test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, MarketMakerIt, + Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, RICK, + ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS}; use mm2_test_helpers::get_passphrase; use mm2_test_helpers::structs::{EnableCoinBalance, InitTaskResult, InitZcoinStatus, RpcV2Response, ZCoinActivationResult}; @@ -224,15 +224,14 @@ async fn enable_z_coin_light( #[wasm_bindgen_test] async fn activate_z_coin_light() { register_wasm_log(); - let coins = json!([zombie_conf()]); + let coins = json!([pirate_conf()]); let conf = Mm2TestConf::seednode(ZOMBIE_TEST_BALANCE_SEED, &coins); let mm = MarketMakerIt::start_async(conf.conf, conf.rpc_password, Some(wasm_start)) .await .unwrap(); - let activation_result = - enable_z_coin_light(&mm, ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None).await; + let activation_result = enable_z_coin_light(&mm, ARRR, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None).await; let balance = match activation_result.wallet_balance { EnableCoinBalance::Iguana(iguana) => iguana, diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index 944f866107..c0736b91a6 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -2458,7 +2458,7 @@ pub async fn init_z_coin_light_with_short_height( "electrum_servers": electrum_servers_rpc(electrums), "light_wallet_d_servers": lightwalletd_urls, "sync_params": { - "height": 2626737 + "height": 2626830 } }, }, From 18e0c06e10ae82bc0616c84f190a13b073a33b82 Mon Sep 17 00:00:00 2001 From: borngraced Date: Fri, 27 Oct 2023 05:26:51 +0100 Subject: [PATCH 31/68] update librustzcash and remove redundancy code Signed-off-by: borngraced --- Cargo.lock | 20 +- mm2src/coins/Cargo.toml | 13 +- mm2src/coins/z_coin/storage.rs | 3 - .../coins/z_coin/storage/walletdb/wasm/mod.rs | 563 +++++++++--------- mm2src/mm2_main/src/wasm_tests.rs | 12 +- mm2src/mm2_test_helpers/src/for_tests.rs | 41 -- 6 files changed, 304 insertions(+), 348 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a7af241524..f14502e8b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1428,7 +1428,7 @@ dependencies = [ "crossbeam-utils 0.7.2", "lazy_static", "maybe-uninit", - "memoffset 0.5.4", + "memoffset 0.5.6", "scopeguard", ] @@ -2097,7 +2097,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.1.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=37623e3#37623e3b4c9fa6b2ebe712f8f9b0f90044e5dd01" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=b381253#b3812539206e100d7fd5e70a2e42beb1cf2977cd" dependencies = [ "blake2b_simd", "byteorder", @@ -4105,9 +4105,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ "autocfg 1.1.0", ] @@ -9430,7 +9430,7 @@ checksum = "0f9079049688da5871a7558ddacb7f04958862c703e68258594cb7a862b5e33f" [[package]] name = "zcash_client_backend" version = "0.5.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=37623e3#37623e3b4c9fa6b2ebe712f8f9b0f90044e5dd01" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=b381253#b3812539206e100d7fd5e70a2e42beb1cf2977cd" dependencies = [ "async-trait", "base64 0.13.0", @@ -9456,7 +9456,7 @@ dependencies = [ [[package]] name = "zcash_client_sqlite" version = "0.3.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=37623e3#37623e3b4c9fa6b2ebe712f8f9b0f90044e5dd01" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=b381253#b3812539206e100d7fd5e70a2e42beb1cf2977cd" dependencies = [ "async-trait", "bech32", @@ -9479,7 +9479,7 @@ dependencies = [ [[package]] name = "zcash_extras" version = "0.1.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=37623e3#37623e3b4c9fa6b2ebe712f8f9b0f90044e5dd01" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=b381253#b3812539206e100d7fd5e70a2e42beb1cf2977cd" dependencies = [ "async-trait", "ff 0.8.0", @@ -9495,7 +9495,7 @@ dependencies = [ [[package]] name = "zcash_note_encryption" version = "0.0.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=37623e3#37623e3b4c9fa6b2ebe712f8f9b0f90044e5dd01" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=b381253#b3812539206e100d7fd5e70a2e42beb1cf2977cd" dependencies = [ "blake2b_simd", "byteorder", @@ -9509,7 +9509,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.5.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=37623e3#37623e3b4c9fa6b2ebe712f8f9b0f90044e5dd01" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=b381253#b3812539206e100d7fd5e70a2e42beb1cf2977cd" dependencies = [ "aes", "bitvec 0.18.5", @@ -9539,7 +9539,7 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.5.0" -source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=37623e3#37623e3b4c9fa6b2ebe712f8f9b0f90044e5dd01" +source = "git+https://github.com/KomodoPlatform/librustzcash.git?rev=b381253#b3812539206e100d7fd5e70a2e42beb1cf2977cd" dependencies = [ "bellman", "blake2b_simd", diff --git a/mm2src/coins/Cargo.toml b/mm2src/coins/Cargo.toml index 3d85678538..f21a0b222e 100644 --- a/mm2src/coins/Cargo.toml +++ b/mm2src/coins/Cargo.toml @@ -104,10 +104,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.19.0", default-features = false } zbase32 = "0.1.2" -zcash_client_backend = { git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "37623e3" } -zcash_extras = { git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "37623e3" } -zcash_primitives = {features = ["transparent-inputs"], git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "37623e3" } -zcash_proofs = { git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "37623e3" } +zcash_client_backend = { git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "b381253" } +zcash_extras = { git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "b381253" } +zcash_primitives = {features = ["transparent-inputs"], git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "b381253" } [target.'cfg(all(not(target_os = "ios"), not(target_os = "android"), not(target_arch = "wasm32")))'.dependencies] bincode = { version = "1.3.3", default-features = false, optional = true } @@ -134,7 +133,7 @@ wasm-bindgen-futures = { version = "0.4.1" } wasm-bindgen-test = { version = "0.3.2" } wagyu-zcash-parameters = { version = "0.2" } web-sys = { version = "0.3.55", features = ["console", "Headers", "Request", "RequestInit", "RequestMode", "Response", "Window"] } -zcash_proofs = { git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "37623e3", default-features = false, features = ["local-prover"] } +zcash_proofs = { git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "b381253", default-features = false, features = ["local-prover"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] dirs = { version = "1" } @@ -155,8 +154,8 @@ tokio = { version = "1.20" } tokio-rustls = { version = "0.23" } tonic = { version = "0.7", features = ["tls", "tls-webpki-roots", "compression"] } webpki-roots = { version = "0.22" } -zcash_client_sqlite = { git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "37623e3" } -zcash_proofs = { git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "37623e3", default-features =false, features = ["local-prover", "multicore"] } +zcash_client_sqlite = { git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "b381253" } +zcash_proofs = { git = "https://github.com/KomodoPlatform/librustzcash.git", rev = "b381253" } [target.'cfg(windows)'.dependencies] winapi = "0.3" diff --git a/mm2src/coins/z_coin/storage.rs b/mm2src/coins/z_coin/storage.rs index d75a86b42e..8acb7778ca 100644 --- a/mm2src/coins/z_coin/storage.rs +++ b/mm2src/coins/z_coin/storage.rs @@ -6,7 +6,6 @@ pub use blockdb::*; pub mod walletdb; pub use walletdb::*; -use common::log::info; #[cfg(target_arch = "wasm32")] use walletdb::wasm::storage::DataConnStmtCacheWasm; #[cfg(debug_assertions)] @@ -184,8 +183,6 @@ pub async fn scan_cached_block( ) .await?; - info!("INSERTED: {current_height}"); - let spent_nf: Vec = txs .iter() .flat_map(|tx| tx.shielded_spends.iter().map(|spend| spend.nf)) diff --git a/mm2src/coins/z_coin/storage/walletdb/wasm/mod.rs b/mm2src/coins/z_coin/storage/walletdb/wasm/mod.rs index de94d4c791..85b81a2ba5 100644 --- a/mm2src/coins/z_coin/storage/walletdb/wasm/mod.rs +++ b/mm2src/coins/z_coin/storage/walletdb/wasm/mod.rs @@ -83,6 +83,7 @@ mod wasm_test { use crate::z_coin::storage::{BlockDbImpl, BlockProcessingMode, DataConnStmtCacheWasm, DataConnStmtCacheWrapper}; use crate::z_coin::{ValidateBlocksError, ZcoinConsensusParams, ZcoinStorageError}; use crate::ZcoinProtocolInfo; + use common::log::wasm_log::register_wasm_log; use mm2_test_helpers::for_tests::mm_ctx_with_custom_db; use protobuf::Message; use wasm_bindgen_test::*; @@ -138,6 +139,8 @@ mod wasm_test { WalletIndexedDb::new(&ctx, ticker, consensus_params).await.unwrap() } + fn network() -> Network { Network::TestNetwork } + #[wasm_bindgen_test] async fn test_empty_database_has_no_balance() { let db = wallet_db_from_zcoin_builder_for_test(TICKER).await; @@ -726,150 +729,148 @@ mod wasm_test { assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value - value2); } - fn network() -> Network { Network::TestNetwork } + #[wasm_bindgen_test] + async fn create_to_address_fails_on_unverified_notes() { + // init blocks_db + let ctx = mm_ctx_with_custom_db(); + let blockdb = BlockDbImpl::new(ctx, TICKER.to_string(), Some("")).await.unwrap(); + + // init walletdb. + let mut walletdb = wallet_db_from_zcoin_builder_for_test(TICKER).await; + let consensus_params = consensus_params(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + assert!(walletdb.init_accounts_table(&[extfvk.clone()]).await.is_ok()); - // #[wasm_bindgen_test] - // async fn create_to_address_fails_on_unverified_notes() { - // // init blocks_db - // let ctx = mm_ctx_with_custom_db(); - // let blockdb = BlockDbImpl::new(ctx, TICKER.to_string(), Some("")).await.unwrap(); - // - // // init walletdb. - // let mut walletdb = wallet_db_from_zcoin_builder_for_test(TICKER).await; - // let consensus_params = consensus_params(); - // - // // Add an account to the wallet - // let extsk = ExtendedSpendingKey::master(&[]); - // let extfvk = ExtendedFullViewingKey::from(&extsk); - // assert!(walletdb.init_accounts_table(&[extfvk.clone()]).await.is_ok()); - // - // // Account balance should be zero - // assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), Amount::zero()); - // - // // Add funds to the wallet in a single note - // let value = Amount::from_u64(50000).unwrap(); - // let (cb, _) = fake_compact_block(sapling_activation_height(), BlockHash([0; 32]), extfvk.clone(), value); - // let cb_bytes = cb.write_to_bytes().unwrap(); - // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - // - // // Scan the cache - // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - // assert!(blockdb - // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - // .await - // .is_ok()); - // - // // Verified balance matches total balance - // let (_, anchor_height) = walletdb.get_target_and_anchor_heights().await.unwrap().unwrap(); - // assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value); - // assert_eq!( - // walletdb.get_balance_at(AccountId(0), anchor_height).await.unwrap(), - // value - // ); - // - // // Add more funds to the wallet in a second note - // let (cb, _) = fake_compact_block(sapling_activation_height() + 1, cb.hash(), extfvk.clone(), value); - // let cb_bytes = cb.write_to_bytes().unwrap(); - // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - // - // // Scan the cache - // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - // assert!(blockdb - // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - // .await - // .is_ok()); - // - // // Verified balance does not include the second note - // let (_, anchor_height2) = walletdb.get_target_and_anchor_heights().await.unwrap().unwrap(); - // assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value + value); - // assert_eq!( - // walletdb.get_balance_at(AccountId(0), anchor_height2).await.unwrap(), - // value - // ); - // - // // Spend fails because there are insufficient verified notes - // let extsk2 = ExtendedSpendingKey::master(&[]); - // let to = extsk2.default_address().unwrap().1.into(); - // match create_spend_to_address( - // &mut walletdb, - // &network(), - // test_prover(), - // AccountId(0), - // &extsk, - // &to, - // Amount::from_u64(70000).unwrap(), - // None, - // OvkPolicy::Sender, - // ) - // .await - // { - // Ok(_) => panic!("Should have failed"), - // Err(e) => assert!(e - // .to_string() - // .contains("Insufficient balance (have 50000, need 71000 including fee)")), - // } - // - // // Mine blocks SAPLING_ACTIVATION_HEIGHT + 2 to 9 until just before the second - // // note is verified - // for i in 2..10 { - // let (cb, _) = fake_compact_block(sapling_activation_height() + i, cb.hash(), extfvk.clone(), value); - // let cb_bytes = cb.write_to_bytes().unwrap(); - // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - // } - // - // // Scan the cache - // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - // assert!(blockdb - // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - // .await - // .is_ok()); - // - // // Second spend still fails - // match create_spend_to_address( - // &mut walletdb, - // &network(), - // test_prover(), - // AccountId(0), - // &extsk, - // &to, - // Amount::from_u64(70000).unwrap(), - // None, - // OvkPolicy::Sender, - // ) - // .await - // { - // Ok(_) => panic!("Should have failed"), - // Err(e) => assert!(e - // .to_string() - // .contains("Insufficient balance (have 50000, need 71000 including fee)")), - // } - // - // // Mine block 11 so that the second note becomes verified - // let (cb, _) = fake_compact_block(sapling_activation_height() + 10, cb.hash(), extfvk, value); - // let cb_bytes = cb.write_to_bytes().unwrap(); - // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - // // Scan the cache - // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - // assert!(blockdb - // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - // .await - // .is_ok()); - // - // // Second spend should now succeed - // create_spend_to_address( - // &mut walletdb, - // &network(), - // test_prover(), - // AccountId(0), - // &extsk, - // &to, - // Amount::from_u64(70000).unwrap(), - // None, - // OvkPolicy::Sender, - // ) - // .await - // .unwrap(); - // } + // Account balance should be zero + assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), Amount::zero()); + + // Add funds to the wallet in a single note + let value = Amount::from_u64(50000).unwrap(); + let (cb, _) = fake_compact_block(sapling_activation_height(), BlockHash([0; 32]), extfvk.clone(), value); + let cb_bytes = cb.write_to_bytes().unwrap(); + blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + + // Scan the cache + let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + assert!(blockdb + .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + .await + .is_ok()); + + // Verified balance matches total balance + let (_, anchor_height) = walletdb.get_target_and_anchor_heights().await.unwrap().unwrap(); + assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value); + assert_eq!( + walletdb.get_balance_at(AccountId(0), anchor_height).await.unwrap(), + value + ); + + // Add more funds to the wallet in a second note + let (cb, _) = fake_compact_block(sapling_activation_height() + 1, cb.hash(), extfvk.clone(), value); + let cb_bytes = cb.write_to_bytes().unwrap(); + blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + + // Scan the cache + let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + assert!(blockdb + .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + .await + .is_ok()); + + // Verified balance does not include the second note + let (_, anchor_height2) = walletdb.get_target_and_anchor_heights().await.unwrap().unwrap(); + assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value + value); + assert_eq!( + walletdb.get_balance_at(AccountId(0), anchor_height2).await.unwrap(), + value + ); + + // Spend fails because there are insufficient verified notes + let extsk2 = ExtendedSpendingKey::master(&[]); + let to = extsk2.default_address().unwrap().1.into(); + match create_spend_to_address( + &mut walletdb, + &network(), + test_prover(), + AccountId(0), + &extsk, + &to, + Amount::from_u64(70000).unwrap(), + None, + OvkPolicy::Sender, + ) + .await + { + Ok(_) => panic!("Should have failed"), + Err(e) => assert!(e + .to_string() + .contains("Insufficient balance (have 50000, need 71000 including fee)")), + } + + // Mine blocks SAPLING_ACTIVATION_HEIGHT + 2 to 9 until just before the second + // note is verified + for i in 2..10 { + let (cb, _) = fake_compact_block(sapling_activation_height() + i, cb.hash(), extfvk.clone(), value); + let cb_bytes = cb.write_to_bytes().unwrap(); + blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + } + + // Scan the cache + let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + assert!(blockdb + .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + .await + .is_ok()); + + // Second spend still fails + match create_spend_to_address( + &mut walletdb, + &network(), + test_prover(), + AccountId(0), + &extsk, + &to, + Amount::from_u64(70000).unwrap(), + None, + OvkPolicy::Sender, + ) + .await + { + Ok(_) => panic!("Should have failed"), + Err(e) => assert!(e + .to_string() + .contains("Insufficient balance (have 50000, need 71000 including fee)")), + } + + // Mine block 11 so that the second note becomes verified + let (cb, _) = fake_compact_block(sapling_activation_height() + 10, cb.hash(), extfvk, value); + let cb_bytes = cb.write_to_bytes().unwrap(); + blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + // Scan the cache + let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + assert!(blockdb + .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + .await + .is_ok()); + + // Second spend should now succeed + create_spend_to_address( + &mut walletdb, + &network(), + test_prover(), + AccountId(0), + &extsk, + &to, + Amount::from_u64(70000).unwrap(), + None, + OvkPolicy::Sender, + ) + .await + .unwrap(); + } #[wasm_bindgen_test] async fn test_create_to_address_fails_on_incorrect_extsk() { @@ -990,142 +991,142 @@ mod wasm_test { } } - // #[wasm_bindgen_test] - // async fn test_create_to_address_fails_on_locked_notes() { - // register_wasm_log(); - // - // // init blocks_db - // let ctx = mm_ctx_with_custom_db(); - // let blockdb = BlockDbImpl::new(ctx, TICKER.to_string(), Some("")).await.unwrap(); - // - // // init walletdb. - // let mut walletdb = wallet_db_from_zcoin_builder_for_test(TICKER).await; - // let consensus_params = consensus_params(); - // - // // Add an account to the wallet - // let extsk = ExtendedSpendingKey::master(&[]); - // let extfvk = ExtendedFullViewingKey::from(&extsk); - // assert!(walletdb.init_accounts_table(&[extfvk.clone()]).await.is_ok()); - // - // // Add funds to the wallet in a single note - // let value = Amount::from_u64(50000).unwrap(); - // let (cb, _) = fake_compact_block(sapling_activation_height(), BlockHash([0; 32]), extfvk, value); - // let cb_bytes = cb.write_to_bytes().unwrap(); - // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - // - // // Scan the cache - // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - // blockdb - // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - // .await - // .unwrap(); - // assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value); - // - // // Send some of the funds to another address - // let extsk2 = ExtendedSpendingKey::master(&[]); - // let to = extsk2.default_address().unwrap().1.into(); - // create_spend_to_address( - // &mut walletdb, - // &network(), - // test_prover(), - // AccountId(0), - // &extsk, - // &to, - // Amount::from_u64(15000).unwrap(), - // None, - // OvkPolicy::Sender, - // ) - // .await - // .unwrap(); - // - // // A second spend fails because there are no usable notes - // match create_spend_to_address( - // &mut walletdb, - // &network(), - // test_prover(), - // AccountId(0), - // &extsk, - // &to, - // Amount::from_u64(2000).unwrap(), - // None, - // OvkPolicy::Sender, - // ) - // .await - // { - // Ok(_) => panic!("Should have failed"), - // Err(e) => assert!(e - // .to_string() - // .contains("Insufficient balance (have 0, need 3000 including fee)")), - // } - // - // // Mine blocks SAPLING_ACTIVATION_HEIGHT + 1 to 21 (that don't send us funds) - // // until just before the first transaction expires - // for i in 1..22 { - // let (cb, _) = fake_compact_block( - // sapling_activation_height() + i, - // cb.hash(), - // ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[i as u8])), - // value, - // ); - // let cb_bytes = cb.write_to_bytes().unwrap(); - // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - // } - // // Scan the cache - // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - // blockdb - // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - // .await - // .unwrap(); - // - // // Second spend still fails - // match create_spend_to_address( - // &mut walletdb, - // &network(), - // test_prover(), - // AccountId(0), - // &extsk, - // &to, - // Amount::from_u64(2000).unwrap(), - // None, - // OvkPolicy::Sender, - // ) - // .await - // { - // Ok(_) => panic!("Should have failed"), - // Err(e) => assert!(e - // .to_string() - // .contains("Insufficient balance (have 0, need 3000 including fee)")), - // } - // - // // Mine block SAPLING_ACTIVATION_HEIGHT + 22 so that the first transaction expires - // let (cb, _) = fake_compact_block( - // sapling_activation_height() + 22, - // cb.hash(), - // ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[22])), - // value, - // ); - // let cb_bytes = cb.write_to_bytes().unwrap(); - // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - // // Scan the cache - // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - // blockdb - // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - // .await - // .unwrap(); - // - // // Second spend should now succeed - // create_spend_to_address( - // &mut walletdb, - // &network(), - // test_prover(), - // AccountId(0), - // &extsk, - // &to, - // Amount::from_u64(2000).unwrap(), - // None, - // OvkPolicy::Sender, - // ) - // .await - // .unwrap(); - // } + #[wasm_bindgen_test] + async fn test_create_to_address_fails_on_locked_notes() { + register_wasm_log(); + + // init blocks_db + let ctx = mm_ctx_with_custom_db(); + let blockdb = BlockDbImpl::new(ctx, TICKER.to_string(), Some("")).await.unwrap(); + + // init walletdb. + let mut walletdb = wallet_db_from_zcoin_builder_for_test(TICKER).await; + let consensus_params = consensus_params(); + + // Add an account to the wallet + let extsk = ExtendedSpendingKey::master(&[]); + let extfvk = ExtendedFullViewingKey::from(&extsk); + assert!(walletdb.init_accounts_table(&[extfvk.clone()]).await.is_ok()); + + // Add funds to the wallet in a single note + let value = Amount::from_u64(50000).unwrap(); + let (cb, _) = fake_compact_block(sapling_activation_height(), BlockHash([0; 32]), extfvk, value); + let cb_bytes = cb.write_to_bytes().unwrap(); + blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + + // Scan the cache + let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + blockdb + .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + .await + .unwrap(); + assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value); + + // Send some of the funds to another address + let extsk2 = ExtendedSpendingKey::master(&[]); + let to = extsk2.default_address().unwrap().1.into(); + create_spend_to_address( + &mut walletdb, + &network(), + test_prover(), + AccountId(0), + &extsk, + &to, + Amount::from_u64(15000).unwrap(), + None, + OvkPolicy::Sender, + ) + .await + .unwrap(); + + // A second spend fails because there are no usable notes + match create_spend_to_address( + &mut walletdb, + &network(), + test_prover(), + AccountId(0), + &extsk, + &to, + Amount::from_u64(2000).unwrap(), + None, + OvkPolicy::Sender, + ) + .await + { + Ok(_) => panic!("Should have failed"), + Err(e) => assert!(e + .to_string() + .contains("Insufficient balance (have 0, need 3000 including fee)")), + } + + // Mine blocks SAPLING_ACTIVATION_HEIGHT + 1 to 21 (that don't send us funds) + // until just before the first transaction expires + for i in 1..22 { + let (cb, _) = fake_compact_block( + sapling_activation_height() + i, + cb.hash(), + ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[i as u8])), + value, + ); + let cb_bytes = cb.write_to_bytes().unwrap(); + blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + } + // Scan the cache + let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + blockdb + .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + .await + .unwrap(); + + // Second spend still fails + match create_spend_to_address( + &mut walletdb, + &network(), + test_prover(), + AccountId(0), + &extsk, + &to, + Amount::from_u64(2000).unwrap(), + None, + OvkPolicy::Sender, + ) + .await + { + Ok(_) => panic!("Should have failed"), + Err(e) => assert!(e + .to_string() + .contains("Insufficient balance (have 0, need 3000 including fee)")), + } + + // Mine block SAPLING_ACTIVATION_HEIGHT + 22 so that the first transaction expires + let (cb, _) = fake_compact_block( + sapling_activation_height() + 22, + cb.hash(), + ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[22])), + value, + ); + let cb_bytes = cb.write_to_bytes().unwrap(); + blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + // Scan the cache + let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + blockdb + .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + .await + .unwrap(); + + // Second spend should now succeed + create_spend_to_address( + &mut walletdb, + &network(), + test_prover(), + AccountId(0), + &extsk, + &to, + Amount::from_u64(2000).unwrap(), + None, + OvkPolicy::Sender, + ) + .await + .unwrap(); + } } diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index b7dc7e1716..7ed0cf1c65 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -8,11 +8,11 @@ use mm2_core::mm_ctx::MmArc; use mm2_number::BigDecimal; use mm2_rpc::data::legacy::OrderbookResponse; use mm2_test_helpers::electrums::{doc_electrums, marty_electrums}; -use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init_z_coin_light_with_short_height, - init_z_coin_status, morty_conf, pirate_conf, rick_conf, start_swaps, - test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, MarketMakerIt, - Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, RICK, - ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS}; +use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init_z_coin_light, init_z_coin_status, + morty_conf, pirate_conf, rick_conf, start_swaps, test_qrc20_history_impl, + wait_for_swaps_finish_and_check_status, MarketMakerIt, Mm2InitPrivKeyPolicy, + Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, RICK, ZOMBIE_ELECTRUMS, + ZOMBIE_LIGHTWALLETD_URLS}; use mm2_test_helpers::get_passphrase; use mm2_test_helpers::structs::{EnableCoinBalance, InitTaskResult, InitZcoinStatus, RpcV2Response, ZCoinActivationResult}; @@ -202,7 +202,7 @@ async fn enable_z_coin_light( lightwalletd_urls: &[&str], account: Option, ) -> ZCoinActivationResult { - let init = init_z_coin_light_with_short_height(mm, coin, electrums, lightwalletd_urls, account).await; + let init = init_z_coin_light(mm, coin, electrums, lightwalletd_urls, None, account).await; let init: RpcV2Response = json::from_value(init).unwrap(); let timeout = wait_until_sec(300); diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index c0736b91a6..63f9cfcc38 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -2436,47 +2436,6 @@ pub async fn init_z_coin_light( json::from_str(&request.1).unwrap() } -pub async fn init_z_coin_light_with_short_height( - mm: &MarketMakerIt, - coin: &str, - electrums: &[&str], - lightwalletd_urls: &[&str], - account: Option, -) -> Json { - // Number of seconds in a day - let request = mm - .rpc(&json!({ - "userpass": mm.userpass, - "method": "task::enable_z_coin::init", - "mmrpc": "2.0", - "params": { - "ticker": coin, - "activation_params": { - "mode": { - "rpc": "Light", - "rpc_data": { - "electrum_servers": electrum_servers_rpc(electrums), - "light_wallet_d_servers": lightwalletd_urls, - "sync_params": { - "height": 2626830 - } - }, - }, - "account": account.unwrap_or_default(), - }, - } - })) - .await - .unwrap(); - assert_eq!( - request.0, - StatusCode::OK, - "'task::enable_z_coin::init' failed: {}", - request.1 - ); - json::from_str(&request.1).unwrap() -} - pub async fn init_z_coin_status(mm: &MarketMakerIt, task_id: u64) -> Json { let request = mm .rpc(&json!({ From 4131c7a17179ed88d172e2bbb75354a49b02870a Mon Sep 17 00:00:00 2001 From: borngraced Date: Fri, 27 Oct 2023 06:24:52 +0100 Subject: [PATCH 32/68] disable long runtime unit tests Signed-off-by: borngraced --- .../coins/z_coin/storage/walletdb/wasm/mod.rs | 563 +++++++++--------- 1 file changed, 281 insertions(+), 282 deletions(-) diff --git a/mm2src/coins/z_coin/storage/walletdb/wasm/mod.rs b/mm2src/coins/z_coin/storage/walletdb/wasm/mod.rs index 85b81a2ba5..de94d4c791 100644 --- a/mm2src/coins/z_coin/storage/walletdb/wasm/mod.rs +++ b/mm2src/coins/z_coin/storage/walletdb/wasm/mod.rs @@ -83,7 +83,6 @@ mod wasm_test { use crate::z_coin::storage::{BlockDbImpl, BlockProcessingMode, DataConnStmtCacheWasm, DataConnStmtCacheWrapper}; use crate::z_coin::{ValidateBlocksError, ZcoinConsensusParams, ZcoinStorageError}; use crate::ZcoinProtocolInfo; - use common::log::wasm_log::register_wasm_log; use mm2_test_helpers::for_tests::mm_ctx_with_custom_db; use protobuf::Message; use wasm_bindgen_test::*; @@ -139,8 +138,6 @@ mod wasm_test { WalletIndexedDb::new(&ctx, ticker, consensus_params).await.unwrap() } - fn network() -> Network { Network::TestNetwork } - #[wasm_bindgen_test] async fn test_empty_database_has_no_balance() { let db = wallet_db_from_zcoin_builder_for_test(TICKER).await; @@ -729,148 +726,150 @@ mod wasm_test { assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value - value2); } - #[wasm_bindgen_test] - async fn create_to_address_fails_on_unverified_notes() { - // init blocks_db - let ctx = mm_ctx_with_custom_db(); - let blockdb = BlockDbImpl::new(ctx, TICKER.to_string(), Some("")).await.unwrap(); - - // init walletdb. - let mut walletdb = wallet_db_from_zcoin_builder_for_test(TICKER).await; - let consensus_params = consensus_params(); - - // Add an account to the wallet - let extsk = ExtendedSpendingKey::master(&[]); - let extfvk = ExtendedFullViewingKey::from(&extsk); - assert!(walletdb.init_accounts_table(&[extfvk.clone()]).await.is_ok()); - - // Account balance should be zero - assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), Amount::zero()); - - // Add funds to the wallet in a single note - let value = Amount::from_u64(50000).unwrap(); - let (cb, _) = fake_compact_block(sapling_activation_height(), BlockHash([0; 32]), extfvk.clone(), value); - let cb_bytes = cb.write_to_bytes().unwrap(); - blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - - // Scan the cache - let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - assert!(blockdb - .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - .await - .is_ok()); - - // Verified balance matches total balance - let (_, anchor_height) = walletdb.get_target_and_anchor_heights().await.unwrap().unwrap(); - assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value); - assert_eq!( - walletdb.get_balance_at(AccountId(0), anchor_height).await.unwrap(), - value - ); - - // Add more funds to the wallet in a second note - let (cb, _) = fake_compact_block(sapling_activation_height() + 1, cb.hash(), extfvk.clone(), value); - let cb_bytes = cb.write_to_bytes().unwrap(); - blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - - // Scan the cache - let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - assert!(blockdb - .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - .await - .is_ok()); - - // Verified balance does not include the second note - let (_, anchor_height2) = walletdb.get_target_and_anchor_heights().await.unwrap().unwrap(); - assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value + value); - assert_eq!( - walletdb.get_balance_at(AccountId(0), anchor_height2).await.unwrap(), - value - ); - - // Spend fails because there are insufficient verified notes - let extsk2 = ExtendedSpendingKey::master(&[]); - let to = extsk2.default_address().unwrap().1.into(); - match create_spend_to_address( - &mut walletdb, - &network(), - test_prover(), - AccountId(0), - &extsk, - &to, - Amount::from_u64(70000).unwrap(), - None, - OvkPolicy::Sender, - ) - .await - { - Ok(_) => panic!("Should have failed"), - Err(e) => assert!(e - .to_string() - .contains("Insufficient balance (have 50000, need 71000 including fee)")), - } - - // Mine blocks SAPLING_ACTIVATION_HEIGHT + 2 to 9 until just before the second - // note is verified - for i in 2..10 { - let (cb, _) = fake_compact_block(sapling_activation_height() + i, cb.hash(), extfvk.clone(), value); - let cb_bytes = cb.write_to_bytes().unwrap(); - blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - } - - // Scan the cache - let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - assert!(blockdb - .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - .await - .is_ok()); - - // Second spend still fails - match create_spend_to_address( - &mut walletdb, - &network(), - test_prover(), - AccountId(0), - &extsk, - &to, - Amount::from_u64(70000).unwrap(), - None, - OvkPolicy::Sender, - ) - .await - { - Ok(_) => panic!("Should have failed"), - Err(e) => assert!(e - .to_string() - .contains("Insufficient balance (have 50000, need 71000 including fee)")), - } + fn network() -> Network { Network::TestNetwork } - // Mine block 11 so that the second note becomes verified - let (cb, _) = fake_compact_block(sapling_activation_height() + 10, cb.hash(), extfvk, value); - let cb_bytes = cb.write_to_bytes().unwrap(); - blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - // Scan the cache - let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - assert!(blockdb - .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - .await - .is_ok()); - - // Second spend should now succeed - create_spend_to_address( - &mut walletdb, - &network(), - test_prover(), - AccountId(0), - &extsk, - &to, - Amount::from_u64(70000).unwrap(), - None, - OvkPolicy::Sender, - ) - .await - .unwrap(); - } + // #[wasm_bindgen_test] + // async fn create_to_address_fails_on_unverified_notes() { + // // init blocks_db + // let ctx = mm_ctx_with_custom_db(); + // let blockdb = BlockDbImpl::new(ctx, TICKER.to_string(), Some("")).await.unwrap(); + // + // // init walletdb. + // let mut walletdb = wallet_db_from_zcoin_builder_for_test(TICKER).await; + // let consensus_params = consensus_params(); + // + // // Add an account to the wallet + // let extsk = ExtendedSpendingKey::master(&[]); + // let extfvk = ExtendedFullViewingKey::from(&extsk); + // assert!(walletdb.init_accounts_table(&[extfvk.clone()]).await.is_ok()); + // + // // Account balance should be zero + // assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), Amount::zero()); + // + // // Add funds to the wallet in a single note + // let value = Amount::from_u64(50000).unwrap(); + // let (cb, _) = fake_compact_block(sapling_activation_height(), BlockHash([0; 32]), extfvk.clone(), value); + // let cb_bytes = cb.write_to_bytes().unwrap(); + // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + // + // // Scan the cache + // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + // assert!(blockdb + // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + // .await + // .is_ok()); + // + // // Verified balance matches total balance + // let (_, anchor_height) = walletdb.get_target_and_anchor_heights().await.unwrap().unwrap(); + // assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value); + // assert_eq!( + // walletdb.get_balance_at(AccountId(0), anchor_height).await.unwrap(), + // value + // ); + // + // // Add more funds to the wallet in a second note + // let (cb, _) = fake_compact_block(sapling_activation_height() + 1, cb.hash(), extfvk.clone(), value); + // let cb_bytes = cb.write_to_bytes().unwrap(); + // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + // + // // Scan the cache + // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + // assert!(blockdb + // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + // .await + // .is_ok()); + // + // // Verified balance does not include the second note + // let (_, anchor_height2) = walletdb.get_target_and_anchor_heights().await.unwrap().unwrap(); + // assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value + value); + // assert_eq!( + // walletdb.get_balance_at(AccountId(0), anchor_height2).await.unwrap(), + // value + // ); + // + // // Spend fails because there are insufficient verified notes + // let extsk2 = ExtendedSpendingKey::master(&[]); + // let to = extsk2.default_address().unwrap().1.into(); + // match create_spend_to_address( + // &mut walletdb, + // &network(), + // test_prover(), + // AccountId(0), + // &extsk, + // &to, + // Amount::from_u64(70000).unwrap(), + // None, + // OvkPolicy::Sender, + // ) + // .await + // { + // Ok(_) => panic!("Should have failed"), + // Err(e) => assert!(e + // .to_string() + // .contains("Insufficient balance (have 50000, need 71000 including fee)")), + // } + // + // // Mine blocks SAPLING_ACTIVATION_HEIGHT + 2 to 9 until just before the second + // // note is verified + // for i in 2..10 { + // let (cb, _) = fake_compact_block(sapling_activation_height() + i, cb.hash(), extfvk.clone(), value); + // let cb_bytes = cb.write_to_bytes().unwrap(); + // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + // } + // + // // Scan the cache + // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + // assert!(blockdb + // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + // .await + // .is_ok()); + // + // // Second spend still fails + // match create_spend_to_address( + // &mut walletdb, + // &network(), + // test_prover(), + // AccountId(0), + // &extsk, + // &to, + // Amount::from_u64(70000).unwrap(), + // None, + // OvkPolicy::Sender, + // ) + // .await + // { + // Ok(_) => panic!("Should have failed"), + // Err(e) => assert!(e + // .to_string() + // .contains("Insufficient balance (have 50000, need 71000 including fee)")), + // } + // + // // Mine block 11 so that the second note becomes verified + // let (cb, _) = fake_compact_block(sapling_activation_height() + 10, cb.hash(), extfvk, value); + // let cb_bytes = cb.write_to_bytes().unwrap(); + // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + // // Scan the cache + // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + // assert!(blockdb + // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + // .await + // .is_ok()); + // + // // Second spend should now succeed + // create_spend_to_address( + // &mut walletdb, + // &network(), + // test_prover(), + // AccountId(0), + // &extsk, + // &to, + // Amount::from_u64(70000).unwrap(), + // None, + // OvkPolicy::Sender, + // ) + // .await + // .unwrap(); + // } #[wasm_bindgen_test] async fn test_create_to_address_fails_on_incorrect_extsk() { @@ -991,142 +990,142 @@ mod wasm_test { } } - #[wasm_bindgen_test] - async fn test_create_to_address_fails_on_locked_notes() { - register_wasm_log(); - - // init blocks_db - let ctx = mm_ctx_with_custom_db(); - let blockdb = BlockDbImpl::new(ctx, TICKER.to_string(), Some("")).await.unwrap(); - - // init walletdb. - let mut walletdb = wallet_db_from_zcoin_builder_for_test(TICKER).await; - let consensus_params = consensus_params(); - - // Add an account to the wallet - let extsk = ExtendedSpendingKey::master(&[]); - let extfvk = ExtendedFullViewingKey::from(&extsk); - assert!(walletdb.init_accounts_table(&[extfvk.clone()]).await.is_ok()); - - // Add funds to the wallet in a single note - let value = Amount::from_u64(50000).unwrap(); - let (cb, _) = fake_compact_block(sapling_activation_height(), BlockHash([0; 32]), extfvk, value); - let cb_bytes = cb.write_to_bytes().unwrap(); - blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - - // Scan the cache - let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - blockdb - .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - .await - .unwrap(); - assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value); - - // Send some of the funds to another address - let extsk2 = ExtendedSpendingKey::master(&[]); - let to = extsk2.default_address().unwrap().1.into(); - create_spend_to_address( - &mut walletdb, - &network(), - test_prover(), - AccountId(0), - &extsk, - &to, - Amount::from_u64(15000).unwrap(), - None, - OvkPolicy::Sender, - ) - .await - .unwrap(); - - // A second spend fails because there are no usable notes - match create_spend_to_address( - &mut walletdb, - &network(), - test_prover(), - AccountId(0), - &extsk, - &to, - Amount::from_u64(2000).unwrap(), - None, - OvkPolicy::Sender, - ) - .await - { - Ok(_) => panic!("Should have failed"), - Err(e) => assert!(e - .to_string() - .contains("Insufficient balance (have 0, need 3000 including fee)")), - } - - // Mine blocks SAPLING_ACTIVATION_HEIGHT + 1 to 21 (that don't send us funds) - // until just before the first transaction expires - for i in 1..22 { - let (cb, _) = fake_compact_block( - sapling_activation_height() + i, - cb.hash(), - ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[i as u8])), - value, - ); - let cb_bytes = cb.write_to_bytes().unwrap(); - blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - } - // Scan the cache - let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - blockdb - .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - .await - .unwrap(); - - // Second spend still fails - match create_spend_to_address( - &mut walletdb, - &network(), - test_prover(), - AccountId(0), - &extsk, - &to, - Amount::from_u64(2000).unwrap(), - None, - OvkPolicy::Sender, - ) - .await - { - Ok(_) => panic!("Should have failed"), - Err(e) => assert!(e - .to_string() - .contains("Insufficient balance (have 0, need 3000 including fee)")), - } - - // Mine block SAPLING_ACTIVATION_HEIGHT + 22 so that the first transaction expires - let (cb, _) = fake_compact_block( - sapling_activation_height() + 22, - cb.hash(), - ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[22])), - value, - ); - let cb_bytes = cb.write_to_bytes().unwrap(); - blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); - // Scan the cache - let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); - blockdb - .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) - .await - .unwrap(); - - // Second spend should now succeed - create_spend_to_address( - &mut walletdb, - &network(), - test_prover(), - AccountId(0), - &extsk, - &to, - Amount::from_u64(2000).unwrap(), - None, - OvkPolicy::Sender, - ) - .await - .unwrap(); - } + // #[wasm_bindgen_test] + // async fn test_create_to_address_fails_on_locked_notes() { + // register_wasm_log(); + // + // // init blocks_db + // let ctx = mm_ctx_with_custom_db(); + // let blockdb = BlockDbImpl::new(ctx, TICKER.to_string(), Some("")).await.unwrap(); + // + // // init walletdb. + // let mut walletdb = wallet_db_from_zcoin_builder_for_test(TICKER).await; + // let consensus_params = consensus_params(); + // + // // Add an account to the wallet + // let extsk = ExtendedSpendingKey::master(&[]); + // let extfvk = ExtendedFullViewingKey::from(&extsk); + // assert!(walletdb.init_accounts_table(&[extfvk.clone()]).await.is_ok()); + // + // // Add funds to the wallet in a single note + // let value = Amount::from_u64(50000).unwrap(); + // let (cb, _) = fake_compact_block(sapling_activation_height(), BlockHash([0; 32]), extfvk, value); + // let cb_bytes = cb.write_to_bytes().unwrap(); + // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + // + // // Scan the cache + // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + // blockdb + // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + // .await + // .unwrap(); + // assert_eq!(walletdb.get_balance(AccountId(0)).await.unwrap(), value); + // + // // Send some of the funds to another address + // let extsk2 = ExtendedSpendingKey::master(&[]); + // let to = extsk2.default_address().unwrap().1.into(); + // create_spend_to_address( + // &mut walletdb, + // &network(), + // test_prover(), + // AccountId(0), + // &extsk, + // &to, + // Amount::from_u64(15000).unwrap(), + // None, + // OvkPolicy::Sender, + // ) + // .await + // .unwrap(); + // + // // A second spend fails because there are no usable notes + // match create_spend_to_address( + // &mut walletdb, + // &network(), + // test_prover(), + // AccountId(0), + // &extsk, + // &to, + // Amount::from_u64(2000).unwrap(), + // None, + // OvkPolicy::Sender, + // ) + // .await + // { + // Ok(_) => panic!("Should have failed"), + // Err(e) => assert!(e + // .to_string() + // .contains("Insufficient balance (have 0, need 3000 including fee)")), + // } + // + // // Mine blocks SAPLING_ACTIVATION_HEIGHT + 1 to 21 (that don't send us funds) + // // until just before the first transaction expires + // for i in 1..22 { + // let (cb, _) = fake_compact_block( + // sapling_activation_height() + i, + // cb.hash(), + // ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[i as u8])), + // value, + // ); + // let cb_bytes = cb.write_to_bytes().unwrap(); + // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + // } + // // Scan the cache + // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + // blockdb + // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + // .await + // .unwrap(); + // + // // Second spend still fails + // match create_spend_to_address( + // &mut walletdb, + // &network(), + // test_prover(), + // AccountId(0), + // &extsk, + // &to, + // Amount::from_u64(2000).unwrap(), + // None, + // OvkPolicy::Sender, + // ) + // .await + // { + // Ok(_) => panic!("Should have failed"), + // Err(e) => assert!(e + // .to_string() + // .contains("Insufficient balance (have 0, need 3000 including fee)")), + // } + // + // // Mine block SAPLING_ACTIVATION_HEIGHT + 22 so that the first transaction expires + // let (cb, _) = fake_compact_block( + // sapling_activation_height() + 22, + // cb.hash(), + // ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[22])), + // value, + // ); + // let cb_bytes = cb.write_to_bytes().unwrap(); + // blockdb.insert_block(cb.height as u32, cb_bytes).await.unwrap(); + // // Scan the cache + // let scan = DataConnStmtCacheWrapper::new(DataConnStmtCacheWasm(walletdb.clone())); + // blockdb + // .process_blocks_with_mode(consensus_params.clone(), BlockProcessingMode::Scan(scan), None, None) + // .await + // .unwrap(); + // + // // Second spend should now succeed + // create_spend_to_address( + // &mut walletdb, + // &network(), + // test_prover(), + // AccountId(0), + // &extsk, + // &to, + // Amount::from_u64(2000).unwrap(), + // None, + // OvkPolicy::Sender, + // ) + // .await + // .unwrap(); + // } } From 47af2c003cd30abf40b421dc28bf9ba581d08b24 Mon Sep 17 00:00:00 2001 From: borngraced Date: Mon, 30 Oct 2023 10:36:36 +0100 Subject: [PATCH 33/68] implement tonic client Signed-off-by: borngraced --- mm2src/coins/z_coin/z_rpc.rs | 2 +- mm2src/mm2_net/src/wasm/http.rs | 53 ++---------------------- mm2src/mm2_net/src/wasm/mod.rs | 1 + mm2src/mm2_net/src/wasm/tonic_client.rs | 54 +++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 51 deletions(-) create mode 100644 mm2src/mm2_net/src/wasm/tonic_client.rs diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index df290919b6..e7fe6818c0 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -53,7 +53,7 @@ cfg_native!( ); cfg_wasm32!( - use mm2_net::wasm::http::TonicClient; + use mm2_net::wasm::tonic_client::TonicClient; ); /// ZRpcOps trait provides asynchronous methods for performing various operations related to diff --git a/mm2src/mm2_net/src/wasm/http.rs b/mm2src/mm2_net/src/wasm/http.rs index 2e6f148bfb..73659ef3ff 100644 --- a/mm2src/mm2_net/src/wasm/http.rs +++ b/mm2src/mm2_net/src/wasm/http.rs @@ -1,23 +1,16 @@ -use crate::grpc_web::PostGrpcWebErr; use crate::transport::{SlurpError, SlurpResult}; use crate::wasm::body_stream::ResponseBody; use common::executor::spawn_local; -use common::{stringify_js_error, APPLICATION_GRPC_WEB_PROTO, APPLICATION_JSON, X_GRPC_WEB}; +use common::{stringify_js_error, APPLICATION_JSON}; use futures::channel::oneshot; -use futures_util::Future; -use http::header::{ACCEPT, CONTENT_TYPE}; +use http::header::CONTENT_TYPE; use http::response::Builder; -use http::{HeaderMap, Request, Response, StatusCode}; +use http::{HeaderMap, Response, StatusCode}; use js_sys::Array; use js_sys::Uint8Array; use mm2_err_handle::prelude::*; use std::collections::HashMap; -use std::{pin::Pin, - task::{Context, Poll}}; -use tonic::body::BoxBody; -use tonic::codegen::Body; -use tower_service::Service; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use wasm_bindgen_futures::JsFuture; @@ -380,46 +373,6 @@ impl RequestBody { } } -#[derive(Clone)] -pub struct TonicClient(String); - -impl TonicClient { - pub fn new(url: String) -> Self { Self(url) } -} - -impl Service> for TonicClient { - type Response = Response; - - type Error = MmError; - - type Future = Pin> + Send + 'static>>; - - fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } - - fn call(&mut self, request: Request) -> Self::Future { Box::pin(call(self.0.clone(), request)) } -} - -async fn call(mut base_url: String, request: Request) -> MmResult, PostGrpcWebErr> { - base_url.push_str(&request.uri().to_string()); - - let body = request - .into_body() - .data() - .await - .transpose() - .map_err(|err| PostGrpcWebErr::Status(err.to_string()))?; - let body = body.ok_or_else(|| MmError::new(PostGrpcWebErr::InvalidRequest("Invalid request body".to_string())))?; - - Ok(FetchRequest::post(&base_url) - .body_bytes(body.to_vec()) - .header(CONTENT_TYPE.as_str(), APPLICATION_GRPC_WEB_PROTO) - .header(ACCEPT.as_str(), APPLICATION_GRPC_WEB_PROTO) - .header(X_GRPC_WEB, "1") - .request_stream_response() - .await? - .1) -} - mod tests { use super::*; use wasm_bindgen_test::*; diff --git a/mm2src/mm2_net/src/wasm/mod.rs b/mm2src/mm2_net/src/wasm/mod.rs index 7ac6d5aff0..a2c4efa3ed 100644 --- a/mm2src/mm2_net/src/wasm/mod.rs +++ b/mm2src/mm2_net/src/wasm/mod.rs @@ -1,3 +1,4 @@ pub mod body_stream; pub mod http; +pub mod tonic_client; pub mod wasm_ws; diff --git a/mm2src/mm2_net/src/wasm/tonic_client.rs b/mm2src/mm2_net/src/wasm/tonic_client.rs new file mode 100644 index 0000000000..a42ad675b8 --- /dev/null +++ b/mm2src/mm2_net/src/wasm/tonic_client.rs @@ -0,0 +1,54 @@ +use crate::grpc_web::PostGrpcWebErr; +use crate::wasm::body_stream::ResponseBody; +use crate::wasm::http::FetchRequest; + +use common::{APPLICATION_GRPC_WEB_PROTO, X_GRPC_WEB}; +use futures_util::Future; +use http::header::{ACCEPT, CONTENT_TYPE}; +use http::{Request, Response}; +use mm2_err_handle::prelude::{MmError, MmResult}; +use std::pin::Pin; +use std::task::{Context, Poll}; +use tonic::body::BoxBody; +use tonic::codegen::Body; +use tower_service::Service; + +#[derive(Clone)] +pub struct TonicClient(String); + +impl TonicClient { + pub fn new(url: String) -> Self { Self(url) } +} + +impl Service> for TonicClient { + type Response = Response; + + type Error = MmError; + + type Future = Pin> + Send + 'static>>; + + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } + + fn call(&mut self, request: Request) -> Self::Future { Box::pin(call(self.0.clone(), request)) } +} + +async fn call(mut base_url: String, request: Request) -> MmResult, PostGrpcWebErr> { + base_url.push_str(&request.uri().to_string()); + + let body = request + .into_body() + .data() + .await + .transpose() + .map_err(|err| PostGrpcWebErr::Status(err.to_string()))?; + let body = body.ok_or_else(|| MmError::new(PostGrpcWebErr::InvalidRequest("Invalid request body".to_string())))?; + + Ok(FetchRequest::post(&base_url) + .body_bytes(body.to_vec()) + .header(CONTENT_TYPE.as_str(), APPLICATION_GRPC_WEB_PROTO) + .header(ACCEPT.as_str(), APPLICATION_GRPC_WEB_PROTO) + .header(X_GRPC_WEB, "1") + .request_stream_response() + .await? + .1) +} From f530d757714b931c942241eda013c03273d20b08 Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 1 Nov 2023 11:14:47 +0100 Subject: [PATCH 34/68] use LocalTxProver::from_bytes directly for creating LocalTxProver Signed-off-by: borngraced --- .../coins/z_coin/storage/walletdb/wasm/mod.rs | 9 +------ mm2src/mm2_net/src/wasm/http.rs | 24 ++++++++++--------- mm2src/mm2_net/src/wasm/tonic_client.rs | 7 +++--- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/mm2src/coins/z_coin/storage/walletdb/wasm/mod.rs b/mm2src/coins/z_coin/storage/walletdb/wasm/mod.rs index de94d4c791..8c57283590 100644 --- a/mm2src/coins/z_coin/storage/walletdb/wasm/mod.rs +++ b/mm2src/coins/z_coin/storage/walletdb/wasm/mod.rs @@ -13,7 +13,6 @@ use zcash_primitives::merkle_tree::IncrementalWitness; use zcash_primitives::sapling::Diversifier; use zcash_primitives::sapling::Rseed; use zcash_primitives::transaction::components::Amount; -use zcash_proofs::parse_parameters; use zcash_proofs::prover::LocalTxProver; struct SpendableNoteConstructor { @@ -25,13 +24,7 @@ struct SpendableNoteConstructor { fn test_prover() -> LocalTxProver { let (spend_buf, output_buf) = wagyu_zcash_parameters::load_sapling_parameters(); - let p = parse_parameters(&spend_buf[..], &output_buf[..], None); - - LocalTxProver { - spend_params: p.spend_params, - spend_vk: p.spend_vk, - output_params: p.output_params, - } + LocalTxProver::from_bytes(&spend_buf[..], &output_buf[..]) } fn to_spendable_note(note: SpendableNoteConstructor) -> MmResult { diff --git a/mm2src/mm2_net/src/wasm/http.rs b/mm2src/mm2_net/src/wasm/http.rs index 73659ef3ff..d4fcd562d1 100644 --- a/mm2src/mm2_net/src/wasm/http.rs +++ b/mm2src/mm2_net/src/wasm/http.rs @@ -57,7 +57,7 @@ pub async fn slurp_post_json(url: &str, body: String) -> SlurpResult { fn set_response_headers_and_content_type( mut result: Builder, response: &JsResponse, -) -> Result<(Builder, Option), MmError> { +) -> Result<(Builder, String), MmError> { let headers = response.headers(); let header_iter = @@ -86,7 +86,11 @@ fn set_response_headers_and_content_type( } } - Ok((result, content_type)) + if let None = content_type { + return MmError::err(SlurpError::InvalidRequest("MissingContentType".to_string())); + } + + Ok((result, content_type.unwrap())) } pub struct FetchRequest { @@ -165,13 +169,11 @@ impl FetchRequest { } } - pub async fn request_stream_response(self) -> FetchResult> { + pub async fn request_response_body(self) -> FetchResult> { let (tx, rx) = oneshot::channel(); Self::spawn_fetch_stream_response(self, tx); - match rx.await { - Ok(res) => res, - Err(_e) => MmError::err(SlurpError::Internal("Spawned future has been canceled".to_owned())), - } + rx.await + .map_to_mm(|_| SlurpError::Internal("Spawned future has been canceled".to_owned()))? } fn spawn_fetch_str(request: Self, tx: oneshot::Sender>) { @@ -321,15 +323,15 @@ impl FetchRequest { let resp_stream = match js_response.body() { Some(txt) => txt, None => { - let error = format!("Expected readable stream, found {:?}:", js_response,); - return MmError::err(SlurpError::ErrorDeserializing { uri, error }); + return MmError::err(SlurpError::ErrorDeserializing { + uri, + error: format!("Expected readable stream, found {:?}:", js_response), + }); }, }; let builder = Response::builder().status(status_code); let (builder, content_type) = set_response_headers_and_content_type(builder, &js_response)?; - let content_type = - content_type.ok_or_else(|| MmError::new(SlurpError::InvalidRequest("MissingContentType".to_string())))?; let body = ResponseBody::new(resp_stream, &content_type) .map_to_mm(|err| SlurpError::InvalidRequest(format!("{err:?}")))?; diff --git a/mm2src/mm2_net/src/wasm/tonic_client.rs b/mm2src/mm2_net/src/wasm/tonic_client.rs index a42ad675b8..70ff18c9df 100644 --- a/mm2src/mm2_net/src/wasm/tonic_client.rs +++ b/mm2src/mm2_net/src/wasm/tonic_client.rs @@ -32,9 +32,8 @@ impl Service> for TonicClient { fn call(&mut self, request: Request) -> Self::Future { Box::pin(call(self.0.clone(), request)) } } -async fn call(mut base_url: String, request: Request) -> MmResult, PostGrpcWebErr> { - base_url.push_str(&request.uri().to_string()); - +async fn call(base_url: String, request: Request) -> MmResult, PostGrpcWebErr> { + let base_url = format!("{base_url}{}", &request.uri().to_string()); let body = request .into_body() .data() @@ -48,7 +47,7 @@ async fn call(mut base_url: String, request: Request) -> MmResult Date: Thu, 2 Nov 2023 10:19:48 +0100 Subject: [PATCH 35/68] fix review notes Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 10 +-------- mm2src/coins/z_coin/z_rpc.rs | 9 +++++--- mm2src/mm2_main/src/lib.rs | 2 +- mm2src/mm2_net/src/grpc_web.rs | 24 ++++++-------------- mm2src/mm2_net/src/wasm/body_stream.rs | 30 +++++++++++++++++++++++-- mm2src/mm2_net/src/wasm/http.rs | 2 +- mm2src/mm2_net/src/wasm/tonic_client.rs | 2 +- 7 files changed, 45 insertions(+), 34 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 3d2a962297..8f8b87aba6 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -76,8 +76,6 @@ use zcash_primitives::zip32::ChildIndex as Zip32Child; use zcash_primitives::{constants::mainnet as z_mainnet_constants, sapling::PaymentAddress, zip32::ExtendedFullViewingKey, zip32::ExtendedSpendingKey}; -#[cfg(target_arch = "wasm32")] -use zcash_proofs::parse_parameters; use zcash_proofs::prover::LocalTxProver; mod z_htlc; @@ -1038,13 +1036,7 @@ impl<'a> ZCoinBuilder<'a> { // TODO: Implement TxProver for WASM using indexed db after merging transport layer PR. async fn z_tx_prover(&self) -> Result> { let (spend_buf, output_buf) = wagyu_zcash_parameters::load_sapling_parameters(); - let p = parse_parameters(&spend_buf[..], &output_buf[..], None); - - Ok(LocalTxProver { - spend_params: p.spend_params, - spend_vk: p.spend_vk, - output_params: p.output_params, - }) + Ok(LocalTxProver::from_bytes(&spend_buf[..], &output_buf[..])) } } diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index e7fe6818c0..c4c86287be 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -89,6 +89,7 @@ pub trait ZRpcOps { async fn checkpoint_block_from_height( &mut self, height: u64, + ticker: &str, ) -> MmResult, UpdateBlocksCacheErr>; } @@ -284,8 +285,8 @@ impl ZRpcOps for LightRpcClient { async fn checkpoint_block_from_height( &mut self, height: u64, + ticker: &str, ) -> MmResult, UpdateBlocksCacheErr> { - info!("SYNC STARTING HEIGHT: {height}"); let tree_state = self.get_tree_state(height).await?; let hash = H256Json::from_str(&tree_state.hash) .map_err(|err| UpdateBlocksCacheErr::DecodeError(err.to_string()))? @@ -295,6 +296,7 @@ impl ZRpcOps for LightRpcClient { .map_err(|err: FromHexError| UpdateBlocksCacheErr::DecodeError(err.to_string()))?, ); + info!("Final Derived Sync Height for {ticker} is: {height}"); Ok(Some(CheckPointBlockInfo { height: tree_state.height as u32, hash, @@ -454,7 +456,7 @@ pub(super) async fn init_light_client<'a>( .unwrap_or(sapling_activation_height), }; let maybe_checkpoint_block = light_rpc_clients - .checkpoint_block_from_height(sync_height.max(sapling_activation_height)) + .checkpoint_block_from_height(sync_height.max(sapling_activation_height), &coin) .await?; let min_height = blocks_db.get_earliest_block().await?; // check if no sync_params was provided and continue syncing from last height in db if it's > 0. @@ -746,7 +748,7 @@ impl SaplingSyncLoopHandle { let wallet_ops_guard = wallet_db.get_update_ops().expect("get_update_ops always returns Ok"); let scan = DataConnStmtCacheWrapper::new(wallet_ops_guard); - info!("START SCANNING WALLETDB"); + info!("Scanning/Processing blocks to be saved to walletdb storage"); blocks_db .process_blocks_with_mode( self.consensus_params.clone(), @@ -760,6 +762,7 @@ impl SaplingSyncLoopHandle { Timer::sleep_ms(self.scan_interval_ms).await; } } + Ok(()) } diff --git a/mm2src/mm2_main/src/lib.rs b/mm2src/mm2_main/src/lib.rs index 14759d0b99..23c7b65312 100644 --- a/mm2src/mm2_main/src/lib.rs +++ b/mm2src/mm2_main/src/lib.rs @@ -17,4 +17,4 @@ pub mod mm2; -#[cfg(all(target_arch = "wasm32", test))] pub mod wasm_tests; +#[cfg(all(target_arch = "wasm32", test))] mod wasm_tests; diff --git a/mm2src/mm2_net/src/grpc_web.rs b/mm2src/mm2_net/src/grpc_web.rs index aa79febc2c..c91dc1bb45 100644 --- a/mm2src/mm2_net/src/grpc_web.rs +++ b/mm2src/mm2_net/src/grpc_web.rs @@ -4,10 +4,10 @@ use crate::transport::SlurpError; use bytes::{Buf, BufMut, Bytes, BytesMut}; use common::{cfg_native, cfg_wasm32}; +use derive_more::Display; use http::header::{ACCEPT, CONTENT_TYPE}; use mm2_err_handle::prelude::*; use prost::DecodeError; -use std::fmt::{Display, Formatter}; cfg_native! { use common::APPLICATION_GRPC_WEB; @@ -93,7 +93,7 @@ where Ok(msg) } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, thiserror::Error, Display)] pub enum PostGrpcWebErr { DecodeBody(String), EncodeBody(String), @@ -101,21 +101,11 @@ pub enum PostGrpcWebErr { Internal(String), PayloadTooShort(String), Status(String), - Transport { uri: String, error: String }, -} - -impl Display for PostGrpcWebErr { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match self { - PostGrpcWebErr::DecodeBody(msg) => write!(f, "DecodeBody: {msg}"), - PostGrpcWebErr::EncodeBody(msg) => write!(f, "EncodeBody: {msg}"), - PostGrpcWebErr::InvalidRequest(msg) => write!(f, "InvalidRequest: {msg}"), - PostGrpcWebErr::Internal(msg) => write!(f, "Internal: {msg}"), - PostGrpcWebErr::PayloadTooShort(msg) => write!(f, "PayloadTooShort: {msg}"), - PostGrpcWebErr::Status(error) => write!(f, "Status: {error:?}"), - PostGrpcWebErr::Transport { uri, error } => write!(f, "Transport: URI: {uri}, Error: {error}"), - } - } + #[display(fmt = "Transport Error — uri: {uri} — error: {error}")] + Transport { + uri: String, + error: String, + }, } impl From for PostGrpcWebErr { diff --git a/mm2src/mm2_net/src/wasm/body_stream.rs b/mm2src/mm2_net/src/wasm/body_stream.rs index b1ae0e3c63..70ef60d023 100644 --- a/mm2src/mm2_net/src/wasm/body_stream.rs +++ b/mm2src/mm2_net/src/wasm/body_stream.rs @@ -1,3 +1,19 @@ +/// This module handles HTTP response decoding and trailer extraction for gRPC-Web communication/streaming. +/// # gRPC-Web Response Body Handling Module +/// +/// gRPC-Web is a protocol that enables web applications to communicate with gRPC services over HTTP/1.1. It is +/// particularly useful for browsers and other environments that do not support HTTP/2. This module provides +/// essential functionality to process and decode gRPC-Web responses in MM2 also support streaming. +/// +/// ## Key Components +/// +/// - **EncodedBytes**: This struct represents a buffer for encoded bytes. It manages the decoding of base64-encoded data and is used to handle response data and trailers based on the content type. The `new` method initializes an instance based on the content type. Other methods are available for handling encoding and decoding of data. +/// +/// - **ReadState**: An enumeration that represents the different states in which the response can be read. It keeps track of the progress of response processing, indicating whether data reading is complete or trailers have been encountered. +/// +/// - **ResponseBody**: This struct is the core of response handling. It is designed to work with gRPC-Web responses. It reads response data from a ReadableStream, decodes and processes the response, and extracts trailers if present. The `new` method initializes an instance of ResponseBody based on the ReadableStream and content type. It implements the `Body` trait to provide a standardized interface for reading response data and trailers. +/// +/// - **BodyStream**: A struct that represents a stream of bytes for the response body. It is used internally by ResponseBody to read the response data from a web stream. The `new` method creates a new instance based on an `IntoStream`, and the `empty` method creates an empty stream. This struct also implements the `Body` trait, providing methods to read data from the stream and return trailers. use crate::grpc_web::PostGrpcWebErr; use base64::prelude::BASE64_STANDARD; @@ -20,9 +36,10 @@ use wasm_bindgen::JsCast; use wasm_streams::readable::IntoStream; use web_sys::ReadableStream; -/// If 8th MSB of a frame is `0` for data and `1` for trailer +/// If the 8th most significant bit of a frame is `0`, it indicates data; if `1`, it indicates a trailer. const TRAILER_BIT: u8 = 0b10000000; +/// Manages a buffer for storing response data and provides methods for appending and decoding data based on the content type. pub struct EncodedBytes { is_base64: bool, raw_buf: BytesMut, @@ -30,6 +47,7 @@ pub struct EncodedBytes { } impl EncodedBytes { + /// Creates a new `EncodedBytes` instance based on the content type. pub fn new(content_type: &str) -> Result { let is_base64 = match content_type { APPLICATION_GRPC_WEB_TEXT | APPLICATION_GRPC_WEB_TEXT_PROTO => true, @@ -90,6 +108,7 @@ impl DerefMut for EncodedBytes { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.buf } } +/// Represents the state of reading the response body, including compression flags, data lengths, trailers, and the done state. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ReadState { CompressionFlag, @@ -110,7 +129,7 @@ impl ReadState { } } -/// Type to handle HTTP response +/// Handles the HTTP response body, decoding data, and extracting trailers #[pin_project] pub struct ResponseBody { #[pin] @@ -124,6 +143,7 @@ pub struct ResponseBody { } impl ResponseBody { + /// Creates a new `ResponseBody` based on a ReadableStream and content type. pub(crate) fn new(body_stream: ReadableStream, content_type: &str) -> Result { let body_stream = wasm_streams::ReadableStream::from_raw(body_stream.unchecked_into()).into_stream(); @@ -350,11 +370,13 @@ impl Default for ResponseBody { } } +/// Represents a stream of bytes for the response body. pub struct BodyStream { body_stream: Pin>>>, } impl BodyStream { + /// Creates a new `BodyStream` based on an IntoStream. pub fn new(body_stream: IntoStream<'static>) -> Self { let body_stream = body_stream .map_ok(|js_value| { @@ -372,6 +394,7 @@ impl BodyStream { } } + /// Creates an empty `BodyStream`. pub fn empty() -> Self { let body_stream = empty(); @@ -381,6 +404,7 @@ impl BodyStream { } } +// Implementations of the Body trait for ResponseBody and BodyStream. impl Body for BodyStream { type Data = Bytes; @@ -395,5 +419,7 @@ impl Body for BodyStream { } } +// Additional safety traits for BodyStream. unsafe impl Send for BodyStream {} +// Additional safety traits for BodyStream. unsafe impl Sync for BodyStream {} diff --git a/mm2src/mm2_net/src/wasm/http.rs b/mm2src/mm2_net/src/wasm/http.rs index d4fcd562d1..c1c8581931 100644 --- a/mm2src/mm2_net/src/wasm/http.rs +++ b/mm2src/mm2_net/src/wasm/http.rs @@ -169,7 +169,7 @@ impl FetchRequest { } } - pub async fn request_response_body(self) -> FetchResult> { + pub async fn fetch_stream_response(self) -> FetchResult> { let (tx, rx) = oneshot::channel(); Self::spawn_fetch_stream_response(self, tx); rx.await diff --git a/mm2src/mm2_net/src/wasm/tonic_client.rs b/mm2src/mm2_net/src/wasm/tonic_client.rs index 70ff18c9df..84df389e73 100644 --- a/mm2src/mm2_net/src/wasm/tonic_client.rs +++ b/mm2src/mm2_net/src/wasm/tonic_client.rs @@ -47,7 +47,7 @@ async fn call(base_url: String, request: Request) -> MmResult Date: Thu, 2 Nov 2023 12:07:39 +0100 Subject: [PATCH 36/68] update native checkpoint_block_from_height args Signed-off-by: borngraced --- mm2src/coins/z_coin/z_rpc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index c4c86287be..f72b3ce84e 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -420,6 +420,7 @@ impl ZRpcOps for NativeClient { async fn checkpoint_block_from_height( &mut self, _height: u64, + _ticker: &str, ) -> MmResult, UpdateBlocksCacheErr> { todo!() } From 2e09e62bd984f43baecb295d872674b26d8b40e6 Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 2 Nov 2023 12:14:24 +0100 Subject: [PATCH 37/68] use correct const var naming for pirate tests Signed-off-by: borngraced --- mm2src/mm2_main/src/wasm_tests.rs | 10 +++++----- mm2src/mm2_test_helpers/src/for_tests.rs | 7 +++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index 7ed0cf1c65..e84b2bab5b 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -11,8 +11,8 @@ use mm2_test_helpers::electrums::{doc_electrums, marty_electrums}; use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init_z_coin_light, init_z_coin_status, morty_conf, pirate_conf, rick_conf, start_swaps, test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, MarketMakerIt, Mm2InitPrivKeyPolicy, - Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, RICK, ZOMBIE_ELECTRUMS, - ZOMBIE_LIGHTWALLETD_URLS}; + Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, PIRATE_LIGHTWALLETD_URLS, RICK, + ZOMBIE_ELECTRUMS}; use mm2_test_helpers::get_passphrase; use mm2_test_helpers::structs::{EnableCoinBalance, InitTaskResult, InitZcoinStatus, RpcV2Response, ZCoinActivationResult}; @@ -20,7 +20,7 @@ use serde_json::json; use serde_json::{self as json}; use wasm_bindgen_test::wasm_bindgen_test; -const ZOMBIE_TEST_BALANCE_SEED: &str = "zombie test seed"; +const PIRATE_TEST_BALANCE_SEED: &str = "pirate test seed"; /// Starts the WASM version of MM. fn wasm_start(ctx: MmArc) { @@ -226,12 +226,12 @@ async fn activate_z_coin_light() { register_wasm_log(); let coins = json!([pirate_conf()]); - let conf = Mm2TestConf::seednode(ZOMBIE_TEST_BALANCE_SEED, &coins); + let conf = Mm2TestConf::seednode(PIRATE_TEST_BALANCE_SEED, &coins); let mm = MarketMakerIt::start_async(conf.conf, conf.rpc_password, Some(wasm_start)) .await .unwrap(); - let activation_result = enable_z_coin_light(&mm, ARRR, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None).await; + let activation_result = enable_z_coin_light(&mm, ARRR, ZOMBIE_ELECTRUMS, PIRATE_LIGHTWALLETD_URLS, None).await; let balance = match activation_result.wallet_balance { EnableCoinBalance::Iguana(iguana) => iguana, diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index 63f9cfcc38..90995511fa 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -167,8 +167,6 @@ pub const ZOMBIE_ELECTRUMS: &[&str] = &[ ]; #[cfg(target_arch = "wasm32")] pub const ZOMBIE_ELECTRUMS: &[&str] = &["zombie.dragonhound.info:30059"]; - -#[cfg(not(target_arch = "wasm32"))] pub const ZOMBIE_LIGHTWALLETD_URLS: &[&str] = &[ "https://lightd1.pirate.black:443", "https://piratelightd1.cryptoforge.cc:443", @@ -176,10 +174,11 @@ pub const ZOMBIE_LIGHTWALLETD_URLS: &[&str] = &[ "https://piratelightd3.cryptoforge.cc:443", "https://piratelightd4.cryptoforge.cc:443", ]; -#[cfg(target_arch = "wasm32")] -pub const ZOMBIE_LIGHTWALLETD_URLS: &[&str] = &["http://pirate.spyglass.quest:8081"]; pub const PIRATE_ELECTRUMS: &[&str] = &["node1.chainkeeper.pro:10132"]; +#[cfg(not(target_arch = "wasm32"))] pub const PIRATE_LIGHTWALLETD_URLS: &[&str] = &["http://node1.chainkeeper.pro:443"]; +#[cfg(target_arch = "wasm32")] +pub const PIRATE_LIGHTWALLETD_URLS: &[&str] = &["http://pirate.spyglass.quest:8081"]; pub const DEFAULT_RPC_PASSWORD: &str = "pass"; pub const QRC20_ELECTRUMS: &[&str] = &[ "electrum1.cipig.net:10071", From 4b2b3b8d08a7cfe82726ab9236b1a03d97179289 Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 2 Nov 2023 13:48:34 +0100 Subject: [PATCH 38/68] fix review notes Signed-off-by: borngraced --- mm2src/coins/z_coin/compact_formats.proto | 1 + mm2src/coins/z_coin/service.proto | 1 + .../storage/blockdb/blockdb_idb_storage.rs | 38 +------------------ mm2src/coins/z_coin/z_rpc.rs | 1 - 4 files changed, 4 insertions(+), 37 deletions(-) diff --git a/mm2src/coins/z_coin/compact_formats.proto b/mm2src/coins/z_coin/compact_formats.proto index e20c05a56b..d0e1d7a410 100644 --- a/mm2src/coins/z_coin/compact_formats.proto +++ b/mm2src/coins/z_coin/compact_formats.proto @@ -1,4 +1,5 @@ syntax = "proto3"; +// TODO: use pirate.wallet.sdk.rpc for package name. package cash.z.wallet.sdk.rpc; option go_package = "walletrpc"; option swift_prefix = ""; diff --git a/mm2src/coins/z_coin/service.proto b/mm2src/coins/z_coin/service.proto index d0a7085675..300b213639 100644 --- a/mm2src/coins/z_coin/service.proto +++ b/mm2src/coins/z_coin/service.proto @@ -3,6 +3,7 @@ // file COPYING or https://www.opensource.org/licenses/mit-license.php . syntax = "proto3"; +// TODO: use pirate.wallet.sdk.rpc for package name. package cash.z.wallet.sdk.rpc; option go_package = ".;walletrpc"; option swift_prefix = ""; diff --git a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs index 89c35aee36..153b559e9e 100644 --- a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs +++ b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs @@ -182,7 +182,7 @@ impl BlockDbImpl { let mut blocks_to_scan = vec![]; while let Some((_, block)) = maybe_blocks.next().await? { if let Some(limit) = limit { - if block.height > limit { + if blocks_to_scan.len() > limit { break; } }; @@ -216,45 +216,11 @@ impl BlockDbImpl { .unwrap_or(BlockHeight::from_u32(params.sapling_activation_height) - 1) })?, }; - - let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let block_db = db_transaction.table::().await?; - - // Fetch CompactBlocks block_db are needed for scanning. - let min = u32::from(from_height + 1); - let mut maybe_blocks = block_db - .cursor_builder() - .only("ticker", &self.ticker)? - .bound("height", min, u32::MAX) - .open_cursor(BlockDbTable::TICKER_HEIGHT_INDEX) - .await?; - - let mut blocks_to_scan = vec![]; - while let Some((_, block)) = maybe_blocks.next().await? { - if let Some(limit) = limit { - if blocks_to_scan.len() > limit as usize { - break; - } - }; - - blocks_to_scan.push(CompactBlockRow { - height: block.height.into(), - data: block.data, - }); - } - let mut prev_height = from_height; let mut prev_hash: Option = validate_from.map(|(_, hash)| hash); - let blocks_len = blocks_to_scan.len(); + let blocks_to_scan = self.query_blocks_by_limit(from_height, limit).await?; for block in blocks_to_scan { - if let Some(limit) = limit { - if blocks_len > limit as usize { - break; - } - } - let cbr = block; let block = CompactBlock::parse_from_bytes(&cbr.data) .map_to_mm(|err| ZcoinStorageError::DecodingError(err.to_string()))?; diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index f72b3ce84e..2acefb95a1 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -749,7 +749,6 @@ impl SaplingSyncLoopHandle { let wallet_ops_guard = wallet_db.get_update_ops().expect("get_update_ops always returns Ok"); let scan = DataConnStmtCacheWrapper::new(wallet_ops_guard); - info!("Scanning/Processing blocks to be saved to walletdb storage"); blocks_db .process_blocks_with_mode( self.consensus_params.clone(), From d7702243aa988fae14c2798f35a3efd1dc78101c Mon Sep 17 00:00:00 2001 From: borngraced Date: Fri, 3 Nov 2023 05:32:19 +0100 Subject: [PATCH 39/68] fix wasm clippy warning Signed-off-by: borngraced --- mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs | 2 +- mm2src/mm2_net/src/wasm/http.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs index 153b559e9e..f5dbb80bdd 100644 --- a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs +++ b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs @@ -182,7 +182,7 @@ impl BlockDbImpl { let mut blocks_to_scan = vec![]; while let Some((_, block)) = maybe_blocks.next().await? { if let Some(limit) = limit { - if blocks_to_scan.len() > limit { + if blocks_to_scan.len() > limit as usize { break; } }; diff --git a/mm2src/mm2_net/src/wasm/http.rs b/mm2src/mm2_net/src/wasm/http.rs index c1c8581931..d9d51dd314 100644 --- a/mm2src/mm2_net/src/wasm/http.rs +++ b/mm2src/mm2_net/src/wasm/http.rs @@ -86,7 +86,7 @@ fn set_response_headers_and_content_type( } } - if let None = content_type { + if content_type.is_none() { return MmError::err(SlurpError::InvalidRequest("MissingContentType".to_string())); } From 99608275d49590ecaef31cab2ede558902bb1371 Mon Sep 17 00:00:00 2001 From: borngraced Date: Sun, 5 Nov 2023 16:57:51 +0100 Subject: [PATCH 40/68] fix review notes Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 20 +++++-------- mm2src/coins/z_coin/storage/blockdb/mod.rs | 9 ++++-- mm2src/coins/z_coin/z_rpc.rs | 27 ++++++++--------- mm2src/mm2_main/src/wasm_tests.rs | 6 ++-- mm2src/mm2_net/Cargo.toml | 4 +-- mm2src/mm2_net/src/wasm/body_stream.rs | 35 ++++------------------ mm2src/mm2_net/src/wasm/http.rs | 17 +++++------ mm2src/mm2_test_helpers/src/for_tests.rs | 10 +++++-- 8 files changed, 51 insertions(+), 77 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 8f8b87aba6..b9429732da 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -75,7 +75,6 @@ use zcash_primitives::transaction::Transaction as ZTransaction; use zcash_primitives::zip32::ChildIndex as Zip32Child; use zcash_primitives::{constants::mainnet as z_mainnet_constants, sapling::PaymentAddress, zip32::ExtendedFullViewingKey, zip32::ExtendedSpendingKey}; - use zcash_proofs::prover::LocalTxProver; mod z_htlc; @@ -812,7 +811,6 @@ pub async fn z_coin_from_conf_and_params( let db_dir_path = PathBuf::new(); #[cfg(not(target_arch = "wasm32"))] let db_dir_path = ctx.dbdir(); - let z_spending_key = None; let builder = ZCoinBuilder::new( ctx, @@ -916,7 +914,7 @@ impl<'a> UtxoCoinBuilder for ZCoinBuilder<'a> { &my_z_addr, ); - let blocks_db = self.blocks_db().await?; + let blocks_db = self.init_blocks_db().await?; let (sync_state_connector, light_wallet_db) = match &self.z_coin_params.mode { #[cfg(not(target_arch = "wasm32"))] ZcoinRpcMode::Native => { @@ -950,12 +948,10 @@ impl<'a> UtxoCoinBuilder for ZCoinBuilder<'a> { sync_state_connector, }; - let z_coin = ZCoin { + Ok(ZCoin { utxo_arc, z_fields: Arc::new(z_fields), - }; - - Ok(z_coin) + }) } } @@ -1005,7 +1001,7 @@ impl<'a> ZCoinBuilder<'a> { } } - async fn blocks_db(&self) -> Result> { + async fn init_blocks_db(&self) -> Result> { let cache_db_path = self.db_dir_path.join(format!("{}_cache.db", self.ticker)); let ctx = self.ctx.clone(); let ticker = self.ticker.to_string(); @@ -1473,10 +1469,6 @@ impl SwapOps for ZCoin { utxo_common::search_for_swap_tx_spend_other(self, input, utxo_common::DEFAULT_SWAP_VOUT).await } - fn check_tx_signed_by_pub(&self, _tx: &[u8], _expected_pub: &[u8]) -> Result> { - unimplemented!(); - } - #[inline] async fn extract_secret( &self, @@ -1487,6 +1479,10 @@ impl SwapOps for ZCoin { utxo_common::extract_secret(secret_hash, spend_tx) } + fn check_tx_signed_by_pub(&self, _tx: &[u8], _expected_pub: &[u8]) -> Result> { + unimplemented!(); + } + fn is_auto_refundable(&self) -> bool { false } async fn wait_for_htlc_refund(&self, _tx: &[u8], _locktime: u64) -> RefundResult<()> { diff --git a/mm2src/coins/z_coin/storage/blockdb/mod.rs b/mm2src/coins/z_coin/storage/blockdb/mod.rs index 5f1ec9c763..88f6a776bf 100644 --- a/mm2src/coins/z_coin/storage/blockdb/mod.rs +++ b/mm2src/coins/z_coin/storage/blockdb/mod.rs @@ -118,9 +118,12 @@ mod wasm_tests { #[wasm_bindgen_test] async fn test_transport() { register_wasm_log(); - let mut client = LightRpcClient::new(vec!["http://pirate.spyglass.quest:8081".to_string()]) - .await - .unwrap(); + let mut client = LightRpcClient::new(vec![ + "http://pirate.spyglass.quest:8081".to_string(), + "http://pirate.battlefield.earth:8081".to_string(), + ]) + .await + .unwrap(); let tree_state = client.get_block_height().await; info!("LATEST BLOCK: {tree_state:?}"); } diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 2acefb95a1..08f4780ba4 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -112,7 +112,7 @@ impl LightRpcClient { let mut errors = Vec::new(); for url in &lightwalletd_urls { - cfg_native!( + #[cfg(not(target_arch = "wasm32"))] let uri = match Uri::from_str(url) { Ok(uri) => uri, Err(err) => { @@ -120,26 +120,25 @@ impl LightRpcClient { continue; }, }; - - let endpoint = match Channel::builder(uri).tls_config(ClientTlsConfig::new()) { + #[cfg(not(target_arch = "wasm32"))] + let endpoint = match Channel::builder(uri).tls_config(ClientTlsConfig::new()) { Ok(endpoint) => endpoint, Err(err) => { errors.push(UrlIterError::TlsConfigFailure(err)); continue; }, }; - let client = match connect_endpoint(endpoint).await { - Ok(tonic_channel) => tonic_channel, - Err(err) => { - errors.push(UrlIterError::ConnectionFailure(err)); - continue; - }, - }; - ); + #[cfg(not(target_arch = "wasm32"))] + let client = match connect_endpoint(endpoint).await { + Ok(tonic_channel) => tonic_channel, + Err(err) => { + errors.push(UrlIterError::ConnectionFailure(err)); + continue; + }, + }; - cfg_wasm32!( - let client = CompactTxStreamerClient::new(TonicClient::new(url.to_string())); - ); + #[cfg(target_arch = "wasm32")] + let client = CompactTxStreamerClient::new(TonicClient::new(url.to_string())); rpc_clients.push(client); } diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index e84b2bab5b..8f9d8028d1 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -11,8 +11,8 @@ use mm2_test_helpers::electrums::{doc_electrums, marty_electrums}; use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init_z_coin_light, init_z_coin_status, morty_conf, pirate_conf, rick_conf, start_swaps, test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, MarketMakerIt, Mm2InitPrivKeyPolicy, - Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, PIRATE_LIGHTWALLETD_URLS, RICK, - ZOMBIE_ELECTRUMS}; + Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, PIRATE_ELECTRUMS, + PIRATE_LIGHTWALLETD_URLS, RICK}; use mm2_test_helpers::get_passphrase; use mm2_test_helpers::structs::{EnableCoinBalance, InitTaskResult, InitZcoinStatus, RpcV2Response, ZCoinActivationResult}; @@ -231,7 +231,7 @@ async fn activate_z_coin_light() { .await .unwrap(); - let activation_result = enable_z_coin_light(&mm, ARRR, ZOMBIE_ELECTRUMS, PIRATE_LIGHTWALLETD_URLS, None).await; + let activation_result = enable_z_coin_light(&mm, ARRR, PIRATE_ELECTRUMS, PIRATE_LIGHTWALLETD_URLS, None).await; let balance = match activation_result.wallet_balance { EnableCoinBalance::Iguana(iguana) => iguana, diff --git a/mm2src/mm2_net/Cargo.toml b/mm2src/mm2_net/Cargo.toml index 66a30202d8..4781319a06 100644 --- a/mm2src/mm2_net/Cargo.toml +++ b/mm2src/mm2_net/Cargo.toml @@ -15,8 +15,8 @@ async-stream = { version = "0.3", optional = true } async-trait = "0.1" bytes = "1.1" cfg-if = "1.0" -derive_more = "0.99" common = { path = "../common" } +derive_more = "0.99" ethkey = { git = "https://github.com/KomodoPlatform/mm2-parity-ethereum.git" } futures = { version = "0.3", package = "futures", features = ["compat", "async-await", "thread-pool"] } http = "0.2" @@ -47,9 +47,9 @@ tower-service = "0.3" wasm-bindgen = "0.2.86" wasm-bindgen-test = { version = "0.3.2" } wasm-bindgen-futures = "0.4.21" +wasm-streams = "0.3.0" web-sys = { version = "0.3.55", features = ["console", "CloseEvent", "DomException", "ErrorEvent", "IdbDatabase", "IdbCursor", "IdbCursorWithValue", "IdbFactory", "IdbIndex", "IdbIndexParameters", "IdbObjectStore", "IdbObjectStoreParameters", "IdbOpenDbRequest", "IdbKeyRange", "IdbTransaction", "IdbTransactionMode", "IdbVersionChangeEvent", "MessageEvent","ReadableStream", "WebSocket"] } -wasm-streams = "0.3.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/mm2src/mm2_net/src/wasm/body_stream.rs b/mm2src/mm2_net/src/wasm/body_stream.rs index 70ef60d023..bd26d1ebed 100644 --- a/mm2src/mm2_net/src/wasm/body_stream.rs +++ b/mm2src/mm2_net/src/wasm/body_stream.rs @@ -352,24 +352,6 @@ impl Body for ResponseBody { } } -impl Default for ResponseBody { - fn default() -> Self { - Self { - body_stream: BodyStream::empty(), - buf: EncodedBytes { - is_base64: Default::default(), - raw_buf: BytesMut::new(), - buf: BytesMut::new(), - }, - incomplete_data: BytesMut::new(), - data: None, - trailer: None, - state: ReadState::Done, - finished_stream: true, - } - } -} - /// Represents a stream of bytes for the response body. pub struct BodyStream { body_stream: Pin>>>, @@ -378,19 +360,12 @@ pub struct BodyStream { impl BodyStream { /// Creates a new `BodyStream` based on an IntoStream. pub fn new(body_stream: IntoStream<'static>) -> Self { - let body_stream = body_stream - .map_ok(|js_value| { - let buffer = Uint8Array::new(&js_value); - - let mut bytes_vec = vec![0; buffer.length() as usize]; - buffer.copy_to(&mut bytes_vec); - - bytes_vec.into() - }) - .map_err(|err| PostGrpcWebErr::InvalidRequest(format!("{err:?}"))); - Self { - body_stream: Box::pin(body_stream), + body_stream: Box::pin( + body_stream + .map_ok(|js_value| Uint8Array::new(&js_value).to_vec().into()) + .map_err(|err| PostGrpcWebErr::InvalidRequest(format!("{err:?}"))), + ), } } diff --git a/mm2src/mm2_net/src/wasm/http.rs b/mm2src/mm2_net/src/wasm/http.rs index d9d51dd314..9dd107c294 100644 --- a/mm2src/mm2_net/src/wasm/http.rs +++ b/mm2src/mm2_net/src/wasm/http.rs @@ -67,12 +67,10 @@ fn set_response_headers_and_content_type( if let Some(header_iter) = header_iter { for header in header_iter { - let header = header.map_to_mm(|err| SlurpError::InvalidRequest(format!("{err:?}")))?; - let pair: Array = header.into(); - - let header_name = pair.get(0).as_string(); - let header_value = pair.get(1).as_string(); - + let pair: Array = header + .map_to_mm(|err| SlurpError::InvalidRequest(format!("{err:?}")))? + .into(); + let (header_name, header_value) = (pair.get(0).as_string(), pair.get(1).as_string()); match (header_name, header_value) { (Some(header_name), Some(header_value)) => { if header_name == CONTENT_TYPE.as_str() { @@ -86,11 +84,10 @@ fn set_response_headers_and_content_type( } } - if content_type.is_none() { - return MmError::err(SlurpError::InvalidRequest("MissingContentType".to_string())); + match content_type { + Some(content_type) => Ok((result, content_type)), + None => MmError::err(SlurpError::InvalidRequest("MissingContentType".to_string())), } - - Ok((result, content_type.unwrap())) } pub struct FetchRequest { diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index 90995511fa..80600dda48 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -159,14 +159,11 @@ pub const MARTY_ELECTRUM_ADDRS: &[&str] = &[ ]; pub const ZOMBIE_TICKER: &str = "ZOMBIE"; pub const ARRR: &str = "ARRR"; -#[cfg(not(target_arch = "wasm32"))] pub const ZOMBIE_ELECTRUMS: &[&str] = &[ "electrum1.cipig.net:10008", "electrum2.cipig.net:10008", "electrum3.cipig.net:10008", ]; -#[cfg(target_arch = "wasm32")] -pub const ZOMBIE_ELECTRUMS: &[&str] = &["zombie.dragonhound.info:30059"]; pub const ZOMBIE_LIGHTWALLETD_URLS: &[&str] = &[ "https://lightd1.pirate.black:443", "https://piratelightd1.cryptoforge.cc:443", @@ -174,7 +171,14 @@ pub const ZOMBIE_LIGHTWALLETD_URLS: &[&str] = &[ "https://piratelightd3.cryptoforge.cc:443", "https://piratelightd4.cryptoforge.cc:443", ]; +#[cfg(not(target_arch = "wasm32"))] pub const PIRATE_ELECTRUMS: &[&str] = &["node1.chainkeeper.pro:10132"]; +#[cfg(target_arch = "wasm32")] +pub const PIRATE_ELECTRUMS: &[&str] = &[ + "electrum3.cipig.net:30008", + "electrum1.cipig.net:30008", + "electrum2.cipig.net:30008", +]; #[cfg(not(target_arch = "wasm32"))] pub const PIRATE_LIGHTWALLETD_URLS: &[&str] = &["http://node1.chainkeeper.pro:443"]; #[cfg(target_arch = "wasm32")] From f1452160a6bdfa3d02f2d81993dc7253d27ddde9 Mon Sep 17 00:00:00 2001 From: borngraced Date: Mon, 6 Nov 2023 09:13:19 +0100 Subject: [PATCH 41/68] fix body_stream review notes Signed-off-by: borngraced --- mm2src/mm2_net/src/wasm/body_stream.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/mm2src/mm2_net/src/wasm/body_stream.rs b/mm2src/mm2_net/src/wasm/body_stream.rs index bd26d1ebed..c38c91ae5f 100644 --- a/mm2src/mm2_net/src/wasm/body_stream.rs +++ b/mm2src/mm2_net/src/wasm/body_stream.rs @@ -20,6 +20,7 @@ use base64::prelude::BASE64_STANDARD; use base64::Engine; use byteorder::{BigEndian, ByteOrder}; use bytes::{BufMut, Bytes, BytesMut}; +use common::log::info; use common::{APPLICATION_GRPC_WEB, APPLICATION_GRPC_WEB_PROTO, APPLICATION_GRPC_WEB_TEXT, APPLICATION_GRPC_WEB_TEXT_PROTO}; use futures_util::ready; @@ -72,7 +73,7 @@ impl EncodedBytes { if self.raw_buf.len() >= index { let decoded = BASE64_STANDARD - .decode(self.buf.split_to(index)) + .decode(self.raw_buf.split_to(index)) .map(Bytes::from) .map_err(|err| PostGrpcWebErr::DecodeBody(err.to_string()))?; self.buf.put(decoded); @@ -209,7 +210,7 @@ impl ResponseBody { let data_length_bytes = this.buf.take(4); let data_length = BigEndian::read_u32(data_length_bytes.as_ref()); - this.incomplete_data.unsplit(data_length_bytes); + this.incomplete_data.extend_from_slice(&data_length_bytes); *this.state = ReadState::Data(data_length); } }, @@ -290,8 +291,7 @@ impl Body for ResponseBody { fn poll_data(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>> { // Check if there's already some data in buffer and return that if self.data.is_some() { - let data = self.data.take().unwrap(); - return Poll::Ready(Some(Ok(data.freeze()))); + return Poll::Ready(self.data.take().map(|d| Ok(d.freeze()))); } // If reading data is finished return `None` @@ -312,8 +312,7 @@ impl Body for ResponseBody { if self.data.is_some() { // If data is available in buffer, return that - let data = self.data.take().unwrap(); - return Poll::Ready(Some(Ok(data.freeze()))); + return Poll::Ready(self.data.take().map(|d| Ok(d.freeze()))); } else if self.state.finished_data() { // If we finished reading data continue return `None` return Poll::Ready(None); From b074ca70d86d2fdbe2f40f14a1125e54ccfc2792 Mon Sep 17 00:00:00 2001 From: borngraced Date: Mon, 6 Nov 2023 09:44:28 +0100 Subject: [PATCH 42/68] use pirate.wallet.sdk.rpc for z_coin proto Signed-off-by: borngraced --- mm2src/coins/z_coin/compact_formats.proto | 3 +-- mm2src/coins/z_coin/service.proto | 3 +-- mm2src/coins/z_coin/storage/blockdb/mod.rs | 9 +++------ mm2src/coins/z_coin/z_rpc.rs | 2 +- mm2src/mm2_net/src/wasm/body_stream.rs | 1 - mm2src/mm2_test_helpers/src/for_tests.rs | 2 +- 6 files changed, 7 insertions(+), 13 deletions(-) diff --git a/mm2src/coins/z_coin/compact_formats.proto b/mm2src/coins/z_coin/compact_formats.proto index d0e1d7a410..9a88707355 100644 --- a/mm2src/coins/z_coin/compact_formats.proto +++ b/mm2src/coins/z_coin/compact_formats.proto @@ -1,6 +1,5 @@ syntax = "proto3"; -// TODO: use pirate.wallet.sdk.rpc for package name. -package cash.z.wallet.sdk.rpc; +package pirate.wallet.sdk.rpc; option go_package = "walletrpc"; option swift_prefix = ""; // Remember that proto3 fields are all optional. A field that is not present will be set to its zero value. diff --git a/mm2src/coins/z_coin/service.proto b/mm2src/coins/z_coin/service.proto index 300b213639..e8cd6f6ea2 100644 --- a/mm2src/coins/z_coin/service.proto +++ b/mm2src/coins/z_coin/service.proto @@ -3,8 +3,7 @@ // file COPYING or https://www.opensource.org/licenses/mit-license.php . syntax = "proto3"; -// TODO: use pirate.wallet.sdk.rpc for package name. -package cash.z.wallet.sdk.rpc; +package pirate.wallet.sdk.rpc; option go_package = ".;walletrpc"; option swift_prefix = ""; import "compact_formats.proto"; diff --git a/mm2src/coins/z_coin/storage/blockdb/mod.rs b/mm2src/coins/z_coin/storage/blockdb/mod.rs index 88f6a776bf..1d030d501d 100644 --- a/mm2src/coins/z_coin/storage/blockdb/mod.rs +++ b/mm2src/coins/z_coin/storage/blockdb/mod.rs @@ -118,12 +118,9 @@ mod wasm_tests { #[wasm_bindgen_test] async fn test_transport() { register_wasm_log(); - let mut client = LightRpcClient::new(vec![ - "http://pirate.spyglass.quest:8081".to_string(), - "http://pirate.battlefield.earth:8081".to_string(), - ]) - .await - .unwrap(); + let mut client = LightRpcClient::new(vec!["http://pirate.battlefield.earth:8581".to_string()]) + .await + .unwrap(); let tree_state = client.get_block_height().await; info!("LATEST BLOCK: {tree_state:?}"); } diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 08f4780ba4..47cdaaa7d0 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -31,7 +31,7 @@ use zcash_primitives::transaction::TxId; use zcash_primitives::zip32::ExtendedSpendingKey; pub(crate) mod z_coin_grpc { - tonic::include_proto!("cash.z.wallet.sdk.rpc"); + tonic::include_proto!("pirate.wallet.sdk.rpc"); } use z_coin_grpc::compact_tx_streamer_client::CompactTxStreamerClient; use z_coin_grpc::ChainSpec; diff --git a/mm2src/mm2_net/src/wasm/body_stream.rs b/mm2src/mm2_net/src/wasm/body_stream.rs index c38c91ae5f..6c45d809ac 100644 --- a/mm2src/mm2_net/src/wasm/body_stream.rs +++ b/mm2src/mm2_net/src/wasm/body_stream.rs @@ -20,7 +20,6 @@ use base64::prelude::BASE64_STANDARD; use base64::Engine; use byteorder::{BigEndian, ByteOrder}; use bytes::{BufMut, Bytes, BytesMut}; -use common::log::info; use common::{APPLICATION_GRPC_WEB, APPLICATION_GRPC_WEB_PROTO, APPLICATION_GRPC_WEB_TEXT, APPLICATION_GRPC_WEB_TEXT_PROTO}; use futures_util::ready; diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index 80600dda48..79a29a8876 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -182,7 +182,7 @@ pub const PIRATE_ELECTRUMS: &[&str] = &[ #[cfg(not(target_arch = "wasm32"))] pub const PIRATE_LIGHTWALLETD_URLS: &[&str] = &["http://node1.chainkeeper.pro:443"]; #[cfg(target_arch = "wasm32")] -pub const PIRATE_LIGHTWALLETD_URLS: &[&str] = &["http://pirate.spyglass.quest:8081"]; +pub const PIRATE_LIGHTWALLETD_URLS: &[&str] = &["http://pirate.battlefield.earth:8581"]; pub const DEFAULT_RPC_PASSWORD: &str = "pass"; pub const QRC20_ELECTRUMS: &[&str] = &[ "electrum1.cipig.net:10071", From 7115f16784887a0b1aeb346a7ab64f6f58c0ea48 Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 8 Nov 2023 08:40:55 +0100 Subject: [PATCH 43/68] simplified poll_data fn Signed-off-by: borngraced --- mm2src/mm2_net/src/wasm/body_stream.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/mm2src/mm2_net/src/wasm/body_stream.rs b/mm2src/mm2_net/src/wasm/body_stream.rs index 6c45d809ac..028c040dfc 100644 --- a/mm2src/mm2_net/src/wasm/body_stream.rs +++ b/mm2src/mm2_net/src/wasm/body_stream.rs @@ -288,14 +288,9 @@ impl Body for ResponseBody { type Error = PostGrpcWebErr; fn poll_data(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>> { - // Check if there's already some data in buffer and return that - if self.data.is_some() { - return Poll::Ready(self.data.take().map(|d| Ok(d.freeze()))); - } - // If reading data is finished return `None` if self.state.finished_data() { - return Poll::Ready(None); + return Poll::Ready(self.data.take().map(|d| Ok(d.freeze()))); } loop { @@ -309,12 +304,9 @@ impl Body for ResponseBody { return Poll::Ready(Some(Err(e))); } - if self.data.is_some() { - // If data is available in buffer, return that - return Poll::Ready(self.data.take().map(|d| Ok(d.freeze()))); - } else if self.state.finished_data() { + if self.state.finished_data() { // If we finished reading data continue return `None` - return Poll::Ready(None); + return Poll::Ready(self.data.take().map(|d| Ok(d.freeze()))); } else if self.finished_stream { // If stream is finished but data is not finished return error return Poll::Ready(Some(Err(PostGrpcWebErr::InvalidRequest("Bad response".to_string())))); From dace15f7842f787ce4575313ae38caca7f3462d5 Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 15 Nov 2023 16:12:36 +0100 Subject: [PATCH 44/68] =?UTF-8?q?save=20dev=20state=20=E2=80=94=20imple=20?= =?UTF-8?q?zcash=20params=20db?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: borngraced --- Cargo.lock | 7 +- mm2src/coins/Cargo.toml | 1 + mm2src/coins/z_coin.rs | 1 + .../storage/blockdb/blockdb_idb_storage.rs | 5 +- mm2src/coins/z_coin/z_params/indexeddb.rs | 151 ++++++++++++++++++ mm2src/coins/z_coin/z_params/mod.rs | 79 +++++++++ mm2src/mm2_db/src/indexed_db/indexed_db.rs | 1 - 7 files changed, 238 insertions(+), 7 deletions(-) create mode 100644 mm2src/coins/z_coin/z_params/indexeddb.rs create mode 100644 mm2src/coins/z_coin/z_params/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 3415856f39..b9a865bb34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1000,6 +1000,7 @@ dependencies = [ "bitcoin", "bitcoin_hashes", "bitcrypto", + "blake2b_simd", "byteorder", "bytes 0.4.12", "cfg-if 1.0.0", @@ -6687,12 +6688,12 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 0.4.6", + "itoa 1.0.1", "ryu", "serde", ] diff --git a/mm2src/coins/Cargo.toml b/mm2src/coins/Cargo.toml index 8ce31cd8a0..ede0b14661 100644 --- a/mm2src/coins/Cargo.toml +++ b/mm2src/coins/Cargo.toml @@ -121,6 +121,7 @@ spl-token = { version = "3", optional = true } spl-associated-token-account = { version = "1", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] +blake2b_simd = "0.5" ff = "0.8" futures-util = "0.3" jubjub = "0.5.1" diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 14dd9cbee4..d9472d6555 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -105,6 +105,7 @@ pub use z_coin_errors::*; pub mod storage; #[cfg(all(test, feature = "zhtlc-native-tests"))] mod z_coin_native_tests; +#[cfg(target_arch = "wasm32")] pub mod z_params; /// `ZP2SHSpendError` compatible `TransactionErr` handling macro. macro_rules! try_ztx_s { diff --git a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs index 649249b869..f8c62d648f 100644 --- a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs +++ b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs @@ -4,9 +4,8 @@ use crate::z_coin::z_coin_errors::ZcoinStorageError; use async_trait::async_trait; use mm2_core::mm_ctx::MmArc; -use mm2_db::indexed_db::{BeBigUint, DbIdentifier, DbInstance, DbUpgrader, IndexedDb, IndexedDbBuilder, InitDbResult, - MultiIndex, OnUpgradeResult, TableSignature}; -use mm2_db::indexed_db::{ConstructibleDb, DbLocked}; +use mm2_db::indexed_db::{BeBigUint, ConstructibleDb, DbIdentifier, DbInstance, DbLocked, DbUpgrader, IndexedDb, + IndexedDbBuilder, InitDbResult, MultiIndex, OnUpgradeResult, TableSignature}; use mm2_err_handle::prelude::*; use protobuf::Message; use std::path::Path; diff --git a/mm2src/coins/z_coin/z_params/indexeddb.rs b/mm2src/coins/z_coin/z_params/indexeddb.rs new file mode 100644 index 0000000000..5059141e2c --- /dev/null +++ b/mm2src/coins/z_coin/z_params/indexeddb.rs @@ -0,0 +1,151 @@ +use crate::z_coin::z_coin_errors::ZcoinStorageError; + +use mm2_core::mm_ctx::MmArc; +use mm2_db::indexed_db::{ConstructibleDb, DbIdentifier, DbInstance, DbLocked, DbUpgrader, IndexedDb, IndexedDbBuilder, + InitDbResult, OnUpgradeResult, SharedDb, TableSignature}; +use mm2_err_handle::prelude::*; + +const DB_NAME: &str = "z_params"; +const DB_VERSION: u32 = 1; + +pub type ZcashParamsWasmRes = MmResult; +pub type ZcashParamsInnerLocked<'a> = DbLocked<'a, ZcashParamsWasmInner>; + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct ZcashParamsWasmTable { + sapling_spend1: Vec, + sapling_spend2: Vec, + sapling_spend3: Vec, + sapling_spend4: Vec, + sapling_spend5: Vec, + sapling_output: Vec, +} + +impl ZcashParamsWasmTable { + pub const SPEND_OUTPUT_INDEX: &str = "sapling_spend_sapling_output_index"; +} + +impl TableSignature for ZcashParamsWasmTable { + const TABLE_NAME: &'static str = "z_params_bytes"; + + fn on_upgrade_needed(upgrader: &DbUpgrader, old_version: u32, new_version: u32) -> OnUpgradeResult<()> { + if let (0, 1) = (old_version, new_version) { + let table = upgrader.create_table(Self::TABLE_NAME)?; + table.create_multi_index(Self::SPEND_OUTPUT_INDEX, &["sapling_spend", "sapling_output"], true)?; + table.create_index("sapling_spend", false)?; + table.create_index("sapling_output", false)?; + } + + Ok(()) + } +} + +pub struct ZcashParamsWasmInner(IndexedDb); + +#[async_trait::async_trait] +impl DbInstance for ZcashParamsWasmInner { + const DB_NAME: &'static str = DB_NAME; + + async fn init(db_id: DbIdentifier) -> InitDbResult { + let inner = IndexedDbBuilder::new(db_id) + .with_version(DB_VERSION) + .with_table::() + .build() + .await?; + + Ok(Self(inner)) + } +} + +impl ZcashParamsWasmInner { + pub fn get_inner(&self) -> &IndexedDb { &self.0 } +} + +#[derive(Clone)] +pub struct ZcashParamsWasmImpl(SharedDb); + +impl ZcashParamsWasmImpl { + pub async fn new(ctx: MmArc) -> MmResult { + Ok(Self(ConstructibleDb::new(&ctx).into_shared())) + } + + async fn lock_db(&self) -> ZcashParamsWasmRes> { + self.0 + .get_or_initialize() + .await + .mm_err(|err| ZcoinStorageError::DbError(err.to_string())) + } + + pub async fn save_params(&self, sapling_spend: &[u8], sapling_output: &[u8]) -> MmResult<(), ZcoinStorageError> { + let locked_db = self.lock_db().await?; + let db_transaction = locked_db.get_inner().transaction().await?; + let params_db = db_transaction.table::().await?; + + let mut sapling_spend_chunks: Vec> = sapling_spend.chunks(5).map(|chunk| chunk.to_vec()).collect(); + // Ensure we have at least 5 chunks + while sapling_spend_chunks.len() < 5 { + sapling_spend_chunks.push(Vec::new()); + } + + let params = ZcashParamsWasmTable { + sapling_spend1: sapling_spend_chunks[0].clone(), + sapling_spend2: sapling_spend_chunks[1].clone(), + sapling_spend3: sapling_spend_chunks[2].clone(), + sapling_spend4: sapling_spend_chunks[3].clone(), + sapling_spend5: sapling_spend_chunks[4].clone(), + sapling_output: sapling_output.to_vec(), + }; + params_db.add_item(¶ms).await?; + + Ok(()) + } + + pub async fn check_params(&self) -> MmResult { + let locked_db = self.lock_db().await?; + let db_transaction = locked_db.get_inner().transaction().await?; + let params_db = db_transaction.table::().await?; + + let maybe_param = params_db + .cursor_builder() + .open_cursor(ZcashParamsWasmTable::SPEND_OUTPUT_INDEX) + .await? + .next() + .await?; + + Ok(maybe_param.is_some()) + } + + pub async fn get_params(&self) -> MmResult<(Vec, Vec), ZcoinStorageError> { + let locked_db = self.lock_db().await?; + let db_transaction = locked_db.get_inner().transaction().await?; + let params_db = db_transaction.table::().await?; + + let maybe_params = params_db.get_all_items().await?; + match maybe_params.first() { + Some((_, p)) => { + let mut sapling_spend = Vec::with_capacity( + p.sapling_spend1.len() + + p.sapling_spend2.len() + + p.sapling_spend3.len() + + p.sapling_spend4.len() + + p.sapling_spend5.len(), + ); + + for chunk in [ + &p.sapling_spend1, + &p.sapling_spend2, + &p.sapling_spend3, + &p.sapling_spend4, + &p.sapling_spend5, + ] { + sapling_spend.extend_from_slice(chunk); + } + + Ok((sapling_spend, p.sapling_output.clone())) + }, + None => MmError::err(ZcoinStorageError::CorruptedData( + "No z_cash params found in storage".to_string(), + )), + } + } +} diff --git a/mm2src/coins/z_coin/z_params/mod.rs b/mm2src/coins/z_coin/z_params/mod.rs new file mode 100644 index 0000000000..8ef3c8a119 --- /dev/null +++ b/mm2src/coins/z_coin/z_params/mod.rs @@ -0,0 +1,79 @@ +mod indexeddb; + +use blake2b_simd::State; +pub use indexeddb::ZcashParamsWasmImpl; +use mm2_err_handle::prelude::*; +use mm2_net::wasm::http::FetchRequest; + +const DOWNLOAD_URL: &str = "https://komodoplatform.com/downloads"; +const SAPLING_SPEND_NAME: &str = "sapling-spend.params"; +const SAPLING_OUTPUT_NAME: &str = "sapling-output.params"; +const SAPLING_SPEND_HASH: &str = "8270785a1a0d0bc77196f000ee6d221c9c9894f55307bd9357c3f0105d31ca63991ab91324160d8f53e2bbd3c2633a6eb8bdf5205d822e7f3f73edac51b2b70c"; +const SAPLING_OUTPUT_HASH: &str = "657e3d38dbb5cb5e7dd2970e8b03d69b4787dd907285b5a7f0790dcc8072f60bf593b32cc2d1c030e00ff5ae64bf84c5c3beb84ddc841d48264b4a171744d028"; + +#[derive(Debug, derive_more::Display)] +pub enum ZcashParamsBytesError { + IO(String), +} + +async fn fetch_params(name: &str, expected_hash: &str) -> MmResult, ZcashParamsBytesError> { + let (status, file) = FetchRequest::get(&format!("{DOWNLOAD_URL}/{name}")) + .cors() + .request_array() + .await + .mm_err(|err| ZcashParamsBytesError::IO(err.to_string()))?; + + assert_eq!(200, status); + + let hash = State::new().update(&file).finalize().to_hex(); + // Verify parameter file hash. + if &hash != expected_hash { + return Err(ZcashParamsBytesError::IO(format!( + "{} failed validation (expected: {}, actual: {}, fetched {} bytes)", + name, + expected_hash, + hash, + file.len() + )) + .into()); + } + + Ok(file) +} + +pub async fn download_parameters() -> MmResult<(Vec, Vec), ZcashParamsBytesError> { + Ok(( + fetch_params(SAPLING_SPEND_NAME, SAPLING_SPEND_HASH).await?, + fetch_params(SAPLING_OUTPUT_NAME, SAPLING_OUTPUT_HASH).await?, + )) +} + +use common::log::wasm_log::register_wasm_log; +use mm2_err_handle::prelude::MmResult; +use mm2_test_helpers::for_tests::mm_ctx_with_custom_db; +use wasm_bindgen_test::*; + +#[wasm_bindgen_test] +async fn test_download_save_and_get_params() { + register_wasm_log(); + let ctx = mm_ctx_with_custom_db(); + let db = ZcashParamsWasmImpl::new(ctx).await.unwrap(); + // download params + let (sapling_spend, sapling_output) = download_parameters().await.unwrap(); + // save params + db.save_params(&sapling_spend, &sapling_output).await.unwrap(); + // get params + let (sapling_spend_db, sapling_output_db) = db.get_params().await.unwrap(); + assert_eq!(sapling_spend, sapling_spend_db); + assert_eq!(sapling_output, sapling_output_db); +} + +#[wasm_bindgen_test] +async fn test_check_for_no_params() { + register_wasm_log(); + let ctx = mm_ctx_with_custom_db(); + let db = ZcashParamsWasmImpl::new(ctx).await.unwrap(); + // check for no params + let check_params = db.check_params().await.unwrap(); + assert_eq!(false, check_params) +} diff --git a/mm2src/mm2_db/src/indexed_db/indexed_db.rs b/mm2src/mm2_db/src/indexed_db/indexed_db.rs index 001f973bd7..2e327ce92d 100644 --- a/mm2src/mm2_db/src/indexed_db/indexed_db.rs +++ b/mm2src/mm2_db/src/indexed_db/indexed_db.rs @@ -316,7 +316,6 @@ impl<'transaction, Table: TableSignature> DbTable<'transaction, Table> { /// https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/add pub async fn add_item(&self, item: &Table) -> DbTransactionResult { let item = json::to_value(item).map_to_mm(|e| DbTransactionError::ErrorSerializingItem(e.to_string()))?; - let (result_tx, result_rx) = oneshot::channel(); let event = internal::DbTableEvent::AddItem { item, result_tx }; send_event_recv_response(&self.event_tx, event, result_rx).await From b38c61a3cf167cb23a5eb8109512b1d4d1ccf6a7 Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 15 Nov 2023 18:15:54 +0100 Subject: [PATCH 45/68] =?UTF-8?q?save=20dev=20state=20=E2=80=94=20sapling?= =?UTF-8?q?=5Fspend=5Fto=5Fchunks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 30 ++++++- mm2src/coins/z_coin/z_coin_errors.rs | 1 + mm2src/coins/z_coin/z_params/indexeddb.rs | 100 ++++++++++++---------- mm2src/coins/z_coin/z_params/mod.rs | 2 +- 4 files changed, 85 insertions(+), 48 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index d9472d6555..ba6bb8b263 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -13,6 +13,8 @@ use crate::utxo::{sat_from_big_decimal, utxo_common, ActualTxFee, AdditionalTxDa BroadcastTxErr, FeePolicy, GetUtxoListOps, HistoryUtxoTx, HistoryUtxoTxMap, MatureUnspentList, RecentlySpentOutPointsGuard, UtxoActivationParams, UtxoAddressFormat, UtxoArc, UtxoCoinFields, UtxoCommonOps, UtxoRpcMode, UtxoTxBroadcastOps, UtxoTxGenerationOps, VerboseTransactionFrom}; +#[cfg(target_arch = "wasm32")] +use crate::z_coin::z_params::{download_parameters, ZcashParamsWasmImpl}; use crate::TxFeeDetails; use crate::{BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, CoinFutSpawner, ConfirmPaymentInput, FeeApproxStage, FoundSwapTxSpend, HistorySyncState, MakerSwapTakerCoin, MarketCoinOps, MmCoin, MmCoinEnum, @@ -129,9 +131,9 @@ macro_rules! try_ztx_s { const DEX_FEE_OVK: OutgoingViewingKey = OutgoingViewingKey([7; 32]); const DEX_FEE_Z_ADDR: &str = "zs1rp6426e9r6jkq2nsanl66tkd34enewrmr0uvj0zelhkcwmsy0uvxz2fhm9eu9rl3ukxvgzy2v9f"; cfg_native!( - const BLOCKS_TABLE: &str = "blocks"; const SAPLING_OUTPUT_NAME: &str = "sapling-output.params"; const SAPLING_SPEND_NAME: &str = "sapling-spend.params"; + const BLOCKS_TABLE: &str = "blocks"; const TRANSACTIONS_TABLE: &str = "transactions"; const SAPLING_SPEND_EXPECTED_HASH: &str = "8e48ffd23abb3a5fd9c5589204f32d9c31285a04b78096ba40a79b75677efc13"; const SAPLING_OUTPUT_EXPECTED_HASH: &str = "2f0ebbcbb9bb0bcffe95a397e7eba89c29eb4dde6191c339db88570e3f3fb0e4"; @@ -1036,6 +1038,32 @@ impl<'a> ZCoinBuilder<'a> { let (spend_buf, output_buf) = wagyu_zcash_parameters::load_sapling_parameters(); Ok(LocalTxProver::from_bytes(&spend_buf[..], &output_buf[..])) } + // async fn z_tx_prover(&self) -> Result> { + // let params_db = ZcashParamsWasmImpl::new(self.ctx.clone()) + // .await + // .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; + // return if !params_db + // .check_params() + // .await + // .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))? + // { + // // download params + // let (sapling_spend, sapling_output) = download_parameters().await.unwrap(); + // // save params + // params_db + // .save_params(&sapling_spend, &sapling_output) + // .await + // .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; + // Ok(LocalTxProver::from_bytes(&sapling_spend[..], &sapling_output[..])) + // } else { + // // get params + // let (sapling_spend, sapling_output) = params_db + // .get_params() + // .await + // .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; + // Ok(LocalTxProver::from_bytes(&sapling_spend[..], &sapling_output[..])) + // }; + // } } /// Initialize `ZCoin` with a forced `z_spending_key`. diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index 8fd5c2e1c2..856c26b38a 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -235,6 +235,7 @@ pub enum ZCoinBuildError { Io(std::io::Error), RpcClientInitErr(ZcoinClientInitError), ZCashParamsNotFound, + ZCashParamsError(String), ZDerivationPathNotSet, SaplingParamsInvalidChecksum, } diff --git a/mm2src/coins/z_coin/z_params/indexeddb.rs b/mm2src/coins/z_coin/z_params/indexeddb.rs index 5059141e2c..66befa28c3 100644 --- a/mm2src/coins/z_coin/z_params/indexeddb.rs +++ b/mm2src/coins/z_coin/z_params/indexeddb.rs @@ -1,4 +1,5 @@ use crate::z_coin::z_coin_errors::ZcoinStorageError; +use common::log::info; use mm2_core::mm_ctx::MmArc; use mm2_db::indexed_db::{ConstructibleDb, DbIdentifier, DbInstance, DbLocked, DbUpgrader, IndexedDb, IndexedDbBuilder, @@ -11,14 +12,13 @@ const DB_VERSION: u32 = 1; pub type ZcashParamsWasmRes = MmResult; pub type ZcashParamsInnerLocked<'a> = DbLocked<'a, ZcashParamsWasmInner>; +// indexeddb max data =267386880 bytes to save, so we need to split sapling_spend #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ZcashParamsWasmTable { - sapling_spend1: Vec, - sapling_spend2: Vec, - sapling_spend3: Vec, - sapling_spend4: Vec, - sapling_spend5: Vec, + sapling_spend_id: u8, + sapling_spend: Vec, sapling_output: Vec, + ticker: String, } impl ZcashParamsWasmTable { @@ -34,6 +34,7 @@ impl TableSignature for ZcashParamsWasmTable { table.create_multi_index(Self::SPEND_OUTPUT_INDEX, &["sapling_spend", "sapling_output"], true)?; table.create_index("sapling_spend", false)?; table.create_index("sapling_output", false)?; + table.create_index("ticker", false)?; } Ok(()) @@ -81,22 +82,19 @@ impl ZcashParamsWasmImpl { let db_transaction = locked_db.get_inner().transaction().await?; let params_db = db_transaction.table::().await?; - let mut sapling_spend_chunks: Vec> = sapling_spend.chunks(5).map(|chunk| chunk.to_vec()).collect(); - // Ensure we have at least 5 chunks - while sapling_spend_chunks.len() < 5 { - sapling_spend_chunks.push(Vec::new()); + let sapling_spend_chunks = sapling_spend_to_chunks(sapling_spend); + for i in 0..12 { + info!("current {i}"); + let sapling_output = if i > 0 { vec![] } else { sapling_output.to_vec() }; + let params = ZcashParamsWasmTable { + sapling_spend_id: i as u8, + sapling_spend: sapling_spend_chunks[i].clone(), + sapling_output, + ticker: "z_params".to_string(), + }; + params_db.add_item(¶ms).await?; } - let params = ZcashParamsWasmTable { - sapling_spend1: sapling_spend_chunks[0].clone(), - sapling_spend2: sapling_spend_chunks[1].clone(), - sapling_spend3: sapling_spend_chunks[2].clone(), - sapling_spend4: sapling_spend_chunks[3].clone(), - sapling_spend5: sapling_spend_chunks[4].clone(), - sapling_output: sapling_output.to_vec(), - }; - params_db.add_item(¶ms).await?; - Ok(()) } @@ -107,7 +105,8 @@ impl ZcashParamsWasmImpl { let maybe_param = params_db .cursor_builder() - .open_cursor(ZcashParamsWasmTable::SPEND_OUTPUT_INDEX) + .only("ticker", "z_params")? + .open_cursor("ticker") .await? .next() .await?; @@ -119,33 +118,42 @@ impl ZcashParamsWasmImpl { let locked_db = self.lock_db().await?; let db_transaction = locked_db.get_inner().transaction().await?; let params_db = db_transaction.table::().await?; + let mut maybe_params = params_db + .cursor_builder() + .only("ticker", "z_params")? + .open_cursor("ticker") + .await?; - let maybe_params = params_db.get_all_items().await?; - match maybe_params.first() { - Some((_, p)) => { - let mut sapling_spend = Vec::with_capacity( - p.sapling_spend1.len() - + p.sapling_spend2.len() - + p.sapling_spend3.len() - + p.sapling_spend4.len() - + p.sapling_spend5.len(), - ); - - for chunk in [ - &p.sapling_spend1, - &p.sapling_spend2, - &p.sapling_spend3, - &p.sapling_spend4, - &p.sapling_spend5, - ] { - sapling_spend.extend_from_slice(chunk); - } - - Ok((sapling_spend, p.sapling_output.clone())) - }, - None => MmError::err(ZcoinStorageError::CorruptedData( - "No z_cash params found in storage".to_string(), - )), + let mut sapling_spend = vec![]; + let mut sapling_output = vec![]; + + while let Some((_, params)) = maybe_params.next().await? { + sapling_spend.extend_from_slice(¶ms.sapling_spend); + if params.sapling_spend_id < 1 { + sapling_output = params.sapling_output + } } + + Ok((sapling_spend, sapling_output.clone())) } } + +fn sapling_spend_to_chunks(sapling_spend: &[u8]) -> Vec> { + // Set the target chunk size + let target_chunk_size = 12; + // Calculate the target size for each chunk + let chunk_size = sapling_spend.len() / target_chunk_size; + // Calculate the remainder for cases when the length is not perfectly divisible + let remainder = sapling_spend.len() % target_chunk_size; + let mut sapling_spend_chunks: Vec> = Vec::with_capacity(target_chunk_size); + let mut start = 0; + for i in 0..target_chunk_size { + let end = start + chunk_size + if i < remainder { 1 } else { 0 }; + // Extract the current chunk from the original vector + sapling_spend_chunks.push(sapling_spend[start..end].to_vec()); + // Move the start index to the next position + start = end; + } + + sapling_spend_chunks +} diff --git a/mm2src/coins/z_coin/z_params/mod.rs b/mm2src/coins/z_coin/z_params/mod.rs index 8ef3c8a119..8b1660d0cd 100644 --- a/mm2src/coins/z_coin/z_params/mod.rs +++ b/mm2src/coins/z_coin/z_params/mod.rs @@ -64,7 +64,7 @@ async fn test_download_save_and_get_params() { db.save_params(&sapling_spend, &sapling_output).await.unwrap(); // get params let (sapling_spend_db, sapling_output_db) = db.get_params().await.unwrap(); - assert_eq!(sapling_spend, sapling_spend_db); + // assert_eq!(sapling_spend, sapling_spend_db); assert_eq!(sapling_output, sapling_output_db); } From 5ebf35eb6f0bf5069c32a8b598fff9722a9a4137 Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 15 Nov 2023 18:36:28 +0100 Subject: [PATCH 46/68] =?UTF-8?q?save=20dev=20state=20=E2=80=94=20enable?= =?UTF-8?q?=20assert=5Feq!(sapling=5Fspend,=20sapling=5Fspend=5Fdb)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 55 +++++++++++------------ mm2src/coins/z_coin/z_params/indexeddb.rs | 4 +- mm2src/coins/z_coin/z_params/mod.rs | 2 +- 3 files changed, 27 insertions(+), 34 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index ba6bb8b263..c13d584bbf 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -1033,37 +1033,32 @@ impl<'a> ZCoinBuilder<'a> { } #[cfg(target_arch = "wasm32")] - // TODO: Implement TxProver for WASM using indexed db after merging transport layer PR. async fn z_tx_prover(&self) -> Result> { - let (spend_buf, output_buf) = wagyu_zcash_parameters::load_sapling_parameters(); - Ok(LocalTxProver::from_bytes(&spend_buf[..], &output_buf[..])) - } - // async fn z_tx_prover(&self) -> Result> { - // let params_db = ZcashParamsWasmImpl::new(self.ctx.clone()) - // .await - // .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; - // return if !params_db - // .check_params() - // .await - // .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))? - // { - // // download params - // let (sapling_spend, sapling_output) = download_parameters().await.unwrap(); - // // save params - // params_db - // .save_params(&sapling_spend, &sapling_output) - // .await - // .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; - // Ok(LocalTxProver::from_bytes(&sapling_spend[..], &sapling_output[..])) - // } else { - // // get params - // let (sapling_spend, sapling_output) = params_db - // .get_params() - // .await - // .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; - // Ok(LocalTxProver::from_bytes(&sapling_spend[..], &sapling_output[..])) - // }; - // } + let params_db = ZcashParamsWasmImpl::new(self.ctx.clone()) + .await + .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; + return if !params_db + .check_params() + .await + .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))? + { + // download params + let (sapling_spend, sapling_output) = download_parameters().await.unwrap(); + // save params + params_db + .save_params(&sapling_spend, &sapling_output) + .await + .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; + Ok(LocalTxProver::from_bytes(&sapling_spend[..], &sapling_output[..])) + } else { + // get params + let (sapling_spend, sapling_output) = params_db + .get_params() + .await + .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; + Ok(LocalTxProver::from_bytes(&sapling_spend[..], &sapling_output[..])) + }; + } } /// Initialize `ZCoin` with a forced `z_spending_key`. diff --git a/mm2src/coins/z_coin/z_params/indexeddb.rs b/mm2src/coins/z_coin/z_params/indexeddb.rs index 66befa28c3..825f70cc54 100644 --- a/mm2src/coins/z_coin/z_params/indexeddb.rs +++ b/mm2src/coins/z_coin/z_params/indexeddb.rs @@ -1,5 +1,4 @@ use crate::z_coin::z_coin_errors::ZcoinStorageError; -use common::log::info; use mm2_core::mm_ctx::MmArc; use mm2_db::indexed_db::{ConstructibleDb, DbIdentifier, DbInstance, DbLocked, DbUpgrader, IndexedDb, IndexedDbBuilder, @@ -84,7 +83,6 @@ impl ZcashParamsWasmImpl { let sapling_spend_chunks = sapling_spend_to_chunks(sapling_spend); for i in 0..12 { - info!("current {i}"); let sapling_output = if i > 0 { vec![] } else { sapling_output.to_vec() }; let params = ZcashParamsWasmTable { sapling_spend_id: i as u8, @@ -129,7 +127,7 @@ impl ZcashParamsWasmImpl { while let Some((_, params)) = maybe_params.next().await? { sapling_spend.extend_from_slice(¶ms.sapling_spend); - if params.sapling_spend_id < 1 { + if params.sapling_spend_id == 0 { sapling_output = params.sapling_output } } diff --git a/mm2src/coins/z_coin/z_params/mod.rs b/mm2src/coins/z_coin/z_params/mod.rs index 8b1660d0cd..8ef3c8a119 100644 --- a/mm2src/coins/z_coin/z_params/mod.rs +++ b/mm2src/coins/z_coin/z_params/mod.rs @@ -64,7 +64,7 @@ async fn test_download_save_and_get_params() { db.save_params(&sapling_spend, &sapling_output).await.unwrap(); // get params let (sapling_spend_db, sapling_output_db) = db.get_params().await.unwrap(); - // assert_eq!(sapling_spend, sapling_spend_db); + assert_eq!(sapling_spend, sapling_spend_db); assert_eq!(sapling_output, sapling_output_db); } From c5eaed0bdb48c68413b8ac2c32ebcd4fe03def3a Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 15 Nov 2023 19:01:36 +0100 Subject: [PATCH 47/68] fix clippy warning Signed-off-by: borngraced --- mm2src/coins/z_coin/z_params/indexeddb.rs | 6 +++--- mm2src/coins/z_coin/z_params/mod.rs | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/mm2src/coins/z_coin/z_params/indexeddb.rs b/mm2src/coins/z_coin/z_params/indexeddb.rs index 825f70cc54..d974e1658a 100644 --- a/mm2src/coins/z_coin/z_params/indexeddb.rs +++ b/mm2src/coins/z_coin/z_params/indexeddb.rs @@ -82,11 +82,11 @@ impl ZcashParamsWasmImpl { let params_db = db_transaction.table::().await?; let sapling_spend_chunks = sapling_spend_to_chunks(sapling_spend); - for i in 0..12 { + for (i, item) in sapling_spend_chunks.iter().enumerate() { let sapling_output = if i > 0 { vec![] } else { sapling_output.to_vec() }; let params = ZcashParamsWasmTable { sapling_spend_id: i as u8, - sapling_spend: sapling_spend_chunks[i].clone(), + sapling_spend: item.clone(), sapling_output, ticker: "z_params".to_string(), }; @@ -146,7 +146,7 @@ fn sapling_spend_to_chunks(sapling_spend: &[u8]) -> Vec> { let mut sapling_spend_chunks: Vec> = Vec::with_capacity(target_chunk_size); let mut start = 0; for i in 0..target_chunk_size { - let end = start + chunk_size + if i < remainder { 1 } else { 0 }; + let end = start + chunk_size + usize::from(i < remainder); // Extract the current chunk from the original vector sapling_spend_chunks.push(sapling_spend[start..end].to_vec()); // Move the start index to the next position diff --git a/mm2src/coins/z_coin/z_params/mod.rs b/mm2src/coins/z_coin/z_params/mod.rs index 8ef3c8a119..dfecace1dc 100644 --- a/mm2src/coins/z_coin/z_params/mod.rs +++ b/mm2src/coins/z_coin/z_params/mod.rs @@ -1,6 +1,7 @@ mod indexeddb; use blake2b_simd::State; +use common::log::info; pub use indexeddb::ZcashParamsWasmImpl; use mm2_err_handle::prelude::*; use mm2_net::wasm::http::FetchRequest; @@ -56,6 +57,7 @@ use wasm_bindgen_test::*; #[wasm_bindgen_test] async fn test_download_save_and_get_params() { register_wasm_log(); + info!("Testing download, save and get params"); let ctx = mm_ctx_with_custom_db(); let db = ZcashParamsWasmImpl::new(ctx).await.unwrap(); // download params @@ -66,6 +68,7 @@ async fn test_download_save_and_get_params() { let (sapling_spend_db, sapling_output_db) = db.get_params().await.unwrap(); assert_eq!(sapling_spend, sapling_spend_db); assert_eq!(sapling_output, sapling_output_db); + info!("Testing download, save and get params successful"); } #[wasm_bindgen_test] @@ -75,5 +78,5 @@ async fn test_check_for_no_params() { let db = ZcashParamsWasmImpl::new(ctx).await.unwrap(); // check for no params let check_params = db.check_params().await.unwrap(); - assert_eq!(false, check_params) + assert!(!check_params) } From 4f4f5c283c621118e719003ac5e2014c2015c798 Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 15 Nov 2023 22:09:00 +0100 Subject: [PATCH 48/68] minor changes Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index c13d584bbf..beac75c977 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -1043,7 +1043,9 @@ impl<'a> ZCoinBuilder<'a> { .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))? { // download params - let (sapling_spend, sapling_output) = download_parameters().await.unwrap(); + let (sapling_spend, sapling_output) = download_parameters() + .await + .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; // save params params_db .save_params(&sapling_spend, &sapling_output) From 84be05969b2247e9f24ee343dd50f3419838309c Mon Sep 17 00:00:00 2001 From: borngraced Date: Fri, 17 Nov 2023 17:52:33 +0100 Subject: [PATCH 49/68] fix conflicts Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 2 +- .../z_coin/storage/walletdb/wallet_sql_storage.rs | 4 ++-- mm2src/coins/z_coin/z_coin_errors.rs | 10 +--------- mm2src/coins/z_coin/z_rpc.rs | 5 ----- 4 files changed, 4 insertions(+), 17 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 1cc38210e7..2c1c07864a 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -1011,7 +1011,7 @@ impl<'a> ZCoinBuilder<'a> { let ticker = self.ticker.to_string(); BlockDbImpl::new(ctx, ticker, cache_db_path) - .map_err(|err| MmError::new(ZcoinClientInitError::ZcashDBError(err.to_string()))) + .map_err(|err| MmError::new(ZcoinClientInitError::ZcoinStorageError(err.to_string()))) .await } diff --git a/mm2src/coins/z_coin/storage/walletdb/wallet_sql_storage.rs b/mm2src/coins/z_coin/storage/walletdb/wallet_sql_storage.rs index 2d3d63b540..3a957d375f 100644 --- a/mm2src/coins/z_coin/storage/walletdb/wallet_sql_storage.rs +++ b/mm2src/coins/z_coin/storage/walletdb/wallet_sql_storage.rs @@ -26,14 +26,14 @@ pub async fn create_wallet_db( ) -> Result, MmError> { let db = async_blocking(move || { WalletDbAsync::for_path(wallet_db_path, consensus_params) - .map_to_mm(|err| ZcoinClientInitError::ZcashDBError(err.to_string())) + .map_to_mm(|err| ZcoinClientInitError::ZcoinStorageError(err.to_string())) }) .await?; let db_inner = db.inner(); async_blocking(move || { let db_inner = db_inner.lock().unwrap(); run_optimization_pragmas(db_inner.sql_conn()) - .map_to_mm(|err| ZcoinClientInitError::ZcashDBError(err.to_string())) + .map_to_mm(|err| ZcoinClientInitError::ZcoinStorageError(err.to_string())) }) .await?; diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index cb3a5ce1a8..2a7ebc0c4d 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -55,10 +55,6 @@ impl From for UpdateBlocksCacheErr { fn from(err: SqliteClientError) -> Self { UpdateBlocksCacheErr::ZcashDBError(err.to_string()) } } -impl From for UpdateBlocksCacheErr { - fn from(err: ZcoinStorageError) -> Self { UpdateBlocksCacheErr::ZcashDBError(err.to_string()) } -} - impl From for UpdateBlocksCacheErr { fn from(err: UtxoRpcError) -> Self { UpdateBlocksCacheErr::UtxoRpcError(err) } } @@ -83,17 +79,13 @@ pub enum ZcoinClientInitError { } impl From for ZcoinClientInitError { - fn from(err: ZcoinStorageError) -> Self { ZcoinClientInitError::ZcashDBError(err.to_string()) } + fn from(err: ZcoinStorageError) -> Self { ZcoinClientInitError::ZcoinStorageError(err.to_string()) } } impl From for ZcoinClientInitError { fn from(err: UpdateBlocksCacheErr) -> Self { ZcoinClientInitError::UpdateBlocksCacheErr(err) } } -impl From for ZcoinClientInitError { - fn from(err: ZcoinStorageError) -> Self { ZcoinClientInitError::ZcoinStorageError(err.to_string()) } -} - #[cfg(not(target_arch = "wasm32"))] impl From for ZcoinClientInitError { fn from(err: SqliteClientError) -> Self { ZcoinClientInitError::ZcoinStorageError(err.to_string()) } diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 401f6187d1..ec16fe8d7f 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -45,13 +45,8 @@ cfg_native!( use futures::compat::Future01CompatExt; use group::GroupEncoding; use http::Uri; - use prost::Message; - use std::convert::TryFrom; - use rpc::v1::types::{Bytes, H256 as H256Json}; use std::convert::TryInto; use std::num::TryFromIntError; - use std::pin::Pin; - use std::str::FromStr; use tonic::transport::{Channel, ClientTlsConfig}; use tonic::codegen::StdError; From dbc0e2f43ebf0c415d89e6b9850a0c2b243468e2 Mon Sep 17 00:00:00 2001 From: borngraced Date: Mon, 20 Nov 2023 23:31:09 +0100 Subject: [PATCH 50/68] impl TxBuilderSpawner to disabled blocking when generating tx for WASM Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 56 ++++++++++++++++++++++++---- mm2src/coins/z_coin/z_coin_errors.rs | 4 ++ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 2c1c07864a..e97ddcc00c 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -13,8 +13,6 @@ use crate::utxo::{sat_from_big_decimal, utxo_common, ActualTxFee, AdditionalTxDa BroadcastTxErr, FeePolicy, GetUtxoListOps, HistoryUtxoTx, HistoryUtxoTxMap, MatureUnspentList, RecentlySpentOutPointsGuard, UtxoActivationParams, UtxoAddressFormat, UtxoArc, UtxoCoinFields, UtxoCommonOps, UtxoRpcMode, UtxoTxBroadcastOps, UtxoTxGenerationOps, VerboseTransactionFrom}; -#[cfg(target_arch = "wasm32")] -use crate::z_coin::z_params::{download_parameters, ZcashParamsWasmImpl}; use crate::TxFeeDetails; use crate::{BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, CoinFutSpawner, ConfirmPaymentInput, FeeApproxStage, FoundSwapTxSpend, HistorySyncState, MakerSwapTakerCoin, MarketCoinOps, MmCoin, MmCoinEnum, @@ -67,8 +65,7 @@ use z_rpc::{SaplingSyncConnector, SaplingSyncGuard}; use zcash_client_backend::encoding::{decode_payment_address, encode_extended_spending_key, encode_payment_address}; use zcash_client_backend::wallet::{AccountId, SpendableNote}; use zcash_extras::WalletRead; -use zcash_primitives::consensus; -use zcash_primitives::consensus::{BlockHeight, NetworkUpgrade, Parameters, H0}; +use zcash_primitives::consensus::{BlockHeight, BranchId, NetworkUpgrade, Parameters, H0}; use zcash_primitives::memo::MemoBytes; use zcash_primitives::sapling::keys::OutgoingViewingKey; use zcash_primitives::sapling::note_encryption::try_sapling_output_recovery; @@ -89,7 +86,6 @@ pub use z_rpc::{FirstSyncBlock, SyncStatus}; cfg_native!( use crate::utxo::utxo_common::{addresses_from_script, big_decimal_from_sat}; - use common::{async_blocking, sha256_digest, calc_total_pages, PagingOptionsEnum}; use db_common::sqlite::offset_by_id; use db_common::sqlite::rusqlite::{Error as SqlError, Row}; @@ -100,6 +96,13 @@ cfg_native!( use z_rpc::{init_native_client}; ); +cfg_wasm32!( + use crate::z_coin::z_params::{download_parameters, ZcashParamsWasmImpl}; + use futures::channel::oneshot; + use rand::rngs::OsRng; + use zcash_primitives::transaction::builder::TransactionMetadata; +); + #[allow(unused)] mod z_coin_errors; use crate::z_coin::storage::{BlockDbImpl, WalletDbShared}; pub use z_coin_errors::*; @@ -489,11 +492,14 @@ impl ZCoin { #[cfg(not(target_arch = "wasm32"))] let (tx, _) = async_blocking({ let prover = self.z_fields.z_tx_prover.clone(); - move || tx_builder.build(consensus::BranchId::Sapling, prover.as_ref()) + move || tx_builder.build(BranchId::Sapling, prover.as_ref()) }) .await?; + #[cfg(target_arch = "wasm32")] - let (tx, _) = tx_builder.build(consensus::BranchId::Sapling, self.z_fields.z_tx_prover.clone().as_ref())?; + let (tx, _) = + TxBuilderSpawner::request_tx_result(tx_builder, BranchId::Sapling, self.z_fields.z_tx_prover.clone()) + .await?; let additional_data = AdditionalTxData { received_by_me, @@ -758,6 +764,42 @@ impl AsRef for ZCoin { fn as_ref(&self) -> &UtxoCoinFields { &self.utxo_arc } } +#[cfg(target_arch = "wasm32")] +struct TxBuilderSpawner; + +#[cfg(target_arch = "wasm32")] +impl TxBuilderSpawner { + fn spawn_build_tx( + builder: ZTxBuilder<'static, ZcoinConsensusParams, OsRng>, + branch_id: BranchId, + prover: Arc, + sender: oneshot::Sender< + MmResult<(zcash_primitives::transaction::Transaction, TransactionMetadata), GenTxError>, + >, + ) { + let fut = async move { + let build = builder + .build(branch_id, prover.as_ref()) + .map_to_mm(GenTxError::TxBuilderError); + sender.send(build).ok(); + }; + + common::executor::spawn_local(fut) + } + + async fn request_tx_result( + builder: ZTxBuilder<'static, ZcoinConsensusParams, OsRng>, + branch_id: BranchId, + prover: Arc, + ) -> MmResult<(zcash_primitives::transaction::Transaction, TransactionMetadata), GenTxError> { + let (tx, rx) = oneshot::channel(); + Self::spawn_build_tx(builder, branch_id, prover, tx); + + rx.await + .map_to_mm(|_| GenTxError::Internal("Spawned future has been canceled".to_owned()))? + } +} + /// SyncStartPoint represents the starting point for synchronizing a wallet's blocks and transaction history. /// This can be specified as a date, a block height, or starting from the earliest available data. #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index 2a7ebc0c4d..b0744825e4 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -129,6 +129,8 @@ pub enum GenTxError { LightClientErr(String), FailedToCreateNote, SpendableNotesError(String), + #[cfg(target_arch = "wasm32")] + Internal(String), } impl From for GenTxError { @@ -176,6 +178,8 @@ impl From for WithdrawError { | GenTxError::LightClientErr(_) | GenTxError::SpendableNotesError(_) | GenTxError::FailedToCreateNote => WithdrawError::InternalError(gen_tx.to_string()), + #[cfg(target_arch = "wasm32")] + GenTxError::Internal(_) => WithdrawError::InternalError(gen_tx.to_string()), } } } From 6b79e2f0f81341eae8e7dfad85582c1fdc17a401 Mon Sep 17 00:00:00 2001 From: borngraced Date: Tue, 21 Nov 2023 01:59:21 +0100 Subject: [PATCH 51/68] use spawn_local_abortable Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 46 ++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index e97ddcc00c..1cf8dbb75e 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -98,6 +98,7 @@ cfg_native!( cfg_wasm32!( use crate::z_coin::z_params::{download_parameters, ZcashParamsWasmImpl}; + use common::executor::AbortOnDropHandle; use futures::channel::oneshot; use rand::rngs::OsRng; use zcash_primitives::transaction::builder::TransactionMetadata; @@ -499,7 +500,8 @@ impl ZCoin { #[cfg(target_arch = "wasm32")] let (tx, _) = TxBuilderSpawner::request_tx_result(tx_builder, BranchId::Sapling, self.z_fields.z_tx_prover.clone()) - .await?; + .await? + .tx_result?; let additional_data = AdditionalTxData { received_by_me, @@ -765,7 +767,14 @@ impl AsRef for ZCoin { } #[cfg(target_arch = "wasm32")] -struct TxBuilderSpawner; +type TxResult = MmResult<(zcash_primitives::transaction::Transaction, TransactionMetadata), GenTxError>; + +#[cfg(target_arch = "wasm32")] +/// Spawns an asynchronous task to build a transaction and sends the result through a oneshot channel. +struct TxBuilderSpawner { + pub tx_result: TxResult, + _abort_handle: AbortOnDropHandle, +} #[cfg(target_arch = "wasm32")] impl TxBuilderSpawner { @@ -773,30 +782,37 @@ impl TxBuilderSpawner { builder: ZTxBuilder<'static, ZcoinConsensusParams, OsRng>, branch_id: BranchId, prover: Arc, - sender: oneshot::Sender< - MmResult<(zcash_primitives::transaction::Transaction, TransactionMetadata), GenTxError>, - >, - ) { + sender: oneshot::Sender, + ) -> AbortOnDropHandle { let fut = async move { - let build = builder - .build(branch_id, prover.as_ref()) - .map_to_mm(GenTxError::TxBuilderError); - sender.send(build).ok(); + sender + .send( + builder + .build(branch_id, prover.as_ref()) + .map_to_mm(GenTxError::TxBuilderError), + ) + .ok(); }; - common::executor::spawn_local(fut) + common::executor::spawn_local_abortable(fut) } + /// Requests a transaction asynchronously using the provided builder, branch ID, and prover. async fn request_tx_result( builder: ZTxBuilder<'static, ZcoinConsensusParams, OsRng>, branch_id: BranchId, prover: Arc, - ) -> MmResult<(zcash_primitives::transaction::Transaction, TransactionMetadata), GenTxError> { + ) -> MmResult { + // Create a oneshot channel for communication between the spawned task and this function let (tx, rx) = oneshot::channel(); - Self::spawn_build_tx(builder, branch_id, prover, tx); + let abort_handle = Self::spawn_build_tx(builder, branch_id, prover, tx); - rx.await - .map_to_mm(|_| GenTxError::Internal("Spawned future has been canceled".to_owned()))? + Ok(Self { + tx_result: rx + .await + .map_to_mm(|_| GenTxError::Internal("Spawned future has been canceled".to_owned()))?, + _abort_handle: abort_handle, + }) } } From 47b1fbfae7ddf7b1f59bf8c65cbf468cfcc38439 Mon Sep 17 00:00:00 2001 From: borngraced Date: Wed, 22 Nov 2023 00:03:06 +0100 Subject: [PATCH 52/68] update z_params impl Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 10 ++---- mm2src/coins/z_coin/z_params/indexeddb.rs | 41 ++++++++++++++++------- mm2src/coins/z_coin/z_params/mod.rs | 17 ++++------ 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 1cf8dbb75e..9cc1202970 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -97,7 +97,7 @@ cfg_native!( ); cfg_wasm32!( - use crate::z_coin::z_params::{download_parameters, ZcashParamsWasmImpl}; + use crate::z_coin::z_params::ZcashParamsWasmImpl; use common::executor::AbortOnDropHandle; use futures::channel::oneshot; use rand::rngs::OsRng; @@ -1102,13 +1102,9 @@ impl<'a> ZCoinBuilder<'a> { .await .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))? { - // download params - let (sapling_spend, sapling_output) = download_parameters() - .await - .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; // save params - params_db - .save_params(&sapling_spend, &sapling_output) + let (sapling_spend, sapling_output) = params_db + .download_and_save_params() .await .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; Ok(LocalTxProver::from_bytes(&sapling_spend[..], &sapling_output[..])) diff --git a/mm2src/coins/z_coin/z_params/indexeddb.rs b/mm2src/coins/z_coin/z_params/indexeddb.rs index d974e1658a..0d1b0aa8c8 100644 --- a/mm2src/coins/z_coin/z_params/indexeddb.rs +++ b/mm2src/coins/z_coin/z_params/indexeddb.rs @@ -76,22 +76,23 @@ impl ZcashParamsWasmImpl { .mm_err(|err| ZcoinStorageError::DbError(err.to_string())) } - pub async fn save_params(&self, sapling_spend: &[u8], sapling_output: &[u8]) -> MmResult<(), ZcoinStorageError> { + pub async fn save_params( + &self, + sapling_spend_id: u8, + sapling_spend: &[u8], + sapling_output: &[u8], + ) -> MmResult<(), ZcoinStorageError> { let locked_db = self.lock_db().await?; let db_transaction = locked_db.get_inner().transaction().await?; let params_db = db_transaction.table::().await?; + let params = ZcashParamsWasmTable { + sapling_spend_id, + sapling_spend: sapling_spend.to_vec(), + sapling_output: sapling_output.to_vec(), + ticker: "z_params".to_string(), + }; - let sapling_spend_chunks = sapling_spend_to_chunks(sapling_spend); - for (i, item) in sapling_spend_chunks.iter().enumerate() { - let sapling_output = if i > 0 { vec![] } else { sapling_output.to_vec() }; - let params = ZcashParamsWasmTable { - sapling_spend_id: i as u8, - sapling_spend: item.clone(), - sapling_output, - ticker: "z_params".to_string(), - }; - params_db.add_item(¶ms).await?; - } + params_db.add_item(¶ms).await?; Ok(()) } @@ -134,9 +135,23 @@ impl ZcashParamsWasmImpl { Ok((sapling_spend, sapling_output.clone())) } + + pub async fn download_and_save_params(&self) -> MmResult<(Vec, Vec), ZcoinStorageError> { + let (sapling_spend, sapling_output) = super::download_parameters().await.unwrap(); + let spends = sapling_spend_to_chunks(&sapling_spend); + for (i, spend) in spends.into_iter().enumerate() { + if i == 0 { + self.save_params(i as u8, &spend, &sapling_output).await? + } else { + self.save_params(i as u8, &spend, &[]).await? + } + } + + Ok((sapling_spend, sapling_output)) + } } -fn sapling_spend_to_chunks(sapling_spend: &[u8]) -> Vec> { +pub fn sapling_spend_to_chunks(sapling_spend: &[u8]) -> Vec> { // Set the target chunk size let target_chunk_size = 12; // Calculate the target size for each chunk diff --git a/mm2src/coins/z_coin/z_params/mod.rs b/mm2src/coins/z_coin/z_params/mod.rs index dfecace1dc..dd45acb9e7 100644 --- a/mm2src/coins/z_coin/z_params/mod.rs +++ b/mm2src/coins/z_coin/z_params/mod.rs @@ -1,10 +1,14 @@ mod indexeddb; +pub use indexeddb::{sapling_spend_to_chunks, ZcashParamsWasmImpl}; use blake2b_simd::State; use common::log::info; -pub use indexeddb::ZcashParamsWasmImpl; +use common::log::wasm_log::register_wasm_log; +use mm2_err_handle::prelude::MmResult; use mm2_err_handle::prelude::*; use mm2_net::wasm::http::FetchRequest; +use mm2_test_helpers::for_tests::mm_ctx_with_custom_db; +use wasm_bindgen_test::*; const DOWNLOAD_URL: &str = "https://komodoplatform.com/downloads"; const SAPLING_SPEND_NAME: &str = "sapling-spend.params"; @@ -42,28 +46,21 @@ async fn fetch_params(name: &str, expected_hash: &str) -> MmResult, Zcas Ok(file) } -pub async fn download_parameters() -> MmResult<(Vec, Vec), ZcashParamsBytesError> { +pub(crate) async fn download_parameters() -> MmResult<(Vec, Vec), ZcashParamsBytesError> { Ok(( fetch_params(SAPLING_SPEND_NAME, SAPLING_SPEND_HASH).await?, fetch_params(SAPLING_OUTPUT_NAME, SAPLING_OUTPUT_HASH).await?, )) } -use common::log::wasm_log::register_wasm_log; -use mm2_err_handle::prelude::MmResult; -use mm2_test_helpers::for_tests::mm_ctx_with_custom_db; -use wasm_bindgen_test::*; - #[wasm_bindgen_test] async fn test_download_save_and_get_params() { register_wasm_log(); info!("Testing download, save and get params"); let ctx = mm_ctx_with_custom_db(); let db = ZcashParamsWasmImpl::new(ctx).await.unwrap(); - // download params - let (sapling_spend, sapling_output) = download_parameters().await.unwrap(); // save params - db.save_params(&sapling_spend, &sapling_output).await.unwrap(); + let (sapling_spend, sapling_output) = db.download_and_save_params().await.unwrap(); // get params let (sapling_spend_db, sapling_output_db) = db.get_params().await.unwrap(); assert_eq!(sapling_spend, sapling_spend_db); From 107aed215326397b180a3edb557b0aeace82eb48 Mon Sep 17 00:00:00 2001 From: borngraced Date: Mon, 27 Nov 2023 07:07:25 +0100 Subject: [PATCH 53/68] fix merge conflicts Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 8c4d1d5c19..a901b30ec9 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -9,10 +9,10 @@ use crate::utxo::utxo_builder::{UtxoCoinBuilder, UtxoCoinBuilderCommonOps, UtxoF UtxoFieldsWithHardwareWalletBuilder, UtxoFieldsWithIguanaSecretBuilder}; use crate::utxo::utxo_common::{big_decimal_from_sat_unsigned, payment_script}; use crate::utxo::UtxoFeeDetails; -use crate::utxo::{utxo_common, ActualTxFee, AdditionalTxData, AddrFromStrError, Address, BroadcastTxErr, FeePolicy, - GetUtxoListOps, HistoryUtxoTx, HistoryUtxoTxMap, MatureUnspentList, RecentlySpentOutPointsGuard, - UtxoActivationParams, UtxoAddressFormat, UtxoArc, UtxoCoinFields, UtxoCommonOps, UtxoRpcMode, - UtxoTxBroadcastOps, UtxoTxGenerationOps, VerboseTransactionFrom}; +use crate::utxo::{sat_from_big_decimal, utxo_common, ActualTxFee, AdditionalTxData, AddrFromStrError, Address, + BroadcastTxErr, FeePolicy, GetUtxoListOps, HistoryUtxoTx, HistoryUtxoTxMap, MatureUnspentList, + RecentlySpentOutPointsGuard, UtxoActivationParams, UtxoAddressFormat, UtxoArc, UtxoCoinFields, + UtxoCommonOps, UtxoRpcMode, UtxoTxBroadcastOps, UtxoTxGenerationOps, VerboseTransactionFrom}; use crate::TxFeeDetails; use crate::{BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, CoinFutSpawner, ConfirmPaymentInput, DexFee, FeeApproxStage, FoundSwapTxSpend, HistorySyncState, MakerSwapTakerCoin, MarketCoinOps, MmCoin, @@ -85,8 +85,6 @@ use z_rpc::init_light_client; pub use z_rpc::{FirstSyncBlock, SyncStatus}; cfg_native!( - use crate::{NumConversError, TransactionDetails, TxFeeDetails}; - use crate::utxo::{UtxoFeeDetails, sat_from_big_decimal}; use crate::utxo::utxo_common::{addresses_from_script, big_decimal_from_sat}; use common::{async_blocking, sha256_digest, calc_total_pages, PagingOptionsEnum}; use db_common::sqlite::offset_by_id; From e4689909280bb0fbede209c2a2fa4986720e6e7d Mon Sep 17 00:00:00 2001 From: borngraced Date: Mon, 27 Nov 2023 11:05:32 +0100 Subject: [PATCH 54/68] fix review notes Signed-off-by: borngraced --- mm2src/coins/z_coin/z_params/indexeddb.rs | 34 +++++++++++++---------- mm2src/coins/z_coin/z_params/mod.rs | 10 +++++-- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/mm2src/coins/z_coin/z_params/indexeddb.rs b/mm2src/coins/z_coin/z_params/indexeddb.rs index 0d1b0aa8c8..03fa1555d7 100644 --- a/mm2src/coins/z_coin/z_params/indexeddb.rs +++ b/mm2src/coins/z_coin/z_params/indexeddb.rs @@ -7,11 +7,13 @@ use mm2_err_handle::prelude::*; const DB_NAME: &str = "z_params"; const DB_VERSION: u32 = 1; +const TARGET_SPEND_CHUNKS: usize = 12; -pub type ZcashParamsWasmRes = MmResult; -pub type ZcashParamsInnerLocked<'a> = DbLocked<'a, ZcashParamsWasmInner>; +pub(crate) type ZcashParamsWasmRes = MmResult; +pub(crate) type ZcashParamsInnerLocked<'a> = DbLocked<'a, ZcashParamsWasmInner>; -// indexeddb max data =267386880 bytes to save, so we need to split sapling_spend +/// Since sapling_spend data way is greater than indexeddb max_data(267386880) bytes to save, we need to split +/// sapling_spend and insert to db multiple times with index(sapling_spend_id) #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ZcashParamsWasmTable { sapling_spend_id: u8, @@ -76,6 +78,7 @@ impl ZcashParamsWasmImpl { .mm_err(|err| ZcoinStorageError::DbError(err.to_string())) } + /// Given sapling_spend, sapling_output and sapling_spend_id, save to indexeddb storage. pub async fn save_params( &self, sapling_spend_id: u8, @@ -89,7 +92,7 @@ impl ZcashParamsWasmImpl { sapling_spend_id, sapling_spend: sapling_spend.to_vec(), sapling_output: sapling_output.to_vec(), - ticker: "z_params".to_string(), + ticker: DB_NAME.to_string(), }; params_db.add_item(¶ms).await?; @@ -97,6 +100,7 @@ impl ZcashParamsWasmImpl { Ok(()) } + /// Check if z_params is already save to storage previously. pub async fn check_params(&self) -> MmResult { let locked_db = self.lock_db().await?; let db_transaction = locked_db.get_inner().transaction().await?; @@ -104,7 +108,7 @@ impl ZcashParamsWasmImpl { let maybe_param = params_db .cursor_builder() - .only("ticker", "z_params")? + .only("ticker", DB_NAME)? .open_cursor("ticker") .await? .next() @@ -113,13 +117,14 @@ impl ZcashParamsWasmImpl { Ok(maybe_param.is_some()) } + /// Get z_params from storage. pub async fn get_params(&self) -> MmResult<(Vec, Vec), ZcoinStorageError> { let locked_db = self.lock_db().await?; let db_transaction = locked_db.get_inner().transaction().await?; let params_db = db_transaction.table::().await?; let mut maybe_params = params_db .cursor_builder() - .only("ticker", "z_params")? + .only("ticker", DB_NAME)? .open_cursor("ticker") .await?; @@ -133,9 +138,10 @@ impl ZcashParamsWasmImpl { } } - Ok((sapling_spend, sapling_output.clone())) + Ok((sapling_spend, sapling_output)) } + /// Download and save z_params to storage. pub async fn download_and_save_params(&self) -> MmResult<(Vec, Vec), ZcoinStorageError> { let (sapling_spend, sapling_output) = super::download_parameters().await.unwrap(); let spends = sapling_spend_to_chunks(&sapling_spend); @@ -151,16 +157,16 @@ impl ZcashParamsWasmImpl { } } -pub fn sapling_spend_to_chunks(sapling_spend: &[u8]) -> Vec> { - // Set the target chunk size - let target_chunk_size = 12; +/// Since sapling_spend data way is greater than indexeddb max_data(267386880) bytes to save, we need to split +/// sapling_spend into chunks of 12 and insert to db multiple times with index(sapling_spend_id) +fn sapling_spend_to_chunks(sapling_spend: &[u8]) -> Vec> { // Calculate the target size for each chunk - let chunk_size = sapling_spend.len() / target_chunk_size; + let chunk_size = sapling_spend.len() / TARGET_SPEND_CHUNKS; // Calculate the remainder for cases when the length is not perfectly divisible - let remainder = sapling_spend.len() % target_chunk_size; - let mut sapling_spend_chunks: Vec> = Vec::with_capacity(target_chunk_size); + let remainder = sapling_spend.len() % TARGET_SPEND_CHUNKS; + let mut sapling_spend_chunks: Vec> = Vec::with_capacity(TARGET_SPEND_CHUNKS); let mut start = 0; - for i in 0..target_chunk_size { + for i in 0..TARGET_SPEND_CHUNKS { let end = start + chunk_size + usize::from(i < remainder); // Extract the current chunk from the original vector sapling_spend_chunks.push(sapling_spend[start..end].to_vec()); diff --git a/mm2src/coins/z_coin/z_params/mod.rs b/mm2src/coins/z_coin/z_params/mod.rs index dd45acb9e7..b857a54b98 100644 --- a/mm2src/coins/z_coin/z_params/mod.rs +++ b/mm2src/coins/z_coin/z_params/mod.rs @@ -1,5 +1,5 @@ mod indexeddb; -pub use indexeddb::{sapling_spend_to_chunks, ZcashParamsWasmImpl}; +pub use indexeddb::ZcashParamsWasmImpl; use blake2b_simd::State; use common::log::info; @@ -21,6 +21,7 @@ pub enum ZcashParamsBytesError { IO(String), } +/// Download, validate and return z_params from given `DOWNLOAD_URL` async fn fetch_params(name: &str, expected_hash: &str) -> MmResult, ZcashParamsBytesError> { let (status, file) = FetchRequest::get(&format!("{DOWNLOAD_URL}/{name}")) .cors() @@ -28,7 +29,12 @@ async fn fetch_params(name: &str, expected_hash: &str) -> MmResult, Zcas .await .mm_err(|err| ZcashParamsBytesError::IO(err.to_string()))?; - assert_eq!(200, status); + if status != 200 { + return MmError::err(ZcashParamsBytesError::IO(format!( + "Expected status 200, got {} for {}", + status, name + ))); + } let hash = State::new().update(&file).finalize().to_hex(); // Verify parameter file hash. From f2995bcf8d6a3df42552e4e1d7570a7813365ab4 Mon Sep 17 00:00:00 2001 From: borngraced Date: Tue, 28 Nov 2023 07:41:24 +0100 Subject: [PATCH 55/68] make struct and fn pub(crate) Signed-off-by: borngraced --- mm2src/coins/z_coin/z_params/indexeddb.rs | 18 +++++++++--------- mm2src/coins/z_coin/z_params/mod.rs | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/mm2src/coins/z_coin/z_params/indexeddb.rs b/mm2src/coins/z_coin/z_params/indexeddb.rs index 03fa1555d7..a7ff09eb03 100644 --- a/mm2src/coins/z_coin/z_params/indexeddb.rs +++ b/mm2src/coins/z_coin/z_params/indexeddb.rs @@ -15,7 +15,7 @@ pub(crate) type ZcashParamsInnerLocked<'a> = DbLocked<'a, ZcashParamsWasmInner>; /// Since sapling_spend data way is greater than indexeddb max_data(267386880) bytes to save, we need to split /// sapling_spend and insert to db multiple times with index(sapling_spend_id) #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct ZcashParamsWasmTable { +struct ZcashParamsWasmTable { sapling_spend_id: u8, sapling_spend: Vec, sapling_output: Vec, @@ -23,7 +23,7 @@ pub struct ZcashParamsWasmTable { } impl ZcashParamsWasmTable { - pub const SPEND_OUTPUT_INDEX: &str = "sapling_spend_sapling_output_index"; + const SPEND_OUTPUT_INDEX: &str = "sapling_spend_sapling_output_index"; } impl TableSignature for ZcashParamsWasmTable { @@ -60,14 +60,14 @@ impl DbInstance for ZcashParamsWasmInner { } impl ZcashParamsWasmInner { - pub fn get_inner(&self) -> &IndexedDb { &self.0 } + pub(crate) fn get_inner(&self) -> &IndexedDb { &self.0 } } #[derive(Clone)] -pub struct ZcashParamsWasmImpl(SharedDb); +pub(crate) struct ZcashParamsWasmImpl(SharedDb); impl ZcashParamsWasmImpl { - pub async fn new(ctx: MmArc) -> MmResult { + pub(crate) async fn new(ctx: MmArc) -> MmResult { Ok(Self(ConstructibleDb::new(&ctx).into_shared())) } @@ -79,7 +79,7 @@ impl ZcashParamsWasmImpl { } /// Given sapling_spend, sapling_output and sapling_spend_id, save to indexeddb storage. - pub async fn save_params( + pub(crate) async fn save_params( &self, sapling_spend_id: u8, sapling_spend: &[u8], @@ -101,7 +101,7 @@ impl ZcashParamsWasmImpl { } /// Check if z_params is already save to storage previously. - pub async fn check_params(&self) -> MmResult { + pub(crate) async fn check_params(&self) -> MmResult { let locked_db = self.lock_db().await?; let db_transaction = locked_db.get_inner().transaction().await?; let params_db = db_transaction.table::().await?; @@ -118,7 +118,7 @@ impl ZcashParamsWasmImpl { } /// Get z_params from storage. - pub async fn get_params(&self) -> MmResult<(Vec, Vec), ZcoinStorageError> { + pub(crate) async fn get_params(&self) -> MmResult<(Vec, Vec), ZcoinStorageError> { let locked_db = self.lock_db().await?; let db_transaction = locked_db.get_inner().transaction().await?; let params_db = db_transaction.table::().await?; @@ -142,7 +142,7 @@ impl ZcashParamsWasmImpl { } /// Download and save z_params to storage. - pub async fn download_and_save_params(&self) -> MmResult<(Vec, Vec), ZcoinStorageError> { + pub(crate) async fn download_and_save_params(&self) -> MmResult<(Vec, Vec), ZcoinStorageError> { let (sapling_spend, sapling_output) = super::download_parameters().await.unwrap(); let spends = sapling_spend_to_chunks(&sapling_spend); for (i, spend) in spends.into_iter().enumerate() { diff --git a/mm2src/coins/z_coin/z_params/mod.rs b/mm2src/coins/z_coin/z_params/mod.rs index b857a54b98..c888875732 100644 --- a/mm2src/coins/z_coin/z_params/mod.rs +++ b/mm2src/coins/z_coin/z_params/mod.rs @@ -1,5 +1,5 @@ mod indexeddb; -pub use indexeddb::ZcashParamsWasmImpl; +pub(crate) use indexeddb::ZcashParamsWasmImpl; use blake2b_simd::State; use common::log::info; From a6ca1c74ea4454abd8e1b8cb52d24befa638b39d Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 30 Nov 2023 15:57:28 +0100 Subject: [PATCH 56/68] fix review notes Signed-off-by: borngraced --- mm2src/coins/z_coin/z_coin_errors.rs | 2 ++ mm2src/coins/z_coin/z_params/indexeddb.rs | 27 ++++++++++++++--------- mm2src/coins/z_coin/z_params/mod.rs | 15 +++++++------ 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index b0744825e4..a2adab422f 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -421,6 +421,8 @@ pub enum ZcoinStorageError { ChainError(String), InternalError(String), NotSupported(String), + #[cfg(target_arch = "wasm32")] + ZcashParamsError(String), } impl From for ZcoinStorageError { diff --git a/mm2src/coins/z_coin/z_params/indexeddb.rs b/mm2src/coins/z_coin/z_params/indexeddb.rs index a7ff09eb03..37746736f1 100644 --- a/mm2src/coins/z_coin/z_params/indexeddb.rs +++ b/mm2src/coins/z_coin/z_params/indexeddb.rs @@ -42,7 +42,7 @@ impl TableSignature for ZcashParamsWasmTable { } } -pub struct ZcashParamsWasmInner(IndexedDb); +pub(crate) struct ZcashParamsWasmInner(IndexedDb); #[async_trait::async_trait] impl DbInstance for ZcashParamsWasmInner { @@ -143,13 +143,20 @@ impl ZcashParamsWasmImpl { /// Download and save z_params to storage. pub(crate) async fn download_and_save_params(&self) -> MmResult<(Vec, Vec), ZcoinStorageError> { - let (sapling_spend, sapling_output) = super::download_parameters().await.unwrap(); + let (sapling_spend, sapling_output) = super::download_parameters() + .await + .mm_err(|err| ZcoinStorageError::ZcashParamsError(err.to_string()))?; let spends = sapling_spend_to_chunks(&sapling_spend); - for (i, spend) in spends.into_iter().enumerate() { - if i == 0 { - self.save_params(i as u8, &spend, &sapling_output).await? - } else { - self.save_params(i as u8, &spend, &[]).await? + + if sapling_spend.len() <= sapling_output.len() { + self.save_params(0, &sapling_spend, &sapling_output).await? + } else { + for (i, spend) in spends.into_iter().enumerate() { + if i == 0 { + self.save_params(i as u8, spend, &sapling_output).await? + } else { + self.save_params(i as u8, spend, &[]).await? + } } } @@ -159,17 +166,17 @@ impl ZcashParamsWasmImpl { /// Since sapling_spend data way is greater than indexeddb max_data(267386880) bytes to save, we need to split /// sapling_spend into chunks of 12 and insert to db multiple times with index(sapling_spend_id) -fn sapling_spend_to_chunks(sapling_spend: &[u8]) -> Vec> { +fn sapling_spend_to_chunks(sapling_spend: &[u8]) -> Vec<&[u8]> { // Calculate the target size for each chunk let chunk_size = sapling_spend.len() / TARGET_SPEND_CHUNKS; // Calculate the remainder for cases when the length is not perfectly divisible let remainder = sapling_spend.len() % TARGET_SPEND_CHUNKS; - let mut sapling_spend_chunks: Vec> = Vec::with_capacity(TARGET_SPEND_CHUNKS); + let mut sapling_spend_chunks = Vec::with_capacity(TARGET_SPEND_CHUNKS); let mut start = 0; for i in 0..TARGET_SPEND_CHUNKS { let end = start + chunk_size + usize::from(i < remainder); // Extract the current chunk from the original vector - sapling_spend_chunks.push(sapling_spend[start..end].to_vec()); + sapling_spend_chunks.push(&sapling_spend[start..end]); // Move the start index to the next position start = end; } diff --git a/mm2src/coins/z_coin/z_params/mod.rs b/mm2src/coins/z_coin/z_params/mod.rs index c888875732..990886faaf 100644 --- a/mm2src/coins/z_coin/z_params/mod.rs +++ b/mm2src/coins/z_coin/z_params/mod.rs @@ -17,20 +17,21 @@ const SAPLING_SPEND_HASH: &str = "8270785a1a0d0bc77196f000ee6d221c9c9894f55307bd const SAPLING_OUTPUT_HASH: &str = "657e3d38dbb5cb5e7dd2970e8b03d69b4787dd907285b5a7f0790dcc8072f60bf593b32cc2d1c030e00ff5ae64bf84c5c3beb84ddc841d48264b4a171744d028"; #[derive(Debug, derive_more::Display)] -pub enum ZcashParamsBytesError { - IO(String), +pub enum ZcashParamsError { + Transport(String), + ValidationError(String), } /// Download, validate and return z_params from given `DOWNLOAD_URL` -async fn fetch_params(name: &str, expected_hash: &str) -> MmResult, ZcashParamsBytesError> { +async fn fetch_params(name: &str, expected_hash: &str) -> MmResult, ZcashParamsError> { let (status, file) = FetchRequest::get(&format!("{DOWNLOAD_URL}/{name}")) .cors() .request_array() .await - .mm_err(|err| ZcashParamsBytesError::IO(err.to_string()))?; + .mm_err(|err| ZcashParamsError::Transport(err.to_string()))?; if status != 200 { - return MmError::err(ZcashParamsBytesError::IO(format!( + return MmError::err(ZcashParamsError::Transport(format!( "Expected status 200, got {} for {}", status, name ))); @@ -39,7 +40,7 @@ async fn fetch_params(name: &str, expected_hash: &str) -> MmResult, Zcas let hash = State::new().update(&file).finalize().to_hex(); // Verify parameter file hash. if &hash != expected_hash { - return Err(ZcashParamsBytesError::IO(format!( + return Err(ZcashParamsError::ValidationError(format!( "{} failed validation (expected: {}, actual: {}, fetched {} bytes)", name, expected_hash, @@ -52,7 +53,7 @@ async fn fetch_params(name: &str, expected_hash: &str) -> MmResult, Zcas Ok(file) } -pub(crate) async fn download_parameters() -> MmResult<(Vec, Vec), ZcashParamsBytesError> { +pub(crate) async fn download_parameters() -> MmResult<(Vec, Vec), ZcashParamsError> { Ok(( fetch_params(SAPLING_SPEND_NAME, SAPLING_SPEND_HASH).await?, fetch_params(SAPLING_OUTPUT_NAME, SAPLING_OUTPUT_HASH).await?, From 2eecc9fda0395bd0edf00c725a7fcca8de2a8637 Mon Sep 17 00:00:00 2001 From: borngraced Date: Mon, 4 Dec 2023 08:42:05 +0100 Subject: [PATCH 57/68] fix review notes Signed-off-by: borngraced --- mm2src/coins/z_coin/z_params/indexeddb.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/mm2src/coins/z_coin/z_params/indexeddb.rs b/mm2src/coins/z_coin/z_params/indexeddb.rs index 37746736f1..919625a8e4 100644 --- a/mm2src/coins/z_coin/z_params/indexeddb.rs +++ b/mm2src/coins/z_coin/z_params/indexeddb.rs @@ -5,6 +5,7 @@ use mm2_db::indexed_db::{ConstructibleDb, DbIdentifier, DbInstance, DbLocked, Db InitDbResult, OnUpgradeResult, SharedDb, TableSignature}; use mm2_err_handle::prelude::*; +const CHAIN: &str = "z_coin"; const DB_NAME: &str = "z_params"; const DB_VERSION: u32 = 1; const TARGET_SPEND_CHUNKS: usize = 12; @@ -92,7 +93,7 @@ impl ZcashParamsWasmImpl { sapling_spend_id, sapling_spend: sapling_spend.to_vec(), sapling_output: sapling_output.to_vec(), - ticker: DB_NAME.to_string(), + ticker: CHAIN.to_string(), }; params_db.add_item(¶ms).await?; @@ -108,7 +109,7 @@ impl ZcashParamsWasmImpl { let maybe_param = params_db .cursor_builder() - .only("ticker", DB_NAME)? + .only("ticker", CHAIN)? .open_cursor("ticker") .await? .next() @@ -124,7 +125,7 @@ impl ZcashParamsWasmImpl { let params_db = db_transaction.table::().await?; let mut maybe_params = params_db .cursor_builder() - .only("ticker", DB_NAME)? + .only("ticker", CHAIN)? .open_cursor("ticker") .await?; @@ -146,16 +147,16 @@ impl ZcashParamsWasmImpl { let (sapling_spend, sapling_output) = super::download_parameters() .await .mm_err(|err| ZcoinStorageError::ZcashParamsError(err.to_string()))?; - let spends = sapling_spend_to_chunks(&sapling_spend); if sapling_spend.len() <= sapling_output.len() { self.save_params(0, &sapling_spend, &sapling_output).await? } else { - for (i, spend) in spends.into_iter().enumerate() { - if i == 0 { - self.save_params(i as u8, spend, &sapling_output).await? - } else { - self.save_params(i as u8, spend, &[]).await? + let spends = sapling_spend_to_chunks(&sapling_spend); + if let Some((first_spend, remaining_spends)) = spends.split_first() { + self.save_params(0, first_spend, &sapling_output).await?; + + for (i, spend) in remaining_spends.iter().enumerate() { + self.save_params((i + 1) as u8, spend, &[]).await?; } } } From 93e76c5897482c826c77627bff3dbe9bed44ba04 Mon Sep 17 00:00:00 2001 From: borngraced Date: Tue, 5 Dec 2023 15:24:41 +0100 Subject: [PATCH 58/68] test ccursor forget Signed-off-by: borngraced --- mm2src/mm2_db/src/indexed_db/drivers/cursor/cursor.rs | 4 ++-- mm2src/mm2_db/src/indexed_db/indexed_cursor.rs | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mm2src/mm2_db/src/indexed_db/drivers/cursor/cursor.rs b/mm2src/mm2_db/src/indexed_db/drivers/cursor/cursor.rs index bba549d3bd..cb66ef3d38 100644 --- a/mm2src/mm2_db/src/indexed_db/drivers/cursor/cursor.rs +++ b/mm2src/mm2_db/src/indexed_db/drivers/cursor/cursor.rs @@ -196,8 +196,8 @@ pub(crate) struct CursorDriver { /// Whether we got `CursorAction::Stop` at the last iteration or not. stopped: bool, /// We need to hold the closures in memory till `cursor` exists. - _onsuccess_closure: Closure, - _onerror_closure: Closure, + pub _onsuccess_closure: Closure, + pub _onerror_closure: Closure, } impl CursorDriver { diff --git a/mm2src/mm2_db/src/indexed_db/indexed_cursor.rs b/mm2src/mm2_db/src/indexed_db/indexed_cursor.rs index d87ef84448..02ffe5210d 100644 --- a/mm2src/mm2_db/src/indexed_db/indexed_cursor.rs +++ b/mm2src/mm2_db/src/indexed_db/indexed_cursor.rs @@ -177,6 +177,9 @@ pub(crate) async fn cursor_event_loop(mut rx: DbCursorEventRx, mut cursor: Curso }, } } + + cursor._onsuccess_closure.forget(); + cursor._onerror_closure.forget(); } mod tests { From da09c4ceb54a1df31ee6335b56adeab6a83e982e Mon Sep 17 00:00:00 2001 From: borngraced Date: Tue, 5 Dec 2023 23:01:44 +0100 Subject: [PATCH 59/68] continue debug indexeddb cursor Signed-off-by: borngraced --- mm2src/coins/z_coin/z_params/indexeddb.rs | 4 +++- mm2src/mm2_db/src/indexed_db/indexed_cursor.rs | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/mm2src/coins/z_coin/z_params/indexeddb.rs b/mm2src/coins/z_coin/z_params/indexeddb.rs index 919625a8e4..fc7f65d7d5 100644 --- a/mm2src/coins/z_coin/z_params/indexeddb.rs +++ b/mm2src/coins/z_coin/z_params/indexeddb.rs @@ -1,4 +1,5 @@ use crate::z_coin::z_coin_errors::ZcoinStorageError; +use common::log::info; use mm2_core::mm_ctx::MmArc; use mm2_db::indexed_db::{ConstructibleDb, DbIdentifier, DbInstance, DbLocked, DbUpgrader, IndexedDb, IndexedDbBuilder, @@ -132,7 +133,8 @@ impl ZcashParamsWasmImpl { let mut sapling_spend = vec![]; let mut sapling_output = vec![]; - while let Some((_, params)) = maybe_params.next().await? { + while let Some((i, params)) = maybe_params.next().await? { + info!("PROCESSED: {i:?}"); sapling_spend.extend_from_slice(¶ms.sapling_spend); if params.sapling_spend_id == 0 { sapling_output = params.sapling_output diff --git a/mm2src/mm2_db/src/indexed_db/indexed_cursor.rs b/mm2src/mm2_db/src/indexed_db/indexed_cursor.rs index 02ffe5210d..d87ef84448 100644 --- a/mm2src/mm2_db/src/indexed_db/indexed_cursor.rs +++ b/mm2src/mm2_db/src/indexed_db/indexed_cursor.rs @@ -177,9 +177,6 @@ pub(crate) async fn cursor_event_loop(mut rx: DbCursorEventRx, mut cursor: Curso }, } } - - cursor._onsuccess_closure.forget(); - cursor._onerror_closure.forget(); } mod tests { From 4c03c61c17973aa02df0964282963b4fa2a8b969 Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 7 Dec 2023 01:35:58 +0100 Subject: [PATCH 60/68] improve z_params impl Signed-off-by: borngraced --- mm2src/coins/z_coin/z_params/indexeddb.rs | 34 +++++++++++-------- .../src/indexed_db/drivers/cursor/cursor.rs | 4 +-- mm2src/mm2_db/src/indexed_db/indexed_db.rs | 2 +- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/mm2src/coins/z_coin/z_params/indexeddb.rs b/mm2src/coins/z_coin/z_params/indexeddb.rs index fc7f65d7d5..89cf7e9407 100644 --- a/mm2src/coins/z_coin/z_params/indexeddb.rs +++ b/mm2src/coins/z_coin/z_params/indexeddb.rs @@ -1,5 +1,4 @@ use crate::z_coin::z_coin_errors::ZcoinStorageError; -use common::log::info; use mm2_core::mm_ctx::MmArc; use mm2_db::indexed_db::{ConstructibleDb, DbIdentifier, DbInstance, DbLocked, DbUpgrader, IndexedDb, IndexedDbBuilder, @@ -37,6 +36,7 @@ impl TableSignature for ZcashParamsWasmTable { table.create_multi_index(Self::SPEND_OUTPUT_INDEX, &["sapling_spend", "sapling_output"], true)?; table.create_index("sapling_spend", false)?; table.create_index("sapling_output", false)?; + table.create_index("sapling_spend_id", true)?; table.create_index("ticker", false)?; } @@ -97,9 +97,10 @@ impl ZcashParamsWasmImpl { ticker: CHAIN.to_string(), }; - params_db.add_item(¶ms).await?; - - Ok(()) + Ok(params_db + .replace_item_by_unique_index("sapling_spend_id", sapling_spend_id as u32, ¶ms) + .await + .map(|_| ())?) } /// Check if z_params is already save to storage previously. @@ -107,16 +108,12 @@ impl ZcashParamsWasmImpl { let locked_db = self.lock_db().await?; let db_transaction = locked_db.get_inner().transaction().await?; let params_db = db_transaction.table::().await?; + let count = params_db.count_all().await?; + if count != TARGET_SPEND_CHUNKS { + params_db.delete_items_by_index("ticker", CHAIN).await?; + } - let maybe_param = params_db - .cursor_builder() - .only("ticker", CHAIN)? - .open_cursor("ticker") - .await? - .next() - .await?; - - Ok(maybe_param.is_some()) + Ok(count == TARGET_SPEND_CHUNKS) } /// Get z_params from storage. @@ -124,6 +121,14 @@ impl ZcashParamsWasmImpl { let locked_db = self.lock_db().await?; let db_transaction = locked_db.get_inner().transaction().await?; let params_db = db_transaction.table::().await?; + let count = params_db.count_all().await?; + // if params count in store is not 11 we need to delete the store params, re-download and save fresh params + // to avoid bad bytes combinations. + if count != TARGET_SPEND_CHUNKS { + params_db.delete_items_by_index("ticker", CHAIN).await?; + return self.download_and_save_params().await; + }; + let mut maybe_params = params_db .cursor_builder() .only("ticker", CHAIN)? @@ -133,8 +138,7 @@ impl ZcashParamsWasmImpl { let mut sapling_spend = vec![]; let mut sapling_output = vec![]; - while let Some((i, params)) = maybe_params.next().await? { - info!("PROCESSED: {i:?}"); + while let Some((_, params)) = maybe_params.next().await? { sapling_spend.extend_from_slice(¶ms.sapling_spend); if params.sapling_spend_id == 0 { sapling_output = params.sapling_output diff --git a/mm2src/mm2_db/src/indexed_db/drivers/cursor/cursor.rs b/mm2src/mm2_db/src/indexed_db/drivers/cursor/cursor.rs index cb66ef3d38..bba549d3bd 100644 --- a/mm2src/mm2_db/src/indexed_db/drivers/cursor/cursor.rs +++ b/mm2src/mm2_db/src/indexed_db/drivers/cursor/cursor.rs @@ -196,8 +196,8 @@ pub(crate) struct CursorDriver { /// Whether we got `CursorAction::Stop` at the last iteration or not. stopped: bool, /// We need to hold the closures in memory till `cursor` exists. - pub _onsuccess_closure: Closure, - pub _onerror_closure: Closure, + _onsuccess_closure: Closure, + _onerror_closure: Closure, } impl CursorDriver { diff --git a/mm2src/mm2_db/src/indexed_db/indexed_db.rs b/mm2src/mm2_db/src/indexed_db/indexed_db.rs index 840c02f8ec..3e2bfe5982 100644 --- a/mm2src/mm2_db/src/indexed_db/indexed_db.rs +++ b/mm2src/mm2_db/src/indexed_db/indexed_db.rs @@ -495,7 +495,7 @@ impl<'transaction, Table: TableSignature> DbTable<'transaction, Table> { send_event_recv_response(&self.event_tx, event, result_rx).await } - /// Adds the given `item` of replace the previous one. + /// Adds the given `item` or replace the previous one. /// https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/put pub async fn replace_item(&self, item_id: ItemId, item: &Table) -> DbTransactionResult { let item = json::to_value(item).map_to_mm(|e| DbTransactionError::ErrorSerializingItem(e.to_string()))?; From 1d89f455b078ecf76c537a210d747412807e0719 Mon Sep 17 00:00:00 2001 From: borngraced Date: Mon, 18 Dec 2023 14:42:15 +0100 Subject: [PATCH 61/68] refactor body_stream and remove wasm-stream dep Signed-off-by: borngraced --- Cargo.lock | 14 --------- mm2src/mm2_net/Cargo.toml | 3 +- mm2src/mm2_net/src/wasm/body_stream.rs | 43 +++++++++++++++----------- mm2src/mm2_net/src/wasm/http.rs | 1 + 4 files changed, 27 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9a865bb34..85b8b19dec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4580,7 +4580,6 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test", - "wasm-streams", "web-sys", ] @@ -9054,19 +9053,6 @@ dependencies = [ "quote 1.0.33", ] -[[package]] -name = "wasm-streams" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "web-sys" version = "0.3.55" diff --git a/mm2src/mm2_net/Cargo.toml b/mm2src/mm2_net/Cargo.toml index 151607eb9f..1a65ef08a3 100644 --- a/mm2src/mm2_net/Cargo.toml +++ b/mm2src/mm2_net/Cargo.toml @@ -47,11 +47,10 @@ tower-service = "0.3" wasm-bindgen = "0.2.86" wasm-bindgen-test = { version = "0.3.2" } wasm-bindgen-futures = "0.4.21" -wasm-streams = "0.3.0" web-sys = { version = "0.3.55", features = ["console", "CloseEvent", "DomException", "ErrorEvent", "IdbDatabase", "IdbCursor", "IdbCursorWithValue", "IdbFactory", "IdbIndex", "IdbIndexParameters", "IdbObjectStore", "IdbObjectStoreParameters", "IdbOpenDbRequest", "IdbKeyRange", "IdbTransaction", "IdbTransactionMode", - "IdbVersionChangeEvent", "MessageEvent","ReadableStream", "WebSocket", "Worker"] } + "IdbVersionChangeEvent", "MessageEvent", "ReadableStreamDefaultReader", "ReadableStream", "WebSocket", "Worker"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/mm2src/mm2_net/src/wasm/body_stream.rs b/mm2src/mm2_net/src/wasm/body_stream.rs index 028c040dfc..57e0ba92a0 100644 --- a/mm2src/mm2_net/src/wasm/body_stream.rs +++ b/mm2src/mm2_net/src/wasm/body_stream.rs @@ -22,19 +22,19 @@ use byteorder::{BigEndian, ByteOrder}; use bytes::{BufMut, Bytes, BytesMut}; use common::{APPLICATION_GRPC_WEB, APPLICATION_GRPC_WEB_PROTO, APPLICATION_GRPC_WEB_TEXT, APPLICATION_GRPC_WEB_TEXT_PROTO}; -use futures_util::ready; -use futures_util::{stream::empty, Stream, TryStreamExt}; +use futures_util::{ready, stream}; +use futures_util::{stream::empty, Stream}; use http::{header::HeaderName, HeaderMap, HeaderValue}; use http_body::Body; use httparse::{Status, EMPTY_HEADER}; -use js_sys::Uint8Array; +use js_sys::{Object, Uint8Array}; use pin_project::pin_project; use std::ops::{Deref, DerefMut}; use std::{pin::Pin, task::{Context, Poll}}; -use wasm_bindgen::JsCast; -use wasm_streams::readable::IntoStream; -use web_sys::ReadableStream; +use wasm_bindgen::{JsCast, JsValue}; +use wasm_bindgen_futures::JsFuture; +use web_sys::{ReadableStream, ReadableStreamDefaultReader}; /// If the 8th most significant bit of a frame is `0`, it indicates data; if `1`, it indicates a trailer. const TRAILER_BIT: u8 = 0b10000000; @@ -144,11 +144,11 @@ pub struct ResponseBody { impl ResponseBody { /// Creates a new `ResponseBody` based on a ReadableStream and content type. - pub(crate) fn new(body_stream: ReadableStream, content_type: &str) -> Result { - let body_stream = wasm_streams::ReadableStream::from_raw(body_stream.unchecked_into()).into_stream(); + pub(crate) async fn new(body_stream: ReadableStream, content_type: &str) -> Result { + let body_stream: ReadableStreamDefaultReader = body_stream.get_reader().dyn_into().unwrap(); Ok(Self { - body_stream: BodyStream::new(body_stream), + body_stream: BodyStream::new(body_stream).await?, buf: EncodedBytes::new(content_type)?, incomplete_data: BytesMut::new(), data: None, @@ -348,15 +348,22 @@ pub struct BodyStream { } impl BodyStream { - /// Creates a new `BodyStream` based on an IntoStream. - pub fn new(body_stream: IntoStream<'static>) -> Self { - Self { - body_stream: Box::pin( - body_stream - .map_ok(|js_value| Uint8Array::new(&js_value).to_vec().into()) - .map_err(|err| PostGrpcWebErr::InvalidRequest(format!("{err:?}"))), - ), - } + /// Creates a new `BodyStream` based on an `ReadableStreamDefaultReader`. + pub async fn new(body_stream: ReadableStreamDefaultReader) -> Result { + let value = JsFuture::from(body_stream.read()) + .await + .map_err(|err| PostGrpcWebErr::InvalidRequest(format!("{err:?}")))?; + let object: Object = value + .dyn_into() + .map_err(|err| PostGrpcWebErr::InvalidRequest(format!("{err:?}")))?; + let object_value = js_sys::Reflect::get(&object, &JsValue::from_str("value")) + .map_err(|err| PostGrpcWebErr::InvalidRequest(format!("{err:?}")))?; + let chunk = Uint8Array::new(&object_value).to_vec(); + let bytes_stream = Box::pin(stream::once(async { Ok(Bytes::from(chunk)) })); + + Ok(Self { + body_stream: bytes_stream, + }) } /// Creates an empty `BodyStream`. diff --git a/mm2src/mm2_net/src/wasm/http.rs b/mm2src/mm2_net/src/wasm/http.rs index 51f509faf3..588ab02e9c 100644 --- a/mm2src/mm2_net/src/wasm/http.rs +++ b/mm2src/mm2_net/src/wasm/http.rs @@ -331,6 +331,7 @@ impl FetchRequest { let builder = Response::builder().status(status_code); let (builder, content_type) = set_response_headers_and_content_type(builder, &js_response)?; let body = ResponseBody::new(resp_stream, &content_type) + .await .map_to_mm(|err| SlurpError::InvalidRequest(format!("{err:?}")))?; Ok(( From 2a64404c408537d1af9cd2bca342e4ac046a2836 Mon Sep 17 00:00:00 2001 From: borngraced Date: Mon, 18 Dec 2023 16:40:12 +0100 Subject: [PATCH 62/68] read all stream instead of single Signed-off-by: borngraced --- mm2src/coins/z_coin/z_rpc.rs | 2 +- mm2src/mm2_net/src/grpc_web.rs | 1 + mm2src/mm2_net/src/wasm/body_stream.rs | 38 ++++++++++++++++++-------- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index ec16fe8d7f..b9d88361f3 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -244,7 +244,7 @@ impl ZRpcOps for LightRpcClient { .into_inner(); // without Pin method get_mut is not found in current scope while let Some(block) = Pin::new(&mut response).get_mut().message().await? { - debug!("Got block {:?}", block); + debug!("Got block {}", block.height); let height = u32::try_from(block.height) .map_err(|_| UpdateBlocksCacheErr::DecodeError("Block height too large".to_string()))?; db.insert_block(height, block.encode_to_vec()) diff --git a/mm2src/mm2_net/src/grpc_web.rs b/mm2src/mm2_net/src/grpc_web.rs index c91dc1bb45..55f796df82 100644 --- a/mm2src/mm2_net/src/grpc_web.rs +++ b/mm2src/mm2_net/src/grpc_web.rs @@ -98,6 +98,7 @@ pub enum PostGrpcWebErr { DecodeBody(String), EncodeBody(String), InvalidRequest(String), + BadResponse(String), Internal(String), PayloadTooShort(String), Status(String), diff --git a/mm2src/mm2_net/src/wasm/body_stream.rs b/mm2src/mm2_net/src/wasm/body_stream.rs index 57e0ba92a0..d47177c13d 100644 --- a/mm2src/mm2_net/src/wasm/body_stream.rs +++ b/mm2src/mm2_net/src/wasm/body_stream.rs @@ -145,7 +145,10 @@ pub struct ResponseBody { impl ResponseBody { /// Creates a new `ResponseBody` based on a ReadableStream and content type. pub(crate) async fn new(body_stream: ReadableStream, content_type: &str) -> Result { - let body_stream: ReadableStreamDefaultReader = body_stream.get_reader().dyn_into().unwrap(); + let body_stream: ReadableStreamDefaultReader = body_stream + .get_reader() + .dyn_into() + .map_err(|err| PostGrpcWebErr::BadResponse(format!("{err:?}")))?; Ok(Self { body_stream: BodyStream::new(body_stream).await?, @@ -350,19 +353,30 @@ pub struct BodyStream { impl BodyStream { /// Creates a new `BodyStream` based on an `ReadableStreamDefaultReader`. pub async fn new(body_stream: ReadableStreamDefaultReader) -> Result { - let value = JsFuture::from(body_stream.read()) - .await - .map_err(|err| PostGrpcWebErr::InvalidRequest(format!("{err:?}")))?; - let object: Object = value - .dyn_into() - .map_err(|err| PostGrpcWebErr::InvalidRequest(format!("{err:?}")))?; - let object_value = js_sys::Reflect::get(&object, &JsValue::from_str("value")) - .map_err(|err| PostGrpcWebErr::InvalidRequest(format!("{err:?}")))?; - let chunk = Uint8Array::new(&object_value).to_vec(); - let bytes_stream = Box::pin(stream::once(async { Ok(Bytes::from(chunk)) })); + let mut chunks = vec![]; + loop { + let value = JsFuture::from(body_stream.read()) + .await + .map_err(|err| PostGrpcWebErr::InvalidRequest(format!("{err:?}")))?; + let object: Object = value + .dyn_into() + .map_err(|err| PostGrpcWebErr::BadResponse(format!("{err:?}")))?; + let object_value = js_sys::Reflect::get(&object, &JsValue::from_str("value")) + .map_err(|err| PostGrpcWebErr::BadResponse(format!("{err:?}")))?; + let object_progress = js_sys::Reflect::get(&object, &JsValue::from_str("done")) + .map_err(|err| PostGrpcWebErr::BadResponse(format!("{err:?}")))?; + let chunk = Uint8Array::new(&object_value).to_vec(); + chunks.extend_from_slice(&chunk); + + if object_progress.as_bool().ok_or_else(|| { + PostGrpcWebErr::BadResponse("Expected done(bool) field in json object response".to_string()) + })? { + break; + } + } Ok(Self { - body_stream: bytes_stream, + body_stream: Box::pin(stream::once(async { Ok(Bytes::from(chunks)) })), }) } From 5aa68bcc09cdaf6ea966e50785275291fbc09388 Mon Sep 17 00:00:00 2001 From: borngraced Date: Mon, 18 Dec 2023 17:28:01 +0100 Subject: [PATCH 63/68] merge enable_z_coin_light unit test Signed-off-by: borngraced --- mm2src/mm2_main/src/wasm_tests.rs | 36 +++---------------- .../tests/integration_tests_common/mod.rs | 34 ++---------------- mm2src/mm2_main/tests/mm2_tests/mod.rs | 1 + .../tests/mm2_tests/orderbook_sync_tests.rs | 11 +++--- .../mm2_main/tests/mm2_tests/z_coin_tests.rs | 19 +++------- mm2src/mm2_test_helpers/src/for_tests.rs | 30 ++++++++++++++-- 6 files changed, 46 insertions(+), 85 deletions(-) diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index 8f9d8028d1..754ae40b42 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -8,11 +8,11 @@ use mm2_core::mm_ctx::MmArc; use mm2_number::BigDecimal; use mm2_rpc::data::legacy::OrderbookResponse; use mm2_test_helpers::electrums::{doc_electrums, marty_electrums}; -use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, init_z_coin_light, init_z_coin_status, - morty_conf, pirate_conf, rick_conf, start_swaps, test_qrc20_history_impl, - wait_for_swaps_finish_and_check_status, MarketMakerIt, Mm2InitPrivKeyPolicy, - Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, PIRATE_ELECTRUMS, - PIRATE_LIGHTWALLETD_URLS, RICK}; +use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, enable_z_coin_light, init_z_coin_light, + init_z_coin_status, morty_conf, pirate_conf, rick_conf, start_swaps, + test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, MarketMakerIt, + Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, + PIRATE_ELECTRUMS, PIRATE_LIGHTWALLETD_URLS, RICK}; use mm2_test_helpers::get_passphrase; use mm2_test_helpers::structs::{EnableCoinBalance, InitTaskResult, InitZcoinStatus, RpcV2Response, ZCoinActivationResult}; @@ -195,32 +195,6 @@ async fn trade_test_rick_and_morty() { .await; } -async fn enable_z_coin_light( - mm: &MarketMakerIt, - coin: &str, - electrums: &[&str], - lightwalletd_urls: &[&str], - account: Option, -) -> ZCoinActivationResult { - let init = init_z_coin_light(mm, coin, electrums, lightwalletd_urls, None, account).await; - let init: RpcV2Response = json::from_value(init).unwrap(); - let timeout = wait_until_sec(300); - - loop { - if now_sec() > timeout { - panic!("{} initialization timed out", coin); - } - let status = init_z_coin_status(mm, init.result.task_id).await; - info!("Status {}", json::to_string(&status).unwrap()); - let status: RpcV2Response = json::from_value(status).unwrap(); - match status.result { - InitZcoinStatus::Ok(result) => break result, - InitZcoinStatus::Error(e) => panic!("{} initialization error {:?}", coin, e), - _ => Timer::sleep(1.).await, - } - } -} - #[wasm_bindgen_test] async fn activate_z_coin_light() { register_wasm_log(); diff --git a/mm2src/mm2_main/tests/integration_tests_common/mod.rs b/mm2src/mm2_main/tests/integration_tests_common/mod.rs index be7e8bcb46..bf230c1546 100644 --- a/mm2src/mm2_main/tests/integration_tests_common/mod.rs +++ b/mm2src/mm2_main/tests/integration_tests_common/mod.rs @@ -7,9 +7,9 @@ use mm2_main::mm2::{lp_main, LpMainParams}; use mm2_rpc::data::legacy::CoinInitResponse; use mm2_test_helpers::electrums::{doc_electrums, marty_electrums}; use mm2_test_helpers::for_tests::{enable_native as enable_native_impl, init_utxo_electrum, init_utxo_status, - init_z_coin_light, init_z_coin_status, MarketMakerIt}; -use mm2_test_helpers::structs::{InitTaskResult, InitUtxoStatus, InitZcoinStatus, RpcV2Response, - UtxoStandardActivationResult, ZCoinActivationResult}; + MarketMakerIt}; + +use mm2_test_helpers::structs::{InitTaskResult, InitUtxoStatus, RpcV2Response, UtxoStandardActivationResult}; use serde_json::{self as json, Value as Json}; use std::collections::HashMap; use std::env::var; @@ -83,34 +83,6 @@ pub async fn enable_coins_rick_morty_electrum(mm: &MarketMakerIt) -> HashMap<&'s replies } -pub async fn enable_z_coin_light( - mm: &MarketMakerIt, - coin: &str, - electrums: &[&str], - lightwalletd_urls: &[&str], - starting_date: Option, - account: Option, -) -> ZCoinActivationResult { - let init = init_z_coin_light(mm, coin, electrums, lightwalletd_urls, starting_date, account).await; - let init: RpcV2Response = json::from_value(init).unwrap(); - let timeout = wait_until_ms(600000); - - loop { - if now_ms() > timeout { - panic!("{} initialization timed out", coin); - } - - let status = init_z_coin_status(mm, init.result.task_id).await; - println!("Status {}", json::to_string(&status).unwrap()); - let status: RpcV2Response = json::from_value(status).unwrap(); - match status.result { - InitZcoinStatus::Ok(result) => break result, - InitZcoinStatus::Error(e) => panic!("{} initialization error {:?}", coin, e), - _ => Timer::sleep(1.).await, - } - } -} - pub async fn enable_utxo_v2_electrum( mm: &MarketMakerIt, coin: &str, diff --git a/mm2src/mm2_main/tests/mm2_tests/mod.rs b/mm2src/mm2_main/tests/mm2_tests/mod.rs index cfc3aa1e15..f44fec7f0c 100644 --- a/mm2src/mm2_main/tests/mm2_tests/mod.rs +++ b/mm2src/mm2_main/tests/mm2_tests/mod.rs @@ -8,6 +8,7 @@ mod orderbook_sync_tests; mod tendermint_ibc_asset_tests; mod tendermint_tests; mod z_coin_tests; +pub use z_coin_tests::activate_z_coin_light; mod zhtlc_native_reexport { pub use common::executor::Timer; diff --git a/mm2src/mm2_main/tests/mm2_tests/orderbook_sync_tests.rs b/mm2src/mm2_main/tests/mm2_tests/orderbook_sync_tests.rs index 05710fa5c4..6130adfe23 100644 --- a/mm2src/mm2_main/tests/mm2_tests/orderbook_sync_tests.rs +++ b/mm2src/mm2_main/tests/mm2_tests/orderbook_sync_tests.rs @@ -1,14 +1,14 @@ use crate::integration_tests_common::{enable_coins_eth_electrum, enable_coins_rick_morty_electrum, enable_electrum, - enable_electrum_json, enable_z_coin_light}; + enable_electrum_json}; use common::{block_on, log}; use http::StatusCode; use mm2_main::mm2::lp_ordermatch::MIN_ORDER_KEEP_ALIVE_INTERVAL; use mm2_number::{BigDecimal, BigRational, MmNumber}; use mm2_rpc::data::legacy::{AggregatedOrderbookEntry, CoinInitResponse, OrderbookResponse}; use mm2_test_helpers::electrums::doc_electrums; -use mm2_test_helpers::for_tests::{eth_jst_testnet_conf, eth_testnet_conf, get_passphrase, morty_conf, orderbook_v2, - rick_conf, zombie_conf, MarketMakerIt, Mm2TestConf, DOC_ELECTRUM_ADDRS, - ETH_DEV_NODES, MARTY_ELECTRUM_ADDRS, RICK, ZOMBIE_ELECTRUMS, +use mm2_test_helpers::for_tests::{enable_z_coin_light, eth_jst_testnet_conf, eth_testnet_conf, get_passphrase, + morty_conf, orderbook_v2, rick_conf, zombie_conf, MarketMakerIt, Mm2TestConf, + DOC_ELECTRUM_ADDRS, ETH_DEV_NODES, MARTY_ELECTRUM_ADDRS, RICK, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, ZOMBIE_TICKER}; use mm2_test_helpers::get_passphrase; use mm2_test_helpers::structs::{GetPublicKeyResult, OrderbookV2Response, RpcV2Response, SetPriceResponse}; @@ -1337,7 +1337,6 @@ fn zhtlc_orders_sync_alice_connected_before_creation() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, - None, )); let set_price_json = json!({ @@ -1401,7 +1400,6 @@ fn zhtlc_orders_sync_alice_connected_after_creation() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, - None, )); let set_price_json = json!({ @@ -1431,7 +1429,6 @@ fn zhtlc_orders_sync_alice_connected_after_creation() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, - None, )); let set_price_json = json!({ diff --git a/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs b/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs index 7fa96a4b03..bc71482a03 100644 --- a/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs +++ b/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs @@ -3,10 +3,10 @@ use common::executor::Timer; use common::{block_on, log, now_ms, now_sec, wait_until_ms}; use mm2_number::BigDecimal; use mm2_test_helpers::electrums::doc_electrums; -use mm2_test_helpers::for_tests::{disable_coin, init_withdraw, pirate_conf, rick_conf, send_raw_transaction, - withdraw_status, z_coin_tx_history, zombie_conf, MarketMakerIt, Mm2TestConf, ARRR, - PIRATE_ELECTRUMS, PIRATE_LIGHTWALLETD_URLS, RICK, ZOMBIE_ELECTRUMS, - ZOMBIE_LIGHTWALLETD_URLS, ZOMBIE_TICKER}; +use mm2_test_helpers::for_tests::{disable_coin, enable_z_coin_light, init_withdraw, pirate_conf, rick_conf, + send_raw_transaction, withdraw_status, z_coin_tx_history, zombie_conf, + MarketMakerIt, Mm2TestConf, ARRR, PIRATE_ELECTRUMS, PIRATE_LIGHTWALLETD_URLS, RICK, + ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, ZOMBIE_TICKER}; use mm2_test_helpers::structs::{EnableCoinBalance, InitTaskResult, RpcV2Response, TransactionDetails, WithdrawStatus, ZcoinHistoryRes}; use serde_json::{self as json, json, Value as Json}; @@ -47,7 +47,7 @@ async fn withdraw(mm: &MarketMakerIt, coin: &str, to: &str, amount: &str) -> Tra } #[test] -fn activate_z_coin_light() { +pub fn activate_z_coin_light() { let coins = json!([zombie_conf()]); let conf = Mm2TestConf::seednode(ZOMBIE_TEST_BALANCE_SEED, &coins); @@ -59,7 +59,6 @@ fn activate_z_coin_light() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, - None, )); let balance = match activation_result.wallet_balance { @@ -82,7 +81,6 @@ fn activate_z_coin_light_with_changing_height() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, - None, )); let old_first_sync_block = activation_result.first_sync_block; @@ -109,7 +107,6 @@ fn activate_z_coin_light_with_changing_height() { ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, - Some(two_days_ago), None, )); @@ -143,7 +140,6 @@ fn activate_z_coin_with_hd_account() { ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, - None, Some(hd_account_id), )); @@ -172,7 +168,6 @@ fn test_z_coin_tx_history() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, - None, )); let tx_history = block_on(z_coin_tx_history(&mm, ZOMBIE_TICKER, 5, None)); @@ -417,7 +412,6 @@ fn withdraw_z_coin_light() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, - None, )); println!("{:?}", activation_result); @@ -460,7 +454,6 @@ fn trade_rick_zombie_light() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, - None, )); println!("Bob ZOMBIE activation {:?}", zombie_activation); @@ -494,7 +487,6 @@ fn trade_rick_zombie_light() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, - None, )); println!("Alice ZOMBIE activation {:?}", zombie_activation); @@ -552,7 +544,6 @@ fn activate_pirate_light() { PIRATE_ELECTRUMS, PIRATE_LIGHTWALLETD_URLS, None, - None, )); let balance = match activation_result.wallet_balance { diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index f56b71a27a..94a3647158 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -4,8 +4,8 @@ use crate::electrums::qtum_electrums; use crate::structs::*; use common::custom_futures::repeatable::{Ready, Retry}; use common::executor::Timer; -use common::log::debug; -use common::{cfg_native, now_float, now_ms, now_sec, repeatable, wait_until_ms, PagingOptionsEnum}; +use common::log::{debug, info}; +use common::{cfg_native, now_float, now_ms, now_sec, repeatable, wait_until_ms, wait_until_sec, PagingOptionsEnum}; use common::{get_utc_timestamp, log}; use crypto::{CryptoCtx, StandardHDCoinAddress}; use gstuff::{try_s, ERR, ERRL}; @@ -3098,6 +3098,32 @@ pub async fn get_locked_amount(mm: &MarketMakerIt, coin: &str) -> GetLockedAmoun response.result } +pub async fn enable_z_coin_light( + mm: &MarketMakerIt, + coin: &str, + electrums: &[&str], + lightwalletd_urls: &[&str], + account: Option, +) -> ZCoinActivationResult { + let init = init_z_coin_light(mm, coin, electrums, lightwalletd_urls, None, account).await; + let init: RpcV2Response = json::from_value(init).unwrap(); + let timeout = wait_until_sec(300); + + loop { + if now_sec() > timeout { + panic!("{} initialization timed out", coin); + } + let status = init_z_coin_status(mm, init.result.task_id).await; + info!("Status {}", json::to_string(&status).unwrap()); + let status: RpcV2Response = json::from_value(status).unwrap(); + match status.result { + InitZcoinStatus::Ok(result) => break result, + InitZcoinStatus::Error(e) => panic!("{} initialization error {:?}", coin, e), + _ => Timer::sleep(1.).await, + } + } +} + #[test] #[cfg(not(target_arch = "wasm32"))] fn test_parse_env_file() { From d775aec10469946a4d49c50c40342bc4dbcc8636 Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 21 Dec 2023 19:43:40 +0100 Subject: [PATCH 64/68] fix review notes Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 2 +- mm2src/coins/z_coin/z_params/mod.rs | 2 +- mm2src/mm2_main/src/wasm_tests.rs | 16 ++++----- mm2src/mm2_main/tests/mm2_tests/mod.rs | 1 - .../mm2_main/tests/mm2_tests/z_coin_tests.rs | 2 +- mm2src/mm2_net/src/wasm/http.rs | 36 ++++++++----------- 6 files changed, 24 insertions(+), 35 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index a901b30ec9..3a29bfdfca 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -111,7 +111,7 @@ pub use z_coin_errors::*; pub mod storage; #[cfg(all(test, feature = "zhtlc-native-tests"))] mod z_coin_native_tests; -#[cfg(target_arch = "wasm32")] pub mod z_params; +#[cfg(target_arch = "wasm32")] mod z_params; /// `ZP2SHSpendError` compatible `TransactionErr` handling macro. macro_rules! try_ztx_s { diff --git a/mm2src/coins/z_coin/z_params/mod.rs b/mm2src/coins/z_coin/z_params/mod.rs index 990886faaf..650596505b 100644 --- a/mm2src/coins/z_coin/z_params/mod.rs +++ b/mm2src/coins/z_coin/z_params/mod.rs @@ -17,7 +17,7 @@ const SAPLING_SPEND_HASH: &str = "8270785a1a0d0bc77196f000ee6d221c9c9894f55307bd const SAPLING_OUTPUT_HASH: &str = "657e3d38dbb5cb5e7dd2970e8b03d69b4787dd907285b5a7f0790dcc8072f60bf593b32cc2d1c030e00ff5ae64bf84c5c3beb84ddc841d48264b4a171744d028"; #[derive(Debug, derive_more::Display)] -pub enum ZcashParamsError { +pub(crate) enum ZcashParamsError { Transport(String), ValidationError(String), } diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index 754ae40b42..f5b95d780a 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -1,23 +1,19 @@ use crate::mm2::lp_init; use common::executor::{spawn, Timer}; -use common::log::info; use common::log::wasm_log::register_wasm_log; -use common::{now_sec, wait_until_sec}; use crypto::StandardHDCoinAddress; use mm2_core::mm_ctx::MmArc; use mm2_number::BigDecimal; use mm2_rpc::data::legacy::OrderbookResponse; use mm2_test_helpers::electrums::{doc_electrums, marty_electrums}; -use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, enable_z_coin_light, init_z_coin_light, - init_z_coin_status, morty_conf, pirate_conf, rick_conf, start_swaps, - test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, MarketMakerIt, - Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, - PIRATE_ELECTRUMS, PIRATE_LIGHTWALLETD_URLS, RICK}; +use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, enable_z_coin_light, morty_conf, + pirate_conf, rick_conf, start_swaps, test_qrc20_history_impl, + wait_for_swaps_finish_and_check_status, MarketMakerIt, Mm2InitPrivKeyPolicy, + Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, PIRATE_ELECTRUMS, + PIRATE_LIGHTWALLETD_URLS, RICK}; use mm2_test_helpers::get_passphrase; -use mm2_test_helpers::structs::{EnableCoinBalance, InitTaskResult, InitZcoinStatus, RpcV2Response, - ZCoinActivationResult}; +use mm2_test_helpers::structs::EnableCoinBalance; use serde_json::json; -use serde_json::{self as json}; use wasm_bindgen_test::wasm_bindgen_test; const PIRATE_TEST_BALANCE_SEED: &str = "pirate test seed"; diff --git a/mm2src/mm2_main/tests/mm2_tests/mod.rs b/mm2src/mm2_main/tests/mm2_tests/mod.rs index f44fec7f0c..cfc3aa1e15 100644 --- a/mm2src/mm2_main/tests/mm2_tests/mod.rs +++ b/mm2src/mm2_main/tests/mm2_tests/mod.rs @@ -8,7 +8,6 @@ mod orderbook_sync_tests; mod tendermint_ibc_asset_tests; mod tendermint_tests; mod z_coin_tests; -pub use z_coin_tests::activate_z_coin_light; mod zhtlc_native_reexport { pub use common::executor::Timer; diff --git a/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs b/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs index bc71482a03..2bfa50f3b8 100644 --- a/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs +++ b/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs @@ -47,7 +47,7 @@ async fn withdraw(mm: &MarketMakerIt, coin: &str, to: &str, amount: &str) -> Tra } #[test] -pub fn activate_z_coin_light() { +pub(crate) fn activate_z_coin_light() { let coins = json!([zombie_conf()]); let conf = Mm2TestConf::seednode(ZOMBIE_TEST_BALANCE_SEED, &coins); diff --git a/mm2src/mm2_net/src/wasm/http.rs b/mm2src/mm2_net/src/wasm/http.rs index 588ab02e9c..2175df21c7 100644 --- a/mm2src/mm2_net/src/wasm/http.rs +++ b/mm2src/mm2_net/src/wasm/http.rs @@ -1,7 +1,7 @@ use crate::transport::{GetInfoFromUriError, SlurpError, SlurpResult}; use crate::wasm::body_stream::ResponseBody; use common::executor::spawn_local; -use common::{stringify_js_error, APPLICATION_JSON}; +use common::{drop_mutability, stringify_js_error, APPLICATION_JSON}; use futures::channel::oneshot; use gstuff::ERRL; use http::header::{ACCEPT, CONTENT_TYPE}; @@ -59,31 +59,25 @@ fn set_response_headers_and_content_type( mut result: Builder, response: &JsResponse, ) -> Result<(Builder, String), MmError> { - let headers = response.headers(); - - let header_iter = - js_sys::try_iter(headers.as_ref()).map_to_mm(|err| SlurpError::InvalidRequest(format!("{err:?}")))?; + let headers = match js_sys::try_iter(response.headers().as_ref()) { + Ok(Some(headers)) => headers, + Ok(None) => return MmError::err(SlurpError::InvalidRequest("MissingHeaders".to_string())), + Err(err) => return MmError::err(SlurpError::InvalidRequest(format!("{err:?}"))), + }; let mut content_type = None; - - if let Some(header_iter) = header_iter { - for header in header_iter { - let pair: Array = header - .map_to_mm(|err| SlurpError::InvalidRequest(format!("{err:?}")))? - .into(); - let (header_name, header_value) = (pair.get(0).as_string(), pair.get(1).as_string()); - match (header_name, header_value) { - (Some(header_name), Some(header_value)) => { - if header_name == CONTENT_TYPE.as_str() { - content_type = Some(header_value.clone()); - } - - result = result.header(header_name, header_value); - }, - _ => continue, + for header in headers { + let pair: Array = header + .map_to_mm(|err| SlurpError::InvalidRequest(format!("{err:?}")))? + .into(); + if let (Some(header_name), Some(header_value)) = (pair.get(0).as_string(), pair.get(1).as_string()) { + if header_name == CONTENT_TYPE.as_str() { + content_type = Some(header_value.clone()); } + result = result.header(header_name, header_value); } } + drop_mutability!(content_type); match content_type { Some(content_type) => Ok((result, content_type)), From 2300d5cc8096335c344565da08bbe32d2df78a54 Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 21 Dec 2023 20:20:55 +0100 Subject: [PATCH 65/68] fix merge conflicts Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 2 +- mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index dde686e240..47014984c0 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -8,11 +8,11 @@ use crate::utxo::utxo_builder::UtxoCoinBuildError; use crate::utxo::utxo_builder::{UtxoCoinBuilder, UtxoCoinBuilderCommonOps, UtxoFieldsWithGlobalHDBuilder, UtxoFieldsWithHardwareWalletBuilder, UtxoFieldsWithIguanaSecretBuilder}; use crate::utxo::utxo_common::{big_decimal_from_sat_unsigned, payment_script}; -use crate::utxo::UtxoFeeDetails; use crate::utxo::{sat_from_big_decimal, utxo_common, ActualTxFee, AdditionalTxData, AddrFromStrError, Address, BroadcastTxErr, FeePolicy, GetUtxoListOps, HistoryUtxoTx, HistoryUtxoTxMap, MatureUnspentList, RecentlySpentOutPointsGuard, UtxoActivationParams, UtxoAddressFormat, UtxoArc, UtxoCoinFields, UtxoCommonOps, UtxoRpcMode, UtxoTxBroadcastOps, UtxoTxGenerationOps, VerboseTransactionFrom}; +use crate::utxo::{UnsupportedAddr, UtxoFeeDetails}; use crate::TxFeeDetails; use crate::{BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, CoinFutSpawner, ConfirmPaymentInput, DexFee, FeeApproxStage, FoundSwapTxSpend, HistorySyncState, MakerSwapTakerCoin, MarketCoinOps, MmCoin, diff --git a/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs b/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs index 2bfa50f3b8..7c0f99d733 100644 --- a/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs +++ b/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs @@ -47,7 +47,7 @@ async fn withdraw(mm: &MarketMakerIt, coin: &str, to: &str, amount: &str) -> Tra } #[test] -pub(crate) fn activate_z_coin_light() { +fn activate_z_coin_light() { let coins = json!([zombie_conf()]); let conf = Mm2TestConf::seednode(ZOMBIE_TEST_BALANCE_SEED, &coins); From e976a6d10bed7466d498654156ce277d3b1b1d66 Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 21 Dec 2023 22:25:18 +0100 Subject: [PATCH 66/68] fix review notes Signed-off-by: borngraced --- mm2src/coins/z_coin.rs | 14 +-- mm2src/coins/z_coin/z_coin_errors.rs | 2 + mm2src/coins/z_coin/z_params/indexeddb.rs | 8 -- mm2src/mm2_net/src/wasm/body_stream.rs | 119 +++++++++++----------- 4 files changed, 70 insertions(+), 73 deletions(-) diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 47014984c0..1e9a4d2fbe 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -1097,25 +1097,25 @@ impl<'a> ZCoinBuilder<'a> { let params_db = ZcashParamsWasmImpl::new(self.ctx.clone()) .await .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; - return if !params_db + let (sapling_spend, sapling_output) = if !params_db .check_params() .await .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))? { // save params - let (sapling_spend, sapling_output) = params_db + params_db .download_and_save_params() .await - .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; - Ok(LocalTxProver::from_bytes(&sapling_spend[..], &sapling_output[..])) + .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))? } else { // get params - let (sapling_spend, sapling_output) = params_db + params_db .get_params() .await - .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))?; - Ok(LocalTxProver::from_bytes(&sapling_spend[..], &sapling_output[..])) + .mm_err(|err| ZCoinBuildError::ZCashParamsError(err.to_string()))? }; + + Ok(LocalTxProver::from_bytes(&sapling_spend[..], &sapling_output[..])) } } diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index a2adab422f..30bbc1edeb 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -423,6 +423,8 @@ pub enum ZcoinStorageError { NotSupported(String), #[cfg(target_arch = "wasm32")] ZcashParamsError(String), + #[cfg(target_arch = "wasm32")] + MalfunctionedParamsData, } impl From for ZcoinStorageError { diff --git a/mm2src/coins/z_coin/z_params/indexeddb.rs b/mm2src/coins/z_coin/z_params/indexeddb.rs index 89cf7e9407..765329c4dc 100644 --- a/mm2src/coins/z_coin/z_params/indexeddb.rs +++ b/mm2src/coins/z_coin/z_params/indexeddb.rs @@ -121,14 +121,6 @@ impl ZcashParamsWasmImpl { let locked_db = self.lock_db().await?; let db_transaction = locked_db.get_inner().transaction().await?; let params_db = db_transaction.table::().await?; - let count = params_db.count_all().await?; - // if params count in store is not 11 we need to delete the store params, re-download and save fresh params - // to avoid bad bytes combinations. - if count != TARGET_SPEND_CHUNKS { - params_db.delete_items_by_index("ticker", CHAIN).await?; - return self.download_and_save_params().await; - }; - let mut maybe_params = params_db .cursor_builder() .only("ticker", CHAIN)? diff --git a/mm2src/mm2_net/src/wasm/body_stream.rs b/mm2src/mm2_net/src/wasm/body_stream.rs index d47177c13d..f4a59603b0 100644 --- a/mm2src/mm2_net/src/wasm/body_stream.rs +++ b/mm2src/mm2_net/src/wasm/body_stream.rs @@ -52,7 +52,11 @@ impl EncodedBytes { let is_base64 = match content_type { APPLICATION_GRPC_WEB_TEXT | APPLICATION_GRPC_WEB_TEXT_PROTO => true, APPLICATION_GRPC_WEB | APPLICATION_GRPC_WEB_PROTO => false, - _ => return Err(PostGrpcWebErr::InvalidRequest(content_type.to_owned())), + _ => { + return Err(PostGrpcWebErr::InvalidRequest(format!( + "Unsupported Content-Type: {content_type}" + ))) + }, }; Ok(Self { @@ -193,96 +197,95 @@ impl ResponseBody { if this.buf.is_empty() { // Can't read compression flag right now return Ok(()); + }; + + let compression_flag = this.buf.take(1); + if compression_flag[0] & TRAILER_BIT == 0 { + this.incomplete_data.unsplit(compression_flag); + *this.state = ReadState::DataLength; } else { - let compression_flag = this.buf.take(1); - - if compression_flag[0] & TRAILER_BIT == 0 { - this.incomplete_data.unsplit(compression_flag); - *this.state = ReadState::DataLength; - } else { - *this.state = ReadState::TrailerLength; - } + *this.state = ReadState::TrailerLength; } }, ReadState::DataLength => { if this.buf.len() < 4 { // Can't read data length right now return Ok(()); - } else { - let data_length_bytes = this.buf.take(4); - let data_length = BigEndian::read_u32(data_length_bytes.as_ref()); + }; - this.incomplete_data.extend_from_slice(&data_length_bytes); - *this.state = ReadState::Data(data_length); - } + let data_length_bytes = this.buf.take(4); + let data_length = BigEndian::read_u32(data_length_bytes.as_ref()); + + this.incomplete_data.extend_from_slice(&data_length_bytes); + *this.state = ReadState::Data(data_length); }, ReadState::Data(data_length) => { let data_length = *data_length as usize; - if this.buf.len() < data_length { // Can't read data right now return Ok(()); - } else { - this.incomplete_data.unsplit(this.buf.take(data_length)); - - let new_data = this.incomplete_data.split(); + }; - if let Some(data) = this.data { - data.unsplit(new_data); - } else { - *this.data = Some(new_data); - } + this.incomplete_data.unsplit(this.buf.take(data_length)); - *this.state = ReadState::CompressionFlag; + let new_data = this.incomplete_data.split(); + if let Some(data) = this.data { + data.unsplit(new_data); + } else { + *this.data = Some(new_data); } + + *this.state = ReadState::CompressionFlag; }, ReadState::TrailerLength => { if this.buf.len() < 4 { // Can't read data length right now return Ok(()); - } else { - let trailer_length_bytes = this.buf.take(4); - let trailer_length = BigEndian::read_u32(trailer_length_bytes.as_ref()); - *this.state = ReadState::Trailer(trailer_length); - } + }; + + *this.state = ReadState::Trailer(BigEndian::read_u32(this.buf.take(4).as_ref())); }, ReadState::Trailer(trailer_length) => { let trailer_length = *trailer_length as usize; - if this.buf.len() < trailer_length { // Can't read trailer right now return Ok(()); - } else { - let mut trailer_bytes = this.buf.take(trailer_length); - trailer_bytes.put_u8(b'\n'); - - let mut trailers_buf = [EMPTY_HEADER; 64]; - let parsed_trailers = match httparse::parse_headers(&trailer_bytes, &mut trailers_buf) - .map_err(|err| PostGrpcWebErr::InvalidRequest(err.to_string()))? - { - Status::Complete((_, headers)) => Ok(headers), - Status::Partial => Err(PostGrpcWebErr::InvalidRequest("Invalid".to_string())), - }?; - - let mut trailers = HeaderMap::with_capacity(parsed_trailers.len()); - - for parsed_trailer in parsed_trailers { - let header_name = HeaderName::from_bytes(parsed_trailer.name.as_bytes()) - .map_err(|err| PostGrpcWebErr::InvalidRequest(err.to_string()))?; - let header_value = HeaderValue::from_bytes(parsed_trailer.value) - .map_err(|err| PostGrpcWebErr::InvalidRequest(err.to_string()))?; - trailers.insert(header_name, header_value); - } - - *this.trailer = Some(trailers); - - *this.state = ReadState::Done; - } + }; + + let mut trailer_bytes = this.buf.take(trailer_length); + trailer_bytes.put_u8(b'\n'); + + *this.trailer = Some(Self::parse_trailer(&trailer_bytes)?); + *this.state = ReadState::Done; }, ReadState::Done => return Ok(()), } } } + + fn parse_trailer(trailer_bytes: &[u8]) -> Result { + let mut trailers_buf = [EMPTY_HEADER; 64]; + let parsed_trailers = match httparse::parse_headers(trailer_bytes, &mut trailers_buf) + .map_err(|err| PostGrpcWebErr::InvalidRequest(err.to_string()))? + { + Status::Complete((_, headers)) => Ok(headers), + Status::Partial => Err(PostGrpcWebErr::InvalidRequest( + "parse header not completed!".to_string(), + )), + }?; + + let mut trailers = HeaderMap::with_capacity(parsed_trailers.len()); + + for parsed_trailer in parsed_trailers { + let header_name = HeaderName::from_bytes(parsed_trailer.name.as_bytes()) + .map_err(|err| PostGrpcWebErr::InvalidRequest(err.to_string()))?; + let header_value = HeaderValue::from_bytes(parsed_trailer.value) + .map_err(|err| PostGrpcWebErr::InvalidRequest(err.to_string()))?; + trailers.insert(header_name, header_value); + } + + Ok(trailers) + } } impl Body for ResponseBody { From 00eefceaa13fa1c38e9900fa166a9b0f0981d187 Mon Sep 17 00:00:00 2001 From: borngraced Date: Thu, 21 Dec 2023 22:41:02 +0100 Subject: [PATCH 67/68] remove MalfunctionedParamsData Signed-off-by: borngraced --- mm2src/coins/z_coin/z_coin_errors.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index 30bbc1edeb..a2adab422f 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -423,8 +423,6 @@ pub enum ZcoinStorageError { NotSupported(String), #[cfg(target_arch = "wasm32")] ZcashParamsError(String), - #[cfg(target_arch = "wasm32")] - MalfunctionedParamsData, } impl From for ZcoinStorageError { From f93b130cabd6cd15e97a83136e6dd651d06fafac Mon Sep 17 00:00:00 2001 From: borngraced Date: Fri, 22 Dec 2023 00:22:38 +0100 Subject: [PATCH 68/68] update enable_z_coin_light to accept starting date Signed-off-by: borngraced --- mm2src/mm2_main/src/wasm_tests.rs | 3 ++- mm2src/mm2_main/tests/mm2_tests/orderbook_sync_tests.rs | 3 +++ mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs | 9 +++++++++ mm2src/mm2_test_helpers/src/for_tests.rs | 3 ++- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index f5b95d780a..dbb8f5ff81 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -201,7 +201,8 @@ async fn activate_z_coin_light() { .await .unwrap(); - let activation_result = enable_z_coin_light(&mm, ARRR, PIRATE_ELECTRUMS, PIRATE_LIGHTWALLETD_URLS, None).await; + let activation_result = + enable_z_coin_light(&mm, ARRR, PIRATE_ELECTRUMS, PIRATE_LIGHTWALLETD_URLS, None, None).await; let balance = match activation_result.wallet_balance { EnableCoinBalance::Iguana(iguana) => iguana, diff --git a/mm2src/mm2_main/tests/mm2_tests/orderbook_sync_tests.rs b/mm2src/mm2_main/tests/mm2_tests/orderbook_sync_tests.rs index 6130adfe23..00ac53672f 100644 --- a/mm2src/mm2_main/tests/mm2_tests/orderbook_sync_tests.rs +++ b/mm2src/mm2_main/tests/mm2_tests/orderbook_sync_tests.rs @@ -1337,6 +1337,7 @@ fn zhtlc_orders_sync_alice_connected_before_creation() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, + None, )); let set_price_json = json!({ @@ -1400,6 +1401,7 @@ fn zhtlc_orders_sync_alice_connected_after_creation() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, + None, )); let set_price_json = json!({ @@ -1429,6 +1431,7 @@ fn zhtlc_orders_sync_alice_connected_after_creation() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, + None, )); let set_price_json = json!({ diff --git a/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs b/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs index 7c0f99d733..d622bfa7e8 100644 --- a/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs +++ b/mm2src/mm2_main/tests/mm2_tests/z_coin_tests.rs @@ -59,6 +59,7 @@ fn activate_z_coin_light() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, + None, )); let balance = match activation_result.wallet_balance { @@ -81,6 +82,7 @@ fn activate_z_coin_light_with_changing_height() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, + None, )); let old_first_sync_block = activation_result.first_sync_block; @@ -108,6 +110,7 @@ fn activate_z_coin_light_with_changing_height() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, + Some(two_days_ago), )); let new_first_sync_block = activation_result.first_sync_block; @@ -141,6 +144,7 @@ fn activate_z_coin_with_hd_account() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, Some(hd_account_id), + None, )); let actual = match activation_result.wallet_balance { @@ -168,6 +172,7 @@ fn test_z_coin_tx_history() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, + None, )); let tx_history = block_on(z_coin_tx_history(&mm, ZOMBIE_TICKER, 5, None)); @@ -412,6 +417,7 @@ fn withdraw_z_coin_light() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, + None, )); println!("{:?}", activation_result); @@ -454,6 +460,7 @@ fn trade_rick_zombie_light() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, + None, )); println!("Bob ZOMBIE activation {:?}", zombie_activation); @@ -487,6 +494,7 @@ fn trade_rick_zombie_light() { ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, None, + None, )); println!("Alice ZOMBIE activation {:?}", zombie_activation); @@ -544,6 +552,7 @@ fn activate_pirate_light() { PIRATE_ELECTRUMS, PIRATE_LIGHTWALLETD_URLS, None, + None, )); let balance = match activation_result.wallet_balance { diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index 69b32b74ee..5a2554089b 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -3118,8 +3118,9 @@ pub async fn enable_z_coin_light( electrums: &[&str], lightwalletd_urls: &[&str], account: Option, + starting_height: Option, ) -> ZCoinActivationResult { - let init = init_z_coin_light(mm, coin, electrums, lightwalletd_urls, None, account).await; + let init = init_z_coin_light(mm, coin, electrums, lightwalletd_urls, starting_height, account).await; let init: RpcV2Response = json::from_value(init).unwrap(); let timeout = wait_until_sec(300);