From 0f6c7261579ad028b930593c1f2e8a94dca0fced Mon Sep 17 00:00:00 2001 From: Artem Vitae Date: Wed, 10 Aug 2022 18:42:54 +0700 Subject: [PATCH] Fix ARRR activation. More info to activation statuses. Check point block #1427 (#1439) * WIP. * WIP. Added more info to BuildingWalletDb status. Added check_point_block. * Temporary ignore RUSTSEC-2020-0159. * Add TemporaryError variant to SyncStatus #1427. * consensus_params -> protocol_info * Review fixes. Co-authored-by: Artem Vitae --- deny.toml | 2 + mm2src/coins/lp_coins.rs | 6 +- mm2src/coins/z_coin.rs | 66 ++++++++----- mm2src/coins/z_coin/z_coin_errors.rs | 9 +- ...z_coin_tests.rs => z_coin_native_tests.rs} | 0 mm2src/coins/z_coin/z_rpc.rs | 96 +++++++++++++------ .../coins_activation/src/z_coin_activation.rs | 25 +++-- mm2src/common/log.rs | 13 +++ mm2src/mm2_main/src/mm2_tests.rs | 14 +-- .../src/mm2_tests/orderbook_sync_tests.rs | 3 - mm2src/mm2_main/src/mm2_tests/z_coin_tests.rs | 35 +++++-- mm2src/mm2_test_helpers/src/for_tests.rs | 38 ++++++++ 12 files changed, 217 insertions(+), 90 deletions(-) rename mm2src/coins/z_coin/{z_coin_tests.rs => z_coin_native_tests.rs} (100%) diff --git a/deny.toml b/deny.toml index 2c6b571716..a62214ca06 100644 --- a/deny.toml +++ b/deny.toml @@ -51,10 +51,12 @@ notice = "warn" # RUSTSEC-2021-0113 is related to metrics-util crate that is not actively used for now despite being still present in deps tree # RUSTSEC-2020-0071 is related to time crate, which is used only by chrono in our deps tree, remove when https://github.com/chronotope/chrono/issues/700 is resolved # RUSTSEC-2022-0040 is related to owning-ref, which seems unmaintained. We need to find a way to get rid of it. https://github.com/KomodoPlatform/atomicDEX-API/issues/1429 +# RUSTSEC-2020-0159 is related to chrono, updated in dev ignore = [ "RUSTSEC-2021-0113", "RUSTSEC-2020-0071", "RUSTSEC-2022-0040", + "RUSTSEC-2020-0159", #"RUSTSEC-0000-0000", ] # Threshold for security vulnerabilities, any vulnerability with a CVSS score diff --git a/mm2src/coins/lp_coins.rs b/mm2src/coins/lp_coins.rs index 4fed0635b9..66894f6850 100644 --- a/mm2src/coins/lp_coins.rs +++ b/mm2src/coins/lp_coins.rs @@ -69,7 +69,7 @@ cfg_native! { use futures::AsyncWriteExt; use std::io; use zcash_primitives::transaction::Transaction as ZTransaction; - use z_coin::ZcoinConsensusParams; + use z_coin::ZcoinProtocolInfo; } cfg_wasm32! { @@ -2110,9 +2110,7 @@ pub enum CoinProtocol { decimals: u8, }, #[cfg(not(target_arch = "wasm32"))] - ZHTLC { - consensus_params: ZcoinConsensusParams, - }, + ZHTLC(ZcoinProtocolInfo), } pub type RpcTransportEventHandlerShared = Arc; diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index f9b68bbf4b..c29255f9de 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -76,7 +76,7 @@ mod z_coin_errors; pub use z_coin_errors::*; #[cfg(all(test, feature = "zhtlc-native-tests"))] -mod z_coin_tests; +mod z_coin_native_tests; /// `ZP2SHSpendError` compatible `TransactionErr` handling macro. macro_rules! try_ztx_s { @@ -119,6 +119,20 @@ pub struct ZcoinConsensusParams { b58_script_address_prefix: [u8; 2], } +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct CheckPointBlockInfo { + height: u32, + hash: H256Json, + time: u32, + sapling_tree: BytesJson, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ZcoinProtocolInfo { + consensus_params: ZcoinConsensusParams, + check_point_block: Option, +} + impl Parameters for ZcoinConsensusParams { fn activation_height(&self, nu: NetworkUpgrade) -> Option { match nu { @@ -696,22 +710,12 @@ pub async fn z_coin_from_conf_and_params( ticker: &str, conf: &Json, params: &ZcoinActivationParams, - consensus_params: ZcoinConsensusParams, + protocol_info: ZcoinProtocolInfo, secp_priv_key: &[u8], ) -> Result> { let z_key = ExtendedSpendingKey::master(secp_priv_key); let db_dir = ctx.dbdir(); - z_coin_from_conf_and_params_with_z_key( - ctx, - ticker, - conf, - params, - secp_priv_key, - db_dir, - z_key, - consensus_params, - ) - .await + z_coin_from_conf_and_params_with_z_key(ctx, ticker, conf, params, secp_priv_key, db_dir, z_key, protocol_info).await } pub struct ZCoinBuilder<'a> { @@ -723,7 +727,7 @@ pub struct ZCoinBuilder<'a> { secp_priv_key: &'a [u8], db_dir_path: PathBuf, z_spending_key: ExtendedSpendingKey, - consensus_params: ZcoinConsensusParams, + protocol_info: ZcoinProtocolInfo, } impl<'a> UtxoCoinBuilderCommonOps for ZCoinBuilder<'a> { @@ -755,15 +759,21 @@ impl<'a> UtxoCoinWithIguanaPrivKeyBuilder for ZCoinBuilder<'a> { .default_address() .map_err(|_| MmError::new(ZCoinBuildError::GetAddressError))?; - let dex_fee_addr = decode_payment_address(self.consensus_params.hrp_sapling_payment_address(), DEX_FEE_Z_ADDR) - .expect("DEX_FEE_Z_ADDR is a valid z-address") - .expect("DEX_FEE_Z_ADDR is a valid z-address"); + let dex_fee_addr = decode_payment_address( + self.protocol_info.consensus_params.hrp_sapling_payment_address(), + DEX_FEE_Z_ADDR, + ) + .expect("DEX_FEE_Z_ADDR is a valid z-address") + .expect("DEX_FEE_Z_ADDR is a valid z-address"); let z_tx_prover = async_blocking(LocalTxProver::with_default_location) .await .or_mm_err(|| ZCoinBuildError::ZCashParamsNotFound)?; - let my_z_addr_encoded = encode_payment_address(self.consensus_params.hrp_sapling_payment_address(), &my_z_addr); + let my_z_addr_encoded = encode_payment_address( + self.protocol_info.consensus_params.hrp_sapling_payment_address(), + &my_z_addr, + ); let evk = ExtendedFullViewingKey::from(&self.z_spending_key); let (sync_state_connector, light_wallet_db) = match &self.z_coin_params.mode { @@ -782,7 +792,15 @@ impl<'a> UtxoCoinWithIguanaPrivKeyBuilder for ZCoinBuilder<'a> { .or_mm_err(|| ZCoinBuildError::EmptyLightwalletdUris)?, )?; - init_light_client(uri, cache_db_path, wallet_db_path, self.consensus_params.clone(), evk).await? + init_light_client( + uri, + cache_db_path, + wallet_db_path, + self.protocol_info.consensus_params.clone(), + self.protocol_info.check_point_block, + evk, + ) + .await? }, }; @@ -794,7 +812,7 @@ impl<'a> UtxoCoinWithIguanaPrivKeyBuilder for ZCoinBuilder<'a> { z_spending_key: self.z_spending_key, z_tx_prover: Arc::new(z_tx_prover), light_wallet_db, - consensus_params: self.consensus_params, + consensus_params: self.protocol_info.consensus_params, sync_state_connector, }; @@ -817,7 +835,7 @@ impl<'a> ZCoinBuilder<'a> { secp_priv_key: &'a [u8], db_dir_path: PathBuf, z_spending_key: ExtendedSpendingKey, - consensus_params: ZcoinConsensusParams, + protocol_info: ZcoinProtocolInfo, ) -> ZCoinBuilder<'a> { let utxo_mode = match &z_coin_params.mode { ZcoinRpcMode::Native => UtxoRpcMode::Native, @@ -846,7 +864,7 @@ impl<'a> ZCoinBuilder<'a> { secp_priv_key, db_dir_path, z_spending_key, - consensus_params, + protocol_info, } } } @@ -860,7 +878,7 @@ async fn z_coin_from_conf_and_params_with_z_key( secp_priv_key: &[u8], db_dir_path: PathBuf, z_spending_key: ExtendedSpendingKey, - consensus_params: ZcoinConsensusParams, + protocol_info: ZcoinProtocolInfo, ) -> Result> { let builder = ZCoinBuilder::new( ctx, @@ -870,7 +888,7 @@ async fn z_coin_from_conf_and_params_with_z_key( secp_priv_key, db_dir_path, z_spending_key, - consensus_params, + protocol_info, ); builder.build().await } diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index bfe13b1b19..add11fc1ba 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -17,7 +17,8 @@ use zcash_primitives::transaction::builder::Error as ZTxBuilderError; #[non_exhaustive] pub enum UpdateBlocksCacheErr { GrpcError(tonic::Status), - DbError(SqliteError), + BlocksDbError(SqliteError), + ZcashSqliteError(ZcashClientError), } impl From for UpdateBlocksCacheErr { @@ -25,7 +26,11 @@ impl From for UpdateBlocksCacheErr { } impl From for UpdateBlocksCacheErr { - fn from(err: SqliteError) -> Self { UpdateBlocksCacheErr::DbError(err) } + fn from(err: SqliteError) -> Self { UpdateBlocksCacheErr::BlocksDbError(err) } +} + +impl From for UpdateBlocksCacheErr { + fn from(err: ZcashClientError) -> Self { UpdateBlocksCacheErr::ZcashSqliteError(err) } } #[derive(Debug, Display)] diff --git a/mm2src/coins/z_coin/z_coin_tests.rs b/mm2src/coins/z_coin/z_coin_native_tests.rs similarity index 100% rename from mm2src/coins/z_coin/z_coin_tests.rs rename to mm2src/coins/z_coin/z_coin_native_tests.rs diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 6a752bde42..94f0e79901 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -1,7 +1,7 @@ -use super::{z_coin_errors::*, ZcoinConsensusParams}; +use super::{z_coin_errors::*, CheckPointBlockInfo, ZcoinConsensusParams}; use crate::utxo::utxo_common; use common::executor::Timer; -use common::log::{debug, error, info}; +use common::log::{debug, error, info, LogOnError}; use common::{async_blocking, spawn_abortable, AbortOnDropHandle}; use db_common::sqlite::rusqlite::{params, Connection, Error as SqliteError, NO_PARAMS}; use db_common::sqlite::{query_single_row, run_optimization_pragmas}; @@ -23,8 +23,9 @@ use zcash_client_backend::data_api::error::Error as ChainError; use zcash_client_backend::data_api::{BlockSource, WalletRead, WalletWrite}; use zcash_client_backend::proto::compact_formats::CompactBlock; use zcash_client_sqlite::error::SqliteClientError as ZcashClientError; -use zcash_client_sqlite::wallet::init::{init_accounts_table, init_wallet_db}; +use zcash_client_sqlite::wallet::init::{init_accounts_table, init_blocks_table, init_wallet_db}; use zcash_client_sqlite::WalletDb; +use zcash_primitives::block::BlockHash; use zcash_primitives::consensus::BlockHeight; use zcash_primitives::transaction::TxId; use zcash_primitives::zip32::ExtendedFullViewingKey; @@ -103,7 +104,7 @@ impl BlockDb { Ok(()) } - fn get_latest_block(&self) -> Result> { + fn get_latest_block(&self) -> Result> { Ok(query_single_row( &self.0, "SELECT height FROM compactblocks ORDER BY height DESC LIMIT 1", @@ -147,6 +148,7 @@ pub(super) async fn init_light_client( cache_db_path: PathBuf, wallet_db_path: PathBuf, consensus_params: ZcoinConsensusParams, + check_point_block: Option, evk: ExtendedFullViewingKey, ) -> Result<(AsyncMutex, WalletDbShared), MmError> { let blocks_db = @@ -162,6 +164,15 @@ pub(super) async fn init_light_client( init_wallet_db(&db).map_to_mm(ZcoinLightClientInitError::WalletDbInitFailure)?; if db.get_extended_full_viewing_keys()?.is_empty() { init_accounts_table(&db, &[evk])?; + if let Some(check_point) = check_point_block { + init_blocks_table( + &db, + BlockHeight::from_u32(check_point.height), + BlockHash(check_point.hash.0), + check_point.time, + &check_point.sapling_tree.0, + )?; + } } Ok(db) } @@ -235,7 +246,11 @@ pub enum SyncStatus { current_scanned_block: u64, latest_block: u64, }, - BuildingWalletDb, + BuildingWalletDb { + current_scanned_block: u64, + latest_block: u64, + }, + TemporaryError(String), Finished { block_number: u64, }, @@ -257,46 +272,52 @@ pub struct SaplingSyncLoopHandle { impl SaplingSyncLoopHandle { fn notify_blocks_cache_status(&mut self, current_scanned_block: u64, latest_block: u64) { - if self - .sync_status_notifier + self.sync_status_notifier .try_send(SyncStatus::UpdatingBlocksCache { current_scanned_block, latest_block, }) - .is_err() - { - debug!("No one seems interested in SyncStatus"); - } + .debug_log_with_msg("No one seems interested in SyncStatus"); } - fn notify_building_wallet_db(&mut self) { - if self - .sync_status_notifier - .try_send(SyncStatus::BuildingWalletDb) - .is_err() - { - debug!("No one seems interested in SyncStatus"); - } + fn notify_building_wallet_db(&mut self, current_scanned_block: u64, latest_block: u64) { + self.sync_status_notifier + .try_send(SyncStatus::BuildingWalletDb { + current_scanned_block, + latest_block, + }) + .debug_log_with_msg("No one seems interested in SyncStatus"); + } + + fn notify_on_error(&mut self, error: String) { + self.sync_status_notifier + .try_send(SyncStatus::TemporaryError(error)) + .debug_log_with_msg("No one seems interested in SyncStatus"); } fn notify_sync_finished(&mut self) { - if self - .sync_status_notifier + self.sync_status_notifier .try_send(SyncStatus::Finished { block_number: self.current_block.into(), }) - .is_err() - { - debug!("No one seems interested in SyncStatus"); - } + .debug_log_with_msg("No one seems interested in SyncStatus"); } async fn update_blocks_cache(&mut self) -> Result<(), MmError> { let request = tonic::Request::new(ChainSpec {}); let current_blockchain_block = self.grpc_client.get_latest_block(request).await?; let current_block_in_db = block_in_place(|| self.blocks_db.get_latest_block())?; + let extrema = block_in_place(|| self.wallet_db.lock().block_height_extrema())?; + + let mut from_block = self + .consensus_params + .sapling_activation_height + .max(current_block_in_db + 1) as u64; + + if let Some((_, max_in_wallet)) = extrema { + from_block = from_block.max(max_in_wallet.into()); + } - let from_block = current_block_in_db as u64 + 1; let current_block: u64 = current_blockchain_block.into_inner().height; if current_block >= from_block { @@ -327,7 +348,9 @@ 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 fn scan_blocks(&mut self) -> Result<(), MmError> { - let wallet_guard = self.wallet_db.lock(); + // required to avoid immutable borrow of self + let wallet_db_arc = self.wallet_db.clone(); + let wallet_guard = wallet_db_arc.lock(); let mut wallet_ops = wallet_guard.get_update_ops().expect("get_update_ops always returns Ok"); if let Err(e) = validate_chain( @@ -349,7 +372,20 @@ impl SaplingSyncLoopHandle { } } - scan_cached_blocks(&self.consensus_params, &self.blocks_db, &mut wallet_ops, None)?; + let current_block = BlockHeight::from_u32(self.blocks_db.get_latest_block()?); + loop { + match wallet_ops.block_height_extrema()? { + Some((_, max_in_wallet)) => { + if max_in_wallet >= current_block { + break; + } else { + self.notify_building_wallet_db(max_in_wallet.into(), current_block.into()); + } + }, + None => self.notify_building_wallet_db(0, current_block.into()), + } + scan_cached_blocks(&self.consensus_params, &self.blocks_db, &mut wallet_ops, Some(1000))?; + } Ok(()) } @@ -408,14 +444,14 @@ async fn light_wallet_db_sync_loop(mut sync_handle: SaplingSyncLoopHandle) { loop { if let Err(e) = sync_handle.update_blocks_cache().await { error!("Error {} on blocks cache update", e); + sync_handle.notify_on_error(e.to_string()); Timer::sleep(10.).await; continue; } - sync_handle.notify_building_wallet_db(); - if let Err(e) = block_in_place(|| sync_handle.scan_blocks()) { error!("Error {} on scan_blocks", e); + sync_handle.notify_on_error(e.to_string()); Timer::sleep(10.).await; continue; } diff --git a/mm2src/coins_activation/src/z_coin_activation.rs b/mm2src/coins_activation/src/z_coin_activation.rs index 532bb0fc0f..c1580d6dab 100644 --- a/mm2src/coins_activation/src/z_coin_activation.rs +++ b/mm2src/coins_activation/src/z_coin_activation.rs @@ -6,7 +6,7 @@ use crate::standalone_coin::{InitStandaloneCoinActivationOps, InitStandaloneCoin use async_trait::async_trait; use coins::coin_balance::{EnableCoinBalance, IguanaWalletBalance}; use coins::z_coin::{z_coin_from_conf_and_params, BlockchainScanStopped, SyncStatus, ZCoin, ZCoinBuildError, - ZcoinActivationParams, ZcoinConsensusParams}; + ZcoinActivationParams, ZcoinProtocolInfo}; use coins::{BalanceError, CoinProtocol, MarketCoinOps, RegisterCoinError}; use crypto::hw_rpc_task::{HwRpcTaskAwaitingStatus, HwRpcTaskUserAction}; use crypto::CryptoInitError; @@ -44,7 +44,11 @@ pub enum ZcoinInProgressStatus { current_scanned_block: u64, latest_block: u64, }, - BuildingWalletDb, + BuildingWalletDb { + current_scanned_block: u64, + latest_block: u64, + }, + TemporaryError(String), RequestingWalletBalance, Finishing, /// This status doesn't require the user to send `UserAction`, @@ -141,13 +145,13 @@ impl From for InitStandaloneCoinError { } } -impl TryFromCoinProtocol for ZcoinConsensusParams { +impl TryFromCoinProtocol for ZcoinProtocolInfo { fn try_from_coin_protocol(proto: CoinProtocol) -> Result> where Self: Sized, { match proto { - CoinProtocol::ZHTLC { consensus_params } => Ok(consensus_params), + CoinProtocol::ZHTLC(info) => Ok(info), protocol => MmError::err(protocol), } } @@ -156,7 +160,7 @@ impl TryFromCoinProtocol for ZcoinConsensusParams { #[async_trait] impl InitStandaloneCoinActivationOps for ZCoin { type ActivationRequest = ZcoinActivationParams; - type StandaloneProtocol = ZcoinConsensusParams; + type StandaloneProtocol = ZcoinProtocolInfo; type ActivationResult = ZcoinActivationResult; type ActivationError = ZcoinInitError; type InProgressStatus = ZcoinInProgressStatus; @@ -172,7 +176,7 @@ impl InitStandaloneCoinActivationOps for ZCoin { ticker: String, coin_conf: Json, activation_request: &ZcoinActivationParams, - protocol_info: ZcoinConsensusParams, + protocol_info: ZcoinProtocolInfo, task_handle: &ZcoinRpcTaskHandle, ) -> MmResult { let secp_privkey = ctx.secp256k1_key_pair().private().secret; @@ -196,7 +200,14 @@ impl InitStandaloneCoinActivationOps for ZCoin { current_scanned_block, latest_block, }, - SyncStatus::BuildingWalletDb => ZcoinInProgressStatus::BuildingWalletDb, + SyncStatus::BuildingWalletDb { + current_scanned_block, + latest_block, + } => ZcoinInProgressStatus::BuildingWalletDb { + current_scanned_block, + latest_block, + }, + SyncStatus::TemporaryError(e) => ZcoinInProgressStatus::TemporaryError(e), SyncStatus::Finished { .. } => break, }; task_handle.update_in_progress_status(in_progress_status)?; diff --git a/mm2src/common/log.rs b/mm2src/common/log.rs index 15730285c6..a29af6669a 100644 --- a/mm2src/common/log.rs +++ b/mm2src/common/log.rs @@ -239,6 +239,9 @@ pub trait LogOnError { fn error_log_with_msg(self, msg: &str); fn error_log_passthrough(self) -> Self; + + // Log the error, caller location and the given message to DEBUG level here. + fn debug_log_with_msg(self, msg: &str); } impl LogOnError for Result { @@ -292,6 +295,16 @@ impl LogOnError for Result { } self } + + #[track_caller] + fn debug_log_with_msg(self, msg: &str) { + if let Err(e) = self { + let location = std::panic::Location::caller(); + let file = filename(location.file()); + let line = location.line(); + debug!("{}:{}] {}: {}", file, line, msg, e); + } + } } pub trait TagParam<'a> { diff --git a/mm2src/mm2_main/src/mm2_tests.rs b/mm2src/mm2_main/src/mm2_tests.rs index 39553e51d9..adb40904fa 100644 --- a/mm2src/mm2_main/src/mm2_tests.rs +++ b/mm2src/mm2_main/src/mm2_tests.rs @@ -170,26 +170,15 @@ fn rmd160_from_passphrase(passphrase: &str) -> [u8; 20] { key_pair_from_seed(passphrase).unwrap().public().address_hash().take() } -#[cfg(not(target_arch = "wasm32"))] -fn blocks_cache_path(mm: &MarketMakerIt, seed: &str, coin: &str) -> PathBuf { - let rmd = rmd160_from_passphrase(seed); - let db_name = format!("{}_light_cache.db", coin); - mm.folder.join("DB").join(hex::encode(rmd)).join(db_name) -} - async fn enable_z_coin_light( mm: &MarketMakerIt, coin: &str, electrums: &[&str], lightwalletd_urls: &[&str], - blocks_cache_path: &dyn AsRef, ) -> ZcoinActivationResult { - const TEST_CACHE_ZOMBIE: &str = "../coins/test_cache_zombie.db"; - std::fs::copy(TEST_CACHE_ZOMBIE, blocks_cache_path).unwrap(); - let init = init_z_coin_light(mm, coin, electrums, lightwalletd_urls).await; let init: RpcV2Response = json::from_value(init).unwrap(); - let timeout = now_ms() + 600000; + let timeout = now_ms() + 12000000; loop { if now_ms() > timeout { @@ -202,7 +191,6 @@ async fn enable_z_coin_light( if let InitZcoinStatus::Ready(rpc_result) = status.result { match rpc_result { MmRpcResult::Ok { result } => { - std::fs::copy(blocks_cache_path, TEST_CACHE_ZOMBIE).unwrap(); break result; }, MmRpcResult::Err(e) => panic!("{} initialization error {:?}", coin, e), diff --git a/mm2src/mm2_main/src/mm2_tests/orderbook_sync_tests.rs b/mm2src/mm2_main/src/mm2_tests/orderbook_sync_tests.rs index 13ee876fe9..d2b447eb0c 100644 --- a/mm2src/mm2_main/src/mm2_tests/orderbook_sync_tests.rs +++ b/mm2src/mm2_main/src/mm2_tests/orderbook_sync_tests.rs @@ -1372,7 +1372,6 @@ fn zhtlc_orders_sync_alice_connected_before_creation() { ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, - &blocks_cache_path(&mm_bob, &bob_passphrase, ZOMBIE_TICKER), )); let set_price_json = json!({ @@ -1435,7 +1434,6 @@ fn zhtlc_orders_sync_alice_connected_after_creation() { ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, - &blocks_cache_path(&mm_bob, &bob_passphrase, ZOMBIE_TICKER), )); let set_price_json = json!({ @@ -1464,7 +1462,6 @@ fn zhtlc_orders_sync_alice_connected_after_creation() { ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, - &blocks_cache_path(&mm_alice, &alice_passphrase, ZOMBIE_TICKER), )); let set_price_json = json!({ diff --git a/mm2src/mm2_main/src/mm2_tests/z_coin_tests.rs b/mm2src/mm2_main/src/mm2_tests/z_coin_tests.rs index 868a33ad29..cad12aa317 100644 --- a/mm2src/mm2_main/src/mm2_tests/z_coin_tests.rs +++ b/mm2src/mm2_main/src/mm2_tests/z_coin_tests.rs @@ -1,13 +1,15 @@ use super::*; use common::now_ms; -use mm2_test_helpers::for_tests::{init_withdraw, rick_conf, send_raw_transaction, withdraw_status, z_coin_tx_history, - zombie_conf, Mm2TestConf, RICK, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, +use mm2_test_helpers::for_tests::{init_withdraw, pirate_conf, rick_conf, send_raw_transaction, withdraw_status, + z_coin_tx_history, zombie_conf, Mm2TestConf, ARRR, PIRATE_ELECTRUMS, + PIRATE_LIGHTWALLETD_URLS, RICK, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, ZOMBIE_TICKER}; use std::collections::HashSet; use std::iter::FromIterator; use std::num::NonZeroUsize; const ZOMBIE_TEST_BALANCE_SEED: &str = "zombie test seed"; +const ARRR_TEST_ACTIVATION_SEED: &str = "arrr test activation seed"; const ZOMBIE_TEST_HISTORY_SEED: &str = "zombie test history seed"; const ZOMBIE_TEST_WITHDRAW_SEED: &str = "zombie withdraw test seed"; const ZOMBIE_TRADE_BOB_SEED: &str = "RICK ZOMBIE BOB"; @@ -50,7 +52,6 @@ fn activate_z_coin_light() { ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, - &blocks_cache_path(&mm, ZOMBIE_TEST_BALANCE_SEED, ZOMBIE_TICKER), )); let balance = match activation_result.wallet_balance { @@ -74,7 +75,6 @@ fn test_z_coin_tx_history() { ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, - &blocks_cache_path(&mm, ZOMBIE_TEST_HISTORY_SEED, ZOMBIE_TICKER), )); let tx_history = block_on(z_coin_tx_history(&mm, ZOMBIE_TICKER, 5, None)); @@ -318,7 +318,6 @@ fn withdraw_z_coin_light() { ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, - &blocks_cache_path(&mm, ZOMBIE_TEST_WITHDRAW_SEED, ZOMBIE_TICKER), )); println!("{:?}", activation_result); @@ -360,7 +359,6 @@ fn trade_rick_zombie_light() { ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, - &blocks_cache_path(&mm_bob, bob_passphrase, ZOMBIE_TICKER), )); println!("Bob ZOMBIE activation {:?}", zombie_activation); @@ -393,7 +391,6 @@ fn trade_rick_zombie_light() { ZOMBIE_TICKER, ZOMBIE_ELECTRUMS, ZOMBIE_LIGHTWALLETD_URLS, - &blocks_cache_path(&mm_alice, alice_passphrase, ZOMBIE_TICKER), )); println!("Alice ZOMBIE activation {:?}", zombie_activation); @@ -435,3 +432,27 @@ fn trade_rick_zombie_light() { block_on(mm_alice.wait_for_log(900., |log| log.contains(&format!("[swap uuid={}] Finished", uuid)))).unwrap(); } + +// ignored because it requires a long-running Zcoin initialization process +#[test] +#[ignore] +fn activate_pirate_light() { + let coins = json!([pirate_conf()]); + + let conf = Mm2TestConf::seednode(ARRR_TEST_ACTIVATION_SEED, &coins); + let mm = MarketMakerIt::start(conf.conf, conf.rpc_password, conf.local).unwrap(); + + let activation_result = block_on(enable_z_coin_light( + &mm, + ARRR, + PIRATE_ELECTRUMS, + PIRATE_LIGHTWALLETD_URLS, + )); + + let balance = match activation_result.wallet_balance { + EnableCoinBalance::Iguana(iguana) => iguana, + _ => panic!("Expected EnableCoinBalance::Iguana"), + }; + println!("{:?}", balance); + assert_eq!(balance.balance.spendable, BigDecimal::default()); +} diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index cee2c29dc2..3a7caf0fe7 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -102,8 +102,11 @@ pub const TAKER_ERROR_EVENTS: [&str; 13] = [ pub const RICK: &str = "RICK"; pub const MORTY: &str = "MORTY"; pub const ZOMBIE_TICKER: &str = "ZOMBIE"; +pub const ARRR: &str = "ARRR"; pub const ZOMBIE_ELECTRUMS: &[&str] = &["zombie.sirseven.me:10033"]; pub const ZOMBIE_LIGHTWALLETD_URLS: &[&str] = &["http://zombie.sirseven.me:443"]; +pub const PIRATE_ELECTRUMS: &[&str] = &["pirate.sirseven.me:10032"]; +pub const PIRATE_LIGHTWALLETD_URLS: &[&str] = &["http://pirate.sirseven.me:443"]; const DEFAULT_RPC_PASSWORD: &str = "pass"; pub struct Mm2TestConf { @@ -188,6 +191,41 @@ pub fn zombie_conf() -> Json { }) } +pub fn pirate_conf() -> Json { + json!({ + "coin":"ARRR", + "asset":"PIRATE", + "txversion":4, + "overwintered":1, + "mm2":1, + "protocol":{ + "type":"ZHTLC", + "protocol_data": { + "consensus_params": { + "overwinter_activation_height": 152855, + "sapling_activation_height": 152855, + "blossom_activation_height": null, + "heartwood_activation_height": null, + "canopy_activation_height": null, + "coin_type": 133, + "hrp_sapling_extended_spending_key": "secret-extended-key-main", + "hrp_sapling_extended_full_viewing_key": "zxviews", + "hrp_sapling_payment_address": "zs", + "b58_pubkey_address_prefix": [ 28, 184 ], + "b58_script_address_prefix": [ 28, 189 ] + }, + "check_point_block": { + "height": 2010000, + "time": 1659288887, + "hash": "b9024dc7a9b1bb0fe5c3f84175be91c572706d3268f1dc74bbe5121a00000000", + "sapling_tree": "019b6df2c6f4f42d867ac881f9f728e7954ed2e6922801a60c492b4ff85ef5f0400135609f387dd5034be026b7223ec5a85037b6a9d58f9afac8b7373e2606a5be6f150104bdb768da2504afb2f1963c340668490873885c22a06a7a9ac866320f10030d010e2e8e76a1e8bf8a1146661b48296ff36d5ce2082284193346b8ee7e4ec0e33600012f7f502f94a659eee3425e22a66ab4656fb7791ca0a2ac8a558a5fca7e4fbf630000019a9f3d2f985e10841c71bd70b84bb209a51a15680943842fa232e8ad4dc0b8590001b289928cbcc0c951720f14d35db6ea6383e67e62cebbf6d60103f4b0faadbd63000001ff9a30c61d63bb599e967dcac24ab6fedc0e8daa618a0efbd0314366fa05994200014d7ad3b2f0ee6ec7fa8cb4a0e9fadbaac4a3ed7d07f5643171a8eba26f93fc5a0001efa2884b5610614c3676441010863dc4fa6959f4df7a8018e74b93bb26b9d412014b705396332773077e58f73fe5a4c2c1d7ad2a1058bd5856670fb9529d1cd61c01e29681aab902f9876726a6fada746879e13af24d3675ae53fcc20629a85e196b010b5fd8e7610754075f936463780e85841f3ab8ca2978f9afdf7c2c250f16a75f01db56bc66eb1cd54ec6861e5cf24af2f4a17991556a52ca781007569e95b9842401c03877ecdd98378b321250640a1885604d675aaa50380e49da8cfa6ff7deaf15" + }, + } + }, + "required_confirmations":0 + }) +} + pub fn rick_conf() -> Json { json!({ "coin":"RICK",