From df7778c8c59dbb43b356b6eabc33ee98fce5a14a Mon Sep 17 00:00:00 2001 From: laruh Date: Sun, 22 Dec 2024 18:36:06 +0700 Subject: [PATCH 1/7] impl swap kickstart for eth coin in taker and maker swaps --- mm2src/mm2_main/src/lp_swap.rs | 176 ++++++++++++++++-- mm2src/mm2_main/src/lp_swap/swap_v2_common.rs | 62 +++--- 2 files changed, 187 insertions(+), 51 deletions(-) diff --git a/mm2src/mm2_main/src/lp_swap.rs b/mm2src/mm2_main/src/lp_swap.rs index 58fcbe58ea..348f68882e 100644 --- a/mm2src/mm2_main/src/lp_swap.rs +++ b/mm2src/mm2_main/src/lp_swap.rs @@ -59,8 +59,8 @@ use super::lp_network::P2PRequestResult; use crate::lp_network::{broadcast_p2p_msg, Libp2pPeerId, P2PProcessError, P2PProcessResult, P2PRequestError}; -use crate::lp_swap::maker_swap_v2::{MakerSwapStateMachine, MakerSwapStorage}; -use crate::lp_swap::taker_swap_v2::{TakerSwapStateMachine, TakerSwapStorage}; +use crate::lp_swap::maker_swap_v2::{MakerSwapDbRepr, MakerSwapStateMachine, MakerSwapStorage}; +use crate::lp_swap::taker_swap_v2::{TakerSwapDbRepr, TakerSwapStateMachine, TakerSwapStorage}; use bitcrypto::sha256; use coins::{lp_coinfind, lp_coinfind_or_err, CoinFindError, DexFee, MmCoin, MmCoinEnum, TradeFee, TransactionEnum}; use common::log::{debug, warn}; @@ -115,7 +115,9 @@ mod trade_preimage; #[cfg(target_arch = "wasm32")] mod swap_wasm_db; +use crate::lp_swap::swap_v2_common::{swap_kickstart_handler, GetSwapCoins}; pub use check_balance::{check_other_coin_balance_for_swap, CheckBalanceError, CheckBalanceResult}; +use coins::eth::EthCoin; use coins::utxo::utxo_standard::UtxoStandardCoin; use crypto::secret_hash_algo::SecretHashAlgo; use crypto::CryptoCtx; @@ -130,7 +132,7 @@ use pubkey_banning::BanReason; pub use pubkey_banning::{ban_pubkey_rpc, is_pubkey_banned, list_banned_pubkeys_rpc, unban_pubkeys_rpc}; pub use recreate_swap_data::recreate_swap_data; pub use saved_swap::{SavedSwap, SavedSwapError, SavedSwapIo, SavedSwapResult}; -use swap_v2_common::{get_unfinished_swaps_uuids, swap_kickstart_handler, ActiveSwapV2Info}; +use swap_v2_common::{get_unfinished_swaps_uuids, swap_kickstart_coins, ActiveSwapV2Info}; use swap_v2_pb::*; use swap_v2_rpcs::{get_maker_swap_data_for_rpc, get_swap_type, get_taker_swap_data_for_rpc}; pub use swap_watcher::{process_watcher_msg, watcher_topic, TakerSwapWatcherData, MAKER_PAYMENT_SPEND_FOUND_LOG, @@ -1358,9 +1360,20 @@ pub async fn swap_kick_starts(ctx: MmArc) -> Result, String> { try_s!(migrate_swaps_data(&ctx).await); let mut coins = HashSet::new(); + + kickstart_legacy_swaps(&ctx, &mut coins).await?; + + kickstart_maker_swaps(&ctx, &mut coins).await?; + + kickstart_taker_swaps(&ctx, &mut coins).await?; + + Ok(coins) +} + +async fn kickstart_legacy_swaps(ctx: &MmArc, coins: &mut HashSet) -> Result<(), String> { let legacy_unfinished_uuids = try_s!(get_unfinished_swaps_uuids(ctx.clone(), LEGACY_SWAP_TYPE).await); for uuid in legacy_unfinished_uuids { - let swap = match SavedSwap::load_my_swap_from_db(&ctx, uuid).await { + let swap = match SavedSwap::load_my_swap_from_db(ctx, uuid).await { Ok(Some(s)) => s, Ok(None) => { warn!("Swap {} is indexed, but doesn't exist in DB", uuid); @@ -1372,6 +1385,7 @@ pub async fn swap_kick_starts(ctx: MmArc) -> Result, String> { }, }; info!("Kick starting the swap {}", swap.uuid()); + let maker_coin_ticker = match swap.maker_coin_ticker() { Ok(t) => t, Err(e) => { @@ -1379,6 +1393,7 @@ pub async fn swap_kick_starts(ctx: MmArc) -> Result, String> { continue; }, }; + let taker_coin_ticker = match swap.taker_coin_ticker() { Ok(t) => t, Err(e) => { @@ -1386,15 +1401,20 @@ pub async fn swap_kick_starts(ctx: MmArc) -> Result, String> { continue; }, }; + coins.insert(maker_coin_ticker.clone()); coins.insert(taker_coin_ticker.clone()); let fut = kickstart_thread_handler(ctx.clone(), swap, maker_coin_ticker, taker_coin_ticker); ctx.spawner().spawn(fut); } + Ok(()) +} +async fn kickstart_maker_swaps(ctx: &MmArc, coins: &mut HashSet) -> Result<(), String> { let maker_swap_storage = MakerSwapStorage::new(ctx.clone()); let unfinished_maker_uuids = try_s!(maker_swap_storage.get_unfinished().await); + for maker_uuid in unfinished_maker_uuids { info!("Trying to kickstart maker swap {}", maker_uuid); let maker_swap_repr = match maker_swap_storage.get_repr(maker_uuid).await { @@ -1409,17 +1429,25 @@ pub async fn swap_kick_starts(ctx: MmArc) -> Result, String> { coins.insert(maker_swap_repr.maker_coin.clone()); coins.insert(maker_swap_repr.taker_coin.clone()); - let fut = swap_kickstart_handler::>( - ctx.clone(), - maker_swap_repr, - maker_swap_storage.clone(), - maker_uuid, - ); - ctx.spawner().spawn(fut); + if let Some((maker_coin, taker_coin)) = swap_kickstart_coins(ctx, &maker_swap_repr, &maker_uuid).await { + spawn_swap_kickstart_handler_for_maker( + ctx, + maker_swap_repr, + maker_swap_storage.clone(), + maker_uuid, + maker_coin, + taker_coin, + ) + .await; + } } + Ok(()) +} +async fn kickstart_taker_swaps(ctx: &MmArc, coins: &mut HashSet) -> Result<(), String> { let taker_swap_storage = TakerSwapStorage::new(ctx.clone()); let unfinished_taker_uuids = try_s!(taker_swap_storage.get_unfinished().await); + for taker_uuid in unfinished_taker_uuids { info!("Trying to kickstart taker swap {}", taker_uuid); let taker_swap_repr = match taker_swap_storage.get_repr(taker_uuid).await { @@ -1434,15 +1462,125 @@ pub async fn swap_kick_starts(ctx: MmArc) -> Result, String> { coins.insert(taker_swap_repr.maker_coin.clone()); coins.insert(taker_swap_repr.taker_coin.clone()); - let fut = swap_kickstart_handler::>( - ctx.clone(), - taker_swap_repr, - taker_swap_storage.clone(), - taker_uuid, - ); - ctx.spawner().spawn(fut); + if let Some((maker_coin, taker_coin)) = swap_kickstart_coins(ctx, &taker_swap_repr, &taker_uuid).await { + spawn_swap_kickstart_handler_for_taker( + ctx, + taker_swap_repr, + taker_swap_storage.clone(), + taker_uuid, + maker_coin, + taker_coin, + ) + .await; + } } - Ok(coins) + Ok(()) +} + +async fn spawn_swap_kickstart_handler_for_maker( + ctx: &MmArc, + maker_swap_repr: MakerSwapDbRepr, + maker_swap_storage: MakerSwapStorage, + maker_uuid: Uuid, + maker_coin: MmCoinEnum, + taker_coin: MmCoinEnum, +) { + match (maker_coin, taker_coin) { + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => { + let fut = swap_kickstart_handler::< + MakerSwapStateMachine, + UtxoStandardCoin, + UtxoStandardCoin, + >(maker_swap_repr, maker_swap_storage, maker_uuid, m, t); + ctx.spawner().spawn(fut); + }, + (MmCoinEnum::EthCoin(m), MmCoinEnum::EthCoin(t)) => { + let fut = swap_kickstart_handler::, EthCoin, EthCoin>( + maker_swap_repr, + maker_swap_storage, + maker_uuid, + m, + t, + ); + ctx.spawner().spawn(fut); + }, + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::EthCoin(t)) => { + let fut = swap_kickstart_handler::< + MakerSwapStateMachine, + UtxoStandardCoin, + EthCoin, + >(maker_swap_repr, maker_swap_storage, maker_uuid, m, t); + ctx.spawner().spawn(fut); + }, + (MmCoinEnum::EthCoin(m), MmCoinEnum::UtxoCoin(t)) => { + let fut = swap_kickstart_handler::< + MakerSwapStateMachine, + EthCoin, + UtxoStandardCoin, + >(maker_swap_repr, maker_swap_storage, maker_uuid, m, t); + ctx.spawner().spawn(fut); + }, + _ => { + error!( + "V2 swaps are not currently supported for {}/{} pair", + maker_swap_repr.maker_coin(), + maker_swap_repr.taker_coin() + ); + }, + }; +} + +async fn spawn_swap_kickstart_handler_for_taker( + ctx: &MmArc, + taker_swap_repr: TakerSwapDbRepr, + taker_swap_storage: TakerSwapStorage, + taker_uuid: Uuid, + maker_coin: MmCoinEnum, + taker_coin: MmCoinEnum, +) { + match (maker_coin, taker_coin) { + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => { + let fut = swap_kickstart_handler::< + TakerSwapStateMachine, + UtxoStandardCoin, + UtxoStandardCoin, + >(taker_swap_repr, taker_swap_storage, taker_uuid, m, t); + ctx.spawner().spawn(fut); + }, + (MmCoinEnum::EthCoin(m), MmCoinEnum::EthCoin(t)) => { + let fut = swap_kickstart_handler::, EthCoin, EthCoin>( + taker_swap_repr, + taker_swap_storage, + taker_uuid, + m, + t, + ); + ctx.spawner().spawn(fut); + }, + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::EthCoin(t)) => { + let fut = swap_kickstart_handler::< + TakerSwapStateMachine, + UtxoStandardCoin, + EthCoin, + >(taker_swap_repr, taker_swap_storage, taker_uuid, m, t); + ctx.spawner().spawn(fut); + }, + (MmCoinEnum::EthCoin(m), MmCoinEnum::UtxoCoin(t)) => { + let fut = swap_kickstart_handler::< + TakerSwapStateMachine, + EthCoin, + UtxoStandardCoin, + >(taker_swap_repr, taker_swap_storage, taker_uuid, m, t); + ctx.spawner().spawn(fut); + }, + _ => { + error!( + "V2 swaps are not currently supported for {}/{} pair", + taker_swap_repr.maker_coin(), + taker_swap_repr.taker_coin() + ); + }, + }; } async fn kickstart_thread_handler(ctx: MmArc, swap: SavedSwap, maker_coin_ticker: String, taker_coin_ticker: String) { diff --git a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs index 52f1690335..4b2fb78591 100644 --- a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs +++ b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs @@ -1,8 +1,7 @@ use crate::lp_network::{subscribe_to_topic, unsubscribe_from_topic}; use crate::lp_swap::swap_lock::{SwapLock, SwapLockError, SwapLockOps}; use crate::lp_swap::{swap_v2_topic, SwapsContext}; -use coins::utxo::utxo_standard::UtxoStandardCoin; -use coins::{lp_coinfind, MmCoinEnum}; +use coins::{lp_coinfind, MakerCoinSwapOpsV2, MmCoin, MmCoinEnum, TakerCoinSwapOpsV2}; use common::executor::abortable_queue::AbortableQueue; use common::executor::{SpawnFuture, Timer}; use common::log::{error, info, warn}; @@ -292,25 +291,17 @@ pub(super) trait GetSwapCoins { fn taker_coin(&self) -> &str; } -/// Generic function for upgraded swaps kickstart handling. -/// It is implemented only for UtxoStandardCoin/UtxoStandardCoin case temporary. -pub(super) async fn swap_kickstart_handler< - T: StorableStateMachine>, ->( - ctx: MmArc, - swap_repr: ::DbRepr, - storage: T::Storage, - uuid: ::MachineId, -) where - ::MachineId: Copy + std::fmt::Display, - ::DbRepr: GetSwapCoins, - T::Error: std::fmt::Display, - T::RecreateError: std::fmt::Display, -{ +/// Attempts to find and return the maker and taker coins required for the swap to proceed. +/// If a coin is not activated, it logs the information and retries until the coin is found or an error occurs. +pub(super) async fn swap_kickstart_coins( + ctx: &MmArc, + swap_repr: &T, + uuid: &Uuid, +) -> Option<(MmCoinEnum, MmCoinEnum)> { let taker_coin_ticker = swap_repr.taker_coin(); let taker_coin = loop { - match lp_coinfind(&ctx, taker_coin_ticker).await { + match lp_coinfind(ctx, taker_coin_ticker).await { Ok(Some(c)) => break c, Ok(None) => { info!( @@ -321,7 +312,7 @@ pub(super) async fn swap_kickstart_handler< }, Err(e) => { error!("Error {} on {} find attempt", e, taker_coin_ticker); - return; + return None; }, }; }; @@ -329,7 +320,7 @@ pub(super) async fn swap_kickstart_handler< let maker_coin_ticker = swap_repr.maker_coin(); let maker_coin = loop { - match lp_coinfind(&ctx, maker_coin_ticker).await { + match lp_coinfind(ctx, maker_coin_ticker).await { Ok(Some(c)) => break c, Ok(None) => { info!( @@ -340,23 +331,30 @@ pub(super) async fn swap_kickstart_handler< }, Err(e) => { error!("Error {} on {} find attempt", e, maker_coin_ticker); - return; + return None; }, }; }; - // TODO add ETH support - let (maker_coin, taker_coin) = match (maker_coin, taker_coin) { - (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => (m, t), - _ => { - error!( - "V2 swaps are not currently supported for {}/{} pair", - maker_coin_ticker, taker_coin_ticker - ); - return; - }, - }; + Some((maker_coin, taker_coin)) +} +/// Handles the recreation and kickstart of a swap state machine. +pub(super) async fn swap_kickstart_handler< + T: StorableStateMachine>, + MakerCoin: MmCoin + MakerCoinSwapOpsV2, + TakerCoin: MmCoin + TakerCoinSwapOpsV2, +>( + swap_repr: ::DbRepr, + storage: T::Storage, + uuid: ::MachineId, + maker_coin: MakerCoin, + taker_coin: TakerCoin, +) where + ::MachineId: Copy + std::fmt::Display, + T::Error: std::fmt::Display, + T::RecreateError: std::fmt::Display, +{ let recreate_context = SwapRecreateCtx { maker_coin, taker_coin }; let (mut state_machine, state) = match T::recreate_machine(uuid, storage, swap_repr, recreate_context).await { From f65d6a233ba880ee6b379004c0a5c165da54d61b Mon Sep 17 00:00:00 2001 From: laruh Date: Mon, 23 Dec 2024 14:07:11 +0700 Subject: [PATCH 2/7] Revert "impl swap kickstart for eth coin in taker and maker swaps" This reverts commit df7778c8c59dbb43b356b6eabc33ee98fce5a14a. --- mm2src/mm2_main/src/lp_swap.rs | 176 ++---------------- mm2src/mm2_main/src/lp_swap/swap_v2_common.rs | 62 +++--- 2 files changed, 51 insertions(+), 187 deletions(-) diff --git a/mm2src/mm2_main/src/lp_swap.rs b/mm2src/mm2_main/src/lp_swap.rs index 348f68882e..58fcbe58ea 100644 --- a/mm2src/mm2_main/src/lp_swap.rs +++ b/mm2src/mm2_main/src/lp_swap.rs @@ -59,8 +59,8 @@ use super::lp_network::P2PRequestResult; use crate::lp_network::{broadcast_p2p_msg, Libp2pPeerId, P2PProcessError, P2PProcessResult, P2PRequestError}; -use crate::lp_swap::maker_swap_v2::{MakerSwapDbRepr, MakerSwapStateMachine, MakerSwapStorage}; -use crate::lp_swap::taker_swap_v2::{TakerSwapDbRepr, TakerSwapStateMachine, TakerSwapStorage}; +use crate::lp_swap::maker_swap_v2::{MakerSwapStateMachine, MakerSwapStorage}; +use crate::lp_swap::taker_swap_v2::{TakerSwapStateMachine, TakerSwapStorage}; use bitcrypto::sha256; use coins::{lp_coinfind, lp_coinfind_or_err, CoinFindError, DexFee, MmCoin, MmCoinEnum, TradeFee, TransactionEnum}; use common::log::{debug, warn}; @@ -115,9 +115,7 @@ mod trade_preimage; #[cfg(target_arch = "wasm32")] mod swap_wasm_db; -use crate::lp_swap::swap_v2_common::{swap_kickstart_handler, GetSwapCoins}; pub use check_balance::{check_other_coin_balance_for_swap, CheckBalanceError, CheckBalanceResult}; -use coins::eth::EthCoin; use coins::utxo::utxo_standard::UtxoStandardCoin; use crypto::secret_hash_algo::SecretHashAlgo; use crypto::CryptoCtx; @@ -132,7 +130,7 @@ use pubkey_banning::BanReason; pub use pubkey_banning::{ban_pubkey_rpc, is_pubkey_banned, list_banned_pubkeys_rpc, unban_pubkeys_rpc}; pub use recreate_swap_data::recreate_swap_data; pub use saved_swap::{SavedSwap, SavedSwapError, SavedSwapIo, SavedSwapResult}; -use swap_v2_common::{get_unfinished_swaps_uuids, swap_kickstart_coins, ActiveSwapV2Info}; +use swap_v2_common::{get_unfinished_swaps_uuids, swap_kickstart_handler, ActiveSwapV2Info}; use swap_v2_pb::*; use swap_v2_rpcs::{get_maker_swap_data_for_rpc, get_swap_type, get_taker_swap_data_for_rpc}; pub use swap_watcher::{process_watcher_msg, watcher_topic, TakerSwapWatcherData, MAKER_PAYMENT_SPEND_FOUND_LOG, @@ -1360,20 +1358,9 @@ pub async fn swap_kick_starts(ctx: MmArc) -> Result, String> { try_s!(migrate_swaps_data(&ctx).await); let mut coins = HashSet::new(); - - kickstart_legacy_swaps(&ctx, &mut coins).await?; - - kickstart_maker_swaps(&ctx, &mut coins).await?; - - kickstart_taker_swaps(&ctx, &mut coins).await?; - - Ok(coins) -} - -async fn kickstart_legacy_swaps(ctx: &MmArc, coins: &mut HashSet) -> Result<(), String> { let legacy_unfinished_uuids = try_s!(get_unfinished_swaps_uuids(ctx.clone(), LEGACY_SWAP_TYPE).await); for uuid in legacy_unfinished_uuids { - let swap = match SavedSwap::load_my_swap_from_db(ctx, uuid).await { + let swap = match SavedSwap::load_my_swap_from_db(&ctx, uuid).await { Ok(Some(s)) => s, Ok(None) => { warn!("Swap {} is indexed, but doesn't exist in DB", uuid); @@ -1385,7 +1372,6 @@ async fn kickstart_legacy_swaps(ctx: &MmArc, coins: &mut HashSet) -> Res }, }; info!("Kick starting the swap {}", swap.uuid()); - let maker_coin_ticker = match swap.maker_coin_ticker() { Ok(t) => t, Err(e) => { @@ -1393,7 +1379,6 @@ async fn kickstart_legacy_swaps(ctx: &MmArc, coins: &mut HashSet) -> Res continue; }, }; - let taker_coin_ticker = match swap.taker_coin_ticker() { Ok(t) => t, Err(e) => { @@ -1401,20 +1386,15 @@ async fn kickstart_legacy_swaps(ctx: &MmArc, coins: &mut HashSet) -> Res continue; }, }; - coins.insert(maker_coin_ticker.clone()); coins.insert(taker_coin_ticker.clone()); let fut = kickstart_thread_handler(ctx.clone(), swap, maker_coin_ticker, taker_coin_ticker); ctx.spawner().spawn(fut); } - Ok(()) -} -async fn kickstart_maker_swaps(ctx: &MmArc, coins: &mut HashSet) -> Result<(), String> { let maker_swap_storage = MakerSwapStorage::new(ctx.clone()); let unfinished_maker_uuids = try_s!(maker_swap_storage.get_unfinished().await); - for maker_uuid in unfinished_maker_uuids { info!("Trying to kickstart maker swap {}", maker_uuid); let maker_swap_repr = match maker_swap_storage.get_repr(maker_uuid).await { @@ -1429,25 +1409,17 @@ async fn kickstart_maker_swaps(ctx: &MmArc, coins: &mut HashSet) -> Resu coins.insert(maker_swap_repr.maker_coin.clone()); coins.insert(maker_swap_repr.taker_coin.clone()); - if let Some((maker_coin, taker_coin)) = swap_kickstart_coins(ctx, &maker_swap_repr, &maker_uuid).await { - spawn_swap_kickstart_handler_for_maker( - ctx, - maker_swap_repr, - maker_swap_storage.clone(), - maker_uuid, - maker_coin, - taker_coin, - ) - .await; - } + let fut = swap_kickstart_handler::>( + ctx.clone(), + maker_swap_repr, + maker_swap_storage.clone(), + maker_uuid, + ); + ctx.spawner().spawn(fut); } - Ok(()) -} -async fn kickstart_taker_swaps(ctx: &MmArc, coins: &mut HashSet) -> Result<(), String> { let taker_swap_storage = TakerSwapStorage::new(ctx.clone()); let unfinished_taker_uuids = try_s!(taker_swap_storage.get_unfinished().await); - for taker_uuid in unfinished_taker_uuids { info!("Trying to kickstart taker swap {}", taker_uuid); let taker_swap_repr = match taker_swap_storage.get_repr(taker_uuid).await { @@ -1462,125 +1434,15 @@ async fn kickstart_taker_swaps(ctx: &MmArc, coins: &mut HashSet) -> Resu coins.insert(taker_swap_repr.maker_coin.clone()); coins.insert(taker_swap_repr.taker_coin.clone()); - if let Some((maker_coin, taker_coin)) = swap_kickstart_coins(ctx, &taker_swap_repr, &taker_uuid).await { - spawn_swap_kickstart_handler_for_taker( - ctx, - taker_swap_repr, - taker_swap_storage.clone(), - taker_uuid, - maker_coin, - taker_coin, - ) - .await; - } + let fut = swap_kickstart_handler::>( + ctx.clone(), + taker_swap_repr, + taker_swap_storage.clone(), + taker_uuid, + ); + ctx.spawner().spawn(fut); } - Ok(()) -} - -async fn spawn_swap_kickstart_handler_for_maker( - ctx: &MmArc, - maker_swap_repr: MakerSwapDbRepr, - maker_swap_storage: MakerSwapStorage, - maker_uuid: Uuid, - maker_coin: MmCoinEnum, - taker_coin: MmCoinEnum, -) { - match (maker_coin, taker_coin) { - (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => { - let fut = swap_kickstart_handler::< - MakerSwapStateMachine, - UtxoStandardCoin, - UtxoStandardCoin, - >(maker_swap_repr, maker_swap_storage, maker_uuid, m, t); - ctx.spawner().spawn(fut); - }, - (MmCoinEnum::EthCoin(m), MmCoinEnum::EthCoin(t)) => { - let fut = swap_kickstart_handler::, EthCoin, EthCoin>( - maker_swap_repr, - maker_swap_storage, - maker_uuid, - m, - t, - ); - ctx.spawner().spawn(fut); - }, - (MmCoinEnum::UtxoCoin(m), MmCoinEnum::EthCoin(t)) => { - let fut = swap_kickstart_handler::< - MakerSwapStateMachine, - UtxoStandardCoin, - EthCoin, - >(maker_swap_repr, maker_swap_storage, maker_uuid, m, t); - ctx.spawner().spawn(fut); - }, - (MmCoinEnum::EthCoin(m), MmCoinEnum::UtxoCoin(t)) => { - let fut = swap_kickstart_handler::< - MakerSwapStateMachine, - EthCoin, - UtxoStandardCoin, - >(maker_swap_repr, maker_swap_storage, maker_uuid, m, t); - ctx.spawner().spawn(fut); - }, - _ => { - error!( - "V2 swaps are not currently supported for {}/{} pair", - maker_swap_repr.maker_coin(), - maker_swap_repr.taker_coin() - ); - }, - }; -} - -async fn spawn_swap_kickstart_handler_for_taker( - ctx: &MmArc, - taker_swap_repr: TakerSwapDbRepr, - taker_swap_storage: TakerSwapStorage, - taker_uuid: Uuid, - maker_coin: MmCoinEnum, - taker_coin: MmCoinEnum, -) { - match (maker_coin, taker_coin) { - (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => { - let fut = swap_kickstart_handler::< - TakerSwapStateMachine, - UtxoStandardCoin, - UtxoStandardCoin, - >(taker_swap_repr, taker_swap_storage, taker_uuid, m, t); - ctx.spawner().spawn(fut); - }, - (MmCoinEnum::EthCoin(m), MmCoinEnum::EthCoin(t)) => { - let fut = swap_kickstart_handler::, EthCoin, EthCoin>( - taker_swap_repr, - taker_swap_storage, - taker_uuid, - m, - t, - ); - ctx.spawner().spawn(fut); - }, - (MmCoinEnum::UtxoCoin(m), MmCoinEnum::EthCoin(t)) => { - let fut = swap_kickstart_handler::< - TakerSwapStateMachine, - UtxoStandardCoin, - EthCoin, - >(taker_swap_repr, taker_swap_storage, taker_uuid, m, t); - ctx.spawner().spawn(fut); - }, - (MmCoinEnum::EthCoin(m), MmCoinEnum::UtxoCoin(t)) => { - let fut = swap_kickstart_handler::< - TakerSwapStateMachine, - EthCoin, - UtxoStandardCoin, - >(taker_swap_repr, taker_swap_storage, taker_uuid, m, t); - ctx.spawner().spawn(fut); - }, - _ => { - error!( - "V2 swaps are not currently supported for {}/{} pair", - taker_swap_repr.maker_coin(), - taker_swap_repr.taker_coin() - ); - }, - }; + Ok(coins) } async fn kickstart_thread_handler(ctx: MmArc, swap: SavedSwap, maker_coin_ticker: String, taker_coin_ticker: String) { diff --git a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs index 4b2fb78591..52f1690335 100644 --- a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs +++ b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs @@ -1,7 +1,8 @@ use crate::lp_network::{subscribe_to_topic, unsubscribe_from_topic}; use crate::lp_swap::swap_lock::{SwapLock, SwapLockError, SwapLockOps}; use crate::lp_swap::{swap_v2_topic, SwapsContext}; -use coins::{lp_coinfind, MakerCoinSwapOpsV2, MmCoin, MmCoinEnum, TakerCoinSwapOpsV2}; +use coins::utxo::utxo_standard::UtxoStandardCoin; +use coins::{lp_coinfind, MmCoinEnum}; use common::executor::abortable_queue::AbortableQueue; use common::executor::{SpawnFuture, Timer}; use common::log::{error, info, warn}; @@ -291,17 +292,25 @@ pub(super) trait GetSwapCoins { fn taker_coin(&self) -> &str; } -/// Attempts to find and return the maker and taker coins required for the swap to proceed. -/// If a coin is not activated, it logs the information and retries until the coin is found or an error occurs. -pub(super) async fn swap_kickstart_coins( - ctx: &MmArc, - swap_repr: &T, - uuid: &Uuid, -) -> Option<(MmCoinEnum, MmCoinEnum)> { +/// Generic function for upgraded swaps kickstart handling. +/// It is implemented only for UtxoStandardCoin/UtxoStandardCoin case temporary. +pub(super) async fn swap_kickstart_handler< + T: StorableStateMachine>, +>( + ctx: MmArc, + swap_repr: ::DbRepr, + storage: T::Storage, + uuid: ::MachineId, +) where + ::MachineId: Copy + std::fmt::Display, + ::DbRepr: GetSwapCoins, + T::Error: std::fmt::Display, + T::RecreateError: std::fmt::Display, +{ let taker_coin_ticker = swap_repr.taker_coin(); let taker_coin = loop { - match lp_coinfind(ctx, taker_coin_ticker).await { + match lp_coinfind(&ctx, taker_coin_ticker).await { Ok(Some(c)) => break c, Ok(None) => { info!( @@ -312,7 +321,7 @@ pub(super) async fn swap_kickstart_coins( }, Err(e) => { error!("Error {} on {} find attempt", e, taker_coin_ticker); - return None; + return; }, }; }; @@ -320,7 +329,7 @@ pub(super) async fn swap_kickstart_coins( let maker_coin_ticker = swap_repr.maker_coin(); let maker_coin = loop { - match lp_coinfind(ctx, maker_coin_ticker).await { + match lp_coinfind(&ctx, maker_coin_ticker).await { Ok(Some(c)) => break c, Ok(None) => { info!( @@ -331,30 +340,23 @@ pub(super) async fn swap_kickstart_coins( }, Err(e) => { error!("Error {} on {} find attempt", e, maker_coin_ticker); - return None; + return; }, }; }; - Some((maker_coin, taker_coin)) -} + // TODO add ETH support + let (maker_coin, taker_coin) = match (maker_coin, taker_coin) { + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => (m, t), + _ => { + error!( + "V2 swaps are not currently supported for {}/{} pair", + maker_coin_ticker, taker_coin_ticker + ); + return; + }, + }; -/// Handles the recreation and kickstart of a swap state machine. -pub(super) async fn swap_kickstart_handler< - T: StorableStateMachine>, - MakerCoin: MmCoin + MakerCoinSwapOpsV2, - TakerCoin: MmCoin + TakerCoinSwapOpsV2, ->( - swap_repr: ::DbRepr, - storage: T::Storage, - uuid: ::MachineId, - maker_coin: MakerCoin, - taker_coin: TakerCoin, -) where - ::MachineId: Copy + std::fmt::Display, - T::Error: std::fmt::Display, - T::RecreateError: std::fmt::Display, -{ let recreate_context = SwapRecreateCtx { maker_coin, taker_coin }; let (mut state_machine, state) = match T::recreate_machine(uuid, storage, swap_repr, recreate_context).await { From 676d09c4b574f9f20d7e7f16e1097c7d7427d5cd Mon Sep 17 00:00:00 2001 From: laruh Date: Sun, 22 Dec 2024 21:48:42 +0700 Subject: [PATCH 3/7] refactor and spawn futures from swap_kickstart_handler_for_maker and swap_kickstart_handler_for_taker in swap_kick_starts func --- mm2src/mm2_main/src/lp_swap.rs | 24 +-- mm2src/mm2_main/src/lp_swap/swap_v2_common.rs | 160 ++++++++++++++---- 2 files changed, 137 insertions(+), 47 deletions(-) diff --git a/mm2src/mm2_main/src/lp_swap.rs b/mm2src/mm2_main/src/lp_swap.rs index 58fcbe58ea..9feb63cad5 100644 --- a/mm2src/mm2_main/src/lp_swap.rs +++ b/mm2src/mm2_main/src/lp_swap.rs @@ -59,8 +59,8 @@ use super::lp_network::P2PRequestResult; use crate::lp_network::{broadcast_p2p_msg, Libp2pPeerId, P2PProcessError, P2PProcessResult, P2PRequestError}; -use crate::lp_swap::maker_swap_v2::{MakerSwapStateMachine, MakerSwapStorage}; -use crate::lp_swap::taker_swap_v2::{TakerSwapStateMachine, TakerSwapStorage}; +use crate::lp_swap::maker_swap_v2::MakerSwapStorage; +use crate::lp_swap::taker_swap_v2::TakerSwapStorage; use bitcrypto::sha256; use coins::{lp_coinfind, lp_coinfind_or_err, CoinFindError, DexFee, MmCoin, MmCoinEnum, TradeFee, TransactionEnum}; use common::log::{debug, warn}; @@ -116,7 +116,6 @@ mod trade_preimage; #[cfg(target_arch = "wasm32")] mod swap_wasm_db; pub use check_balance::{check_other_coin_balance_for_swap, CheckBalanceError, CheckBalanceResult}; -use coins::utxo::utxo_standard::UtxoStandardCoin; use crypto::secret_hash_algo::SecretHashAlgo; use crypto::CryptoCtx; use keys::{KeyPair, SECP_SIGN, SECP_VERIFY}; @@ -130,7 +129,8 @@ use pubkey_banning::BanReason; pub use pubkey_banning::{ban_pubkey_rpc, is_pubkey_banned, list_banned_pubkeys_rpc, unban_pubkeys_rpc}; pub use recreate_swap_data::recreate_swap_data; pub use saved_swap::{SavedSwap, SavedSwapError, SavedSwapIo, SavedSwapResult}; -use swap_v2_common::{get_unfinished_swaps_uuids, swap_kickstart_handler, ActiveSwapV2Info}; +use swap_v2_common::{get_unfinished_swaps_uuids, swap_kickstart_handler_for_maker, swap_kickstart_handler_for_taker, + ActiveSwapV2Info}; use swap_v2_pb::*; use swap_v2_rpcs::{get_maker_swap_data_for_rpc, get_swap_type, get_taker_swap_data_for_rpc}; pub use swap_watcher::{process_watcher_msg, watcher_topic, TakerSwapWatcherData, MAKER_PAYMENT_SPEND_FOUND_LOG, @@ -1409,12 +1409,8 @@ pub async fn swap_kick_starts(ctx: MmArc) -> Result, String> { coins.insert(maker_swap_repr.maker_coin.clone()); coins.insert(maker_swap_repr.taker_coin.clone()); - let fut = swap_kickstart_handler::>( - ctx.clone(), - maker_swap_repr, - maker_swap_storage.clone(), - maker_uuid, - ); + let fut = + swap_kickstart_handler_for_maker(ctx.clone(), maker_swap_repr, maker_swap_storage.clone(), maker_uuid); ctx.spawner().spawn(fut); } @@ -1434,12 +1430,8 @@ pub async fn swap_kick_starts(ctx: MmArc) -> Result, String> { coins.insert(taker_swap_repr.maker_coin.clone()); coins.insert(taker_swap_repr.taker_coin.clone()); - let fut = swap_kickstart_handler::>( - ctx.clone(), - taker_swap_repr, - taker_swap_storage.clone(), - taker_uuid, - ); + let fut = + swap_kickstart_handler_for_taker(ctx.clone(), taker_swap_repr, taker_swap_storage.clone(), taker_uuid); ctx.spawner().spawn(fut); } Ok(coins) diff --git a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs index 52f1690335..4a690ab06c 100644 --- a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs +++ b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs @@ -1,8 +1,11 @@ use crate::lp_network::{subscribe_to_topic, unsubscribe_from_topic}; +use crate::lp_swap::maker_swap_v2::{MakerSwapDbRepr, MakerSwapStateMachine, MakerSwapStorage}; use crate::lp_swap::swap_lock::{SwapLock, SwapLockError, SwapLockOps}; +use crate::lp_swap::taker_swap_v2::{TakerSwapDbRepr, TakerSwapStateMachine, TakerSwapStorage}; use crate::lp_swap::{swap_v2_topic, SwapsContext}; +use coins::eth::EthCoin; use coins::utxo::utxo_standard::UtxoStandardCoin; -use coins::{lp_coinfind, MmCoinEnum}; +use coins::{lp_coinfind, MakerCoinSwapOpsV2, MmCoin, MmCoinEnum, TakerCoinSwapOpsV2}; use common::executor::abortable_queue::AbortableQueue; use common::executor::{SpawnFuture, Timer}; use common::log::{error, info, warn}; @@ -292,25 +295,17 @@ pub(super) trait GetSwapCoins { fn taker_coin(&self) -> &str; } -/// Generic function for upgraded swaps kickstart handling. -/// It is implemented only for UtxoStandardCoin/UtxoStandardCoin case temporary. -pub(super) async fn swap_kickstart_handler< - T: StorableStateMachine>, ->( - ctx: MmArc, - swap_repr: ::DbRepr, - storage: T::Storage, - uuid: ::MachineId, -) where - ::MachineId: Copy + std::fmt::Display, - ::DbRepr: GetSwapCoins, - T::Error: std::fmt::Display, - T::RecreateError: std::fmt::Display, -{ +/// Attempts to find and return the maker and taker coins required for the swap to proceed. +/// If a coin is not activated, it logs the information and retries until the coin is found or an error occurs. +pub(super) async fn swap_kickstart_coins( + ctx: &MmArc, + swap_repr: &T, + uuid: &Uuid, +) -> Option<(MmCoinEnum, MmCoinEnum)> { let taker_coin_ticker = swap_repr.taker_coin(); let taker_coin = loop { - match lp_coinfind(&ctx, taker_coin_ticker).await { + match lp_coinfind(ctx, taker_coin_ticker).await { Ok(Some(c)) => break c, Ok(None) => { info!( @@ -321,7 +316,7 @@ pub(super) async fn swap_kickstart_handler< }, Err(e) => { error!("Error {} on {} find attempt", e, taker_coin_ticker); - return; + return None; }, }; }; @@ -329,7 +324,7 @@ pub(super) async fn swap_kickstart_handler< let maker_coin_ticker = swap_repr.maker_coin(); let maker_coin = loop { - match lp_coinfind(&ctx, maker_coin_ticker).await { + match lp_coinfind(ctx, maker_coin_ticker).await { Ok(Some(c)) => break c, Ok(None) => { info!( @@ -340,23 +335,30 @@ pub(super) async fn swap_kickstart_handler< }, Err(e) => { error!("Error {} on {} find attempt", e, maker_coin_ticker); - return; + return None; }, }; }; - // TODO add ETH support - let (maker_coin, taker_coin) = match (maker_coin, taker_coin) { - (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => (m, t), - _ => { - error!( - "V2 swaps are not currently supported for {}/{} pair", - maker_coin_ticker, taker_coin_ticker - ); - return; - }, - }; + Some((maker_coin, taker_coin)) +} +/// Handles the recreation and kickstart of a swap state machine. +pub(super) async fn swap_kickstart_handler< + T: StorableStateMachine>, + MakerCoin: MmCoin + MakerCoinSwapOpsV2, + TakerCoin: MmCoin + TakerCoinSwapOpsV2, +>( + swap_repr: ::DbRepr, + storage: T::Storage, + uuid: ::MachineId, + maker_coin: MakerCoin, + taker_coin: TakerCoin, +) where + ::MachineId: Copy + std::fmt::Display, + T::Error: std::fmt::Display, + T::RecreateError: std::fmt::Display, +{ let recreate_context = SwapRecreateCtx { maker_coin, taker_coin }; let (mut state_machine, state) = match T::recreate_machine(uuid, storage, swap_repr, recreate_context).await { @@ -371,3 +373,99 @@ pub(super) async fn swap_kickstart_handler< error!("Error {} on trying to run the swap {}", e, uuid); } } + +pub(super) async fn swap_kickstart_handler_for_maker( + ctx: MmArc, + swap_repr: MakerSwapDbRepr, + storage: MakerSwapStorage, + uuid: Uuid, +) { + let (maker_coin, taker_coin) = match swap_kickstart_coins(&ctx, &swap_repr, &uuid).await { + Some(coins) => coins, + None => return, + }; + + match (maker_coin, taker_coin) { + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => { + swap_kickstart_handler::< + MakerSwapStateMachine, + UtxoStandardCoin, + UtxoStandardCoin, + >(swap_repr, storage, uuid, m, t) + .await + }, + (MmCoinEnum::EthCoin(m), MmCoinEnum::EthCoin(t)) => { + swap_kickstart_handler::, EthCoin, EthCoin>( + swap_repr, storage, uuid, m, t, + ) + .await + }, + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::EthCoin(t)) => { + swap_kickstart_handler::, UtxoStandardCoin, EthCoin>( + swap_repr, storage, uuid, m, t, + ) + .await + }, + (MmCoinEnum::EthCoin(m), MmCoinEnum::UtxoCoin(t)) => { + swap_kickstart_handler::, EthCoin, UtxoStandardCoin>( + swap_repr, storage, uuid, m, t, + ) + .await + }, + _ => { + error!( + "V2 swaps are not currently supported for {}/{} pair", + swap_repr.maker_coin(), + swap_repr.taker_coin() + ); + }, + }; +} + +pub(super) async fn swap_kickstart_handler_for_taker( + ctx: MmArc, + swap_repr: TakerSwapDbRepr, + storage: TakerSwapStorage, + uuid: Uuid, +) { + let (maker_coin, taker_coin) = match swap_kickstart_coins(&ctx, &swap_repr, &uuid).await { + Some(coins) => coins, + None => return, + }; + + match (maker_coin, taker_coin) { + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => { + swap_kickstart_handler::< + TakerSwapStateMachine, + UtxoStandardCoin, + UtxoStandardCoin, + >(swap_repr, storage, uuid, m, t) + .await + }, + (MmCoinEnum::EthCoin(m), MmCoinEnum::EthCoin(t)) => { + swap_kickstart_handler::, EthCoin, EthCoin>( + swap_repr, storage, uuid, m, t, + ) + .await + }, + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::EthCoin(t)) => { + swap_kickstart_handler::, UtxoStandardCoin, EthCoin>( + swap_repr, storage, uuid, m, t, + ) + .await + }, + (MmCoinEnum::EthCoin(m), MmCoinEnum::UtxoCoin(t)) => { + swap_kickstart_handler::, EthCoin, UtxoStandardCoin>( + swap_repr, storage, uuid, m, t, + ) + .await + }, + _ => { + error!( + "V2 swaps are not currently supported for {}/{} pair", + swap_repr.maker_coin(), + swap_repr.taker_coin() + ); + }, + }; +} From 09b4b6bbc85fdc57f377abfde3269f6e38b8ed5a Mon Sep 17 00:00:00 2001 From: laruh Date: Tue, 24 Dec 2024 14:08:22 +0700 Subject: [PATCH 4/7] review: update doc comment --- mm2src/mm2_main/src/lp_swap/swap_v2_common.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs index 4a690ab06c..9a97c1d83f 100644 --- a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs +++ b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs @@ -296,7 +296,8 @@ pub(super) trait GetSwapCoins { } /// Attempts to find and return the maker and taker coins required for the swap to proceed. -/// If a coin is not activated, it logs the information and retries until the coin is found or an error occurs. +/// If a coin is not activated, it logs the information and retries until the coin is found. +/// If an unexpected issue occurs, function logs the error and returns `None`. pub(super) async fn swap_kickstart_coins( ctx: &MmArc, swap_repr: &T, From 1065997604e3d1f250b80d384f644f3e60107d2e Mon Sep 17 00:00:00 2001 From: laruh Date: Tue, 24 Dec 2024 14:23:42 +0700 Subject: [PATCH 5/7] review: omit types --- mm2src/mm2_main/src/lp_swap/swap_v2_common.rs | 46 ++++--------------- 1 file changed, 8 insertions(+), 38 deletions(-) diff --git a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs index 9a97c1d83f..b670163cd5 100644 --- a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs +++ b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs @@ -3,8 +3,6 @@ use crate::lp_swap::maker_swap_v2::{MakerSwapDbRepr, MakerSwapStateMachine, Make use crate::lp_swap::swap_lock::{SwapLock, SwapLockError, SwapLockOps}; use crate::lp_swap::taker_swap_v2::{TakerSwapDbRepr, TakerSwapStateMachine, TakerSwapStorage}; use crate::lp_swap::{swap_v2_topic, SwapsContext}; -use coins::eth::EthCoin; -use coins::utxo::utxo_standard::UtxoStandardCoin; use coins::{lp_coinfind, MakerCoinSwapOpsV2, MmCoin, MmCoinEnum, TakerCoinSwapOpsV2}; use common::executor::abortable_queue::AbortableQueue; use common::executor::{SpawnFuture, Timer}; @@ -388,30 +386,16 @@ pub(super) async fn swap_kickstart_handler_for_maker( match (maker_coin, taker_coin) { (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => { - swap_kickstart_handler::< - MakerSwapStateMachine, - UtxoStandardCoin, - UtxoStandardCoin, - >(swap_repr, storage, uuid, m, t) - .await + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await }, (MmCoinEnum::EthCoin(m), MmCoinEnum::EthCoin(t)) => { - swap_kickstart_handler::, EthCoin, EthCoin>( - swap_repr, storage, uuid, m, t, - ) - .await + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await }, (MmCoinEnum::UtxoCoin(m), MmCoinEnum::EthCoin(t)) => { - swap_kickstart_handler::, UtxoStandardCoin, EthCoin>( - swap_repr, storage, uuid, m, t, - ) - .await + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await }, (MmCoinEnum::EthCoin(m), MmCoinEnum::UtxoCoin(t)) => { - swap_kickstart_handler::, EthCoin, UtxoStandardCoin>( - swap_repr, storage, uuid, m, t, - ) - .await + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await }, _ => { error!( @@ -436,30 +420,16 @@ pub(super) async fn swap_kickstart_handler_for_taker( match (maker_coin, taker_coin) { (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => { - swap_kickstart_handler::< - TakerSwapStateMachine, - UtxoStandardCoin, - UtxoStandardCoin, - >(swap_repr, storage, uuid, m, t) - .await + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await }, (MmCoinEnum::EthCoin(m), MmCoinEnum::EthCoin(t)) => { - swap_kickstart_handler::, EthCoin, EthCoin>( - swap_repr, storage, uuid, m, t, - ) - .await + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await }, (MmCoinEnum::UtxoCoin(m), MmCoinEnum::EthCoin(t)) => { - swap_kickstart_handler::, UtxoStandardCoin, EthCoin>( - swap_repr, storage, uuid, m, t, - ) - .await + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await }, (MmCoinEnum::EthCoin(m), MmCoinEnum::UtxoCoin(t)) => { - swap_kickstart_handler::, EthCoin, UtxoStandardCoin>( - swap_repr, storage, uuid, m, t, - ) - .await + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await }, _ => { error!( From c2147260a9d5124b0a57aee10c022ebac6bbf636 Mon Sep 17 00:00:00 2001 From: laruh Date: Tue, 24 Dec 2024 14:28:44 +0700 Subject: [PATCH 6/7] review: use if let Some --- mm2src/mm2_main/src/lp_swap/swap_v2_common.rs | 98 +++++++++---------- 1 file changed, 46 insertions(+), 52 deletions(-) diff --git a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs index b670163cd5..fd897507b6 100644 --- a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs +++ b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs @@ -379,32 +379,29 @@ pub(super) async fn swap_kickstart_handler_for_maker( storage: MakerSwapStorage, uuid: Uuid, ) { - let (maker_coin, taker_coin) = match swap_kickstart_coins(&ctx, &swap_repr, &uuid).await { - Some(coins) => coins, - None => return, - }; - - match (maker_coin, taker_coin) { - (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => { - swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await - }, - (MmCoinEnum::EthCoin(m), MmCoinEnum::EthCoin(t)) => { - swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await - }, - (MmCoinEnum::UtxoCoin(m), MmCoinEnum::EthCoin(t)) => { - swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await - }, - (MmCoinEnum::EthCoin(m), MmCoinEnum::UtxoCoin(t)) => { - swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await - }, - _ => { - error!( - "V2 swaps are not currently supported for {}/{} pair", - swap_repr.maker_coin(), - swap_repr.taker_coin() - ); - }, - }; + if let Some((maker_coin, taker_coin)) = swap_kickstart_coins(&ctx, &swap_repr, &uuid).await { + match (maker_coin, taker_coin) { + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => { + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await + }, + (MmCoinEnum::EthCoin(m), MmCoinEnum::EthCoin(t)) => { + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await + }, + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::EthCoin(t)) => { + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await + }, + (MmCoinEnum::EthCoin(m), MmCoinEnum::UtxoCoin(t)) => { + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await + }, + _ => { + error!( + "V2 swaps are not currently supported for {}/{} pair", + swap_repr.maker_coin(), + swap_repr.taker_coin() + ); + }, + } + } } pub(super) async fn swap_kickstart_handler_for_taker( @@ -413,30 +410,27 @@ pub(super) async fn swap_kickstart_handler_for_taker( storage: TakerSwapStorage, uuid: Uuid, ) { - let (maker_coin, taker_coin) = match swap_kickstart_coins(&ctx, &swap_repr, &uuid).await { - Some(coins) => coins, - None => return, - }; - - match (maker_coin, taker_coin) { - (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => { - swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await - }, - (MmCoinEnum::EthCoin(m), MmCoinEnum::EthCoin(t)) => { - swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await - }, - (MmCoinEnum::UtxoCoin(m), MmCoinEnum::EthCoin(t)) => { - swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await - }, - (MmCoinEnum::EthCoin(m), MmCoinEnum::UtxoCoin(t)) => { - swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await - }, - _ => { - error!( - "V2 swaps are not currently supported for {}/{} pair", - swap_repr.maker_coin(), - swap_repr.taker_coin() - ); - }, - }; + if let Some((maker_coin, taker_coin)) = swap_kickstart_coins(&ctx, &swap_repr, &uuid).await { + match (maker_coin, taker_coin) { + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::UtxoCoin(t)) => { + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await + }, + (MmCoinEnum::EthCoin(m), MmCoinEnum::EthCoin(t)) => { + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await + }, + (MmCoinEnum::UtxoCoin(m), MmCoinEnum::EthCoin(t)) => { + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await + }, + (MmCoinEnum::EthCoin(m), MmCoinEnum::UtxoCoin(t)) => { + swap_kickstart_handler::, _, _>(swap_repr, storage, uuid, m, t).await + }, + _ => { + error!( + "V2 swaps are not currently supported for {}/{} pair", + swap_repr.maker_coin(), + swap_repr.taker_coin() + ); + }, + } + } } From d48cc250667251a2d19a7bdf8c01e462e3f9833f Mon Sep 17 00:00:00 2001 From: laruh Date: Thu, 26 Dec 2024 18:36:45 +0700 Subject: [PATCH 7/7] eth-eth kickstart test --- .../tests/docker_tests/docker_tests_common.rs | 3 +- .../tests/docker_tests/eth_docker_tests.rs | 146 ++++++++++++++++-- mm2src/mm2_test_helpers/src/for_tests.rs | 55 ++++++- 3 files changed, 191 insertions(+), 13 deletions(-) diff --git a/mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs b/mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs index 3050f22826..311800bb5d 100644 --- a/mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs +++ b/mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs @@ -1313,8 +1313,7 @@ pub fn init_geth_node() { thread::sleep(Duration::from_millis(100)); } - let dex_fee_addr = addr_from_raw_pubkey(&DEX_FEE_ADDR_RAW_PUBKEY).unwrap(); - let dex_fee_addr = Token::Address(dex_fee_addr); + let dex_fee_addr = Token::Address(GETH_ACCOUNT); let params = ethabi::encode(&[dex_fee_addr]); let taker_swap_v2_data = format!("{}{}", TAKER_SWAP_V2_BYTES, hex::encode(params)); diff --git a/mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs b/mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs index d922ba8f27..8aec7ceed5 100644 --- a/mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs +++ b/mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs @@ -28,12 +28,13 @@ use coins::{CoinProtocol, CoinWithDerivationMethod, CommonSwapOpsV2, ConfirmPaym use common::{block_on, block_on_f01, now_sec}; use crypto::Secp256k1Secret; use ethereum_types::U256; -#[cfg(any(feature = "sepolia-maker-swap-v2-tests", feature = "sepolia-taker-swap-v2-tests"))] use mm2_core::mm_ctx::MmArc; use mm2_number::{BigDecimal, BigUint}; -use mm2_test_helpers::for_tests::{account_balance, disable_coin, enable_erc20_token_v2, enable_eth_with_tokens_v2, - erc20_dev_conf, eth_dev_conf, get_new_address, get_token_info, nft_dev_conf, - MarketMakerIt, Mm2TestConf}; +use mm2_test_helpers::for_tests::{account_balance, active_swaps, coins_needed_for_kickstart, disable_coin, + enable_erc20_token_v2, enable_eth_coin_v2, enable_eth_with_tokens_v2, + erc20_dev_conf, eth1_dev_conf, eth_dev_conf, get_locked_amount, get_new_address, + get_token_info, mm_dump, my_swap_status, nft_dev_conf, start_swaps, MarketMakerIt, + Mm2TestConf, SwapV2TestContracts, TestNode}; #[cfg(any(feature = "sepolia-maker-swap-v2-tests", feature = "sepolia-taker-swap-v2-tests"))] use mm2_test_helpers::for_tests::{eth_sepolia_conf, sepolia_erc20_dev_conf}; use mm2_test_helpers::structs::{Bip44Chain, EnableCoinBalanceMap, EthWithTokensActivationResult, HDAccountAddressId, @@ -43,6 +44,7 @@ use serde_json::Value as Json; use std::str::FromStr; use std::thread; use std::time::Duration; +use uuid::Uuid; use web3::contract::{Contract, Options}; use web3::ethabi::Token; #[cfg(any(feature = "sepolia-maker-swap-v2-tests", feature = "sepolia-taker-swap-v2-tests"))] @@ -55,6 +57,7 @@ const SEPOLIA_MAKER_PRIV: &str = "6e2f3a6223b928a05a3a3622b0c3f3573d03663b704a61 const SEPOLIA_TAKER_PRIV: &str = "e0be82dca60ff7e4c6d6db339ac9e1ae249af081dba2110bddd281e711608f16"; const NFT_ETH: &str = "NFT_ETH"; const ETH: &str = "ETH"; +const ETH1: &str = "ETH1"; #[cfg(any(feature = "sepolia-maker-swap-v2-tests", feature = "sepolia-taker-swap-v2-tests"))] const ERC20: &str = "ERC20DEV"; @@ -1427,15 +1430,16 @@ impl SwapAddresses { } } -#[allow(dead_code)] /// Needed for eth or erc20 v2 activation in Geth tests fn eth_coin_v2_activation_with_random_privkey( + ctx: &MmArc, ticker: &str, conf: &Json, swap_addr: SwapAddresses, erc20: bool, -) -> EthCoin { - let build_policy = EthPrivKeyBuildPolicy::IguanaPrivKey(random_secp256k1_secret()); +) -> (EthCoin, Secp256k1Secret) { + let priv_key = random_secp256k1_secret(); + let build_policy = EthPrivKeyBuildPolicy::IguanaPrivKey(priv_key); let node = EthNode { url: GETH_RPC_URL.to_string(), komodo_proxy: false, @@ -1455,7 +1459,7 @@ fn eth_coin_v2_activation_with_random_privkey( gap_limit: None, }; let coin = block_on(eth_coin_from_conf_and_request_v2( - &MM_CTX1, + ctx, ticker, conf, platform_request, @@ -1471,9 +1475,9 @@ fn eth_coin_v2_activation_with_random_privkey( token_addr: erc20_contract(), }; let coin = block_on(coin.set_coin_type(coin_type)); - return coin; + return (coin, priv_key); } - coin + (coin, priv_key) } #[cfg(feature = "sepolia-taker-swap-v2-tests")] @@ -2749,3 +2753,125 @@ fn test_enable_custom_erc20_with_duplicate_contract_in_config() { // Disable the custom token, this to check that it was enabled correctly block_on(disable_coin(&mm_hd, &config_ticker, true)); } + +#[test] +fn test_v2_eth_eth_kickstart() { + // Initialize swap addresses and configurations + let swap_addresses = SwapAddresses::init(); + let contracts = SwapV2TestContracts { + maker_swap_v2_contract: eth_addr_to_hex(&swap_addresses.swap_v2_contracts.maker_swap_v2_contract), + taker_swap_v2_contract: eth_addr_to_hex(&swap_addresses.swap_v2_contracts.taker_swap_v2_contract), + nft_maker_swap_v2_contract: eth_addr_to_hex(&swap_addresses.swap_v2_contracts.nft_maker_swap_v2_contract), + }; + let swap_contract_address = eth_addr_to_hex(&swap_addresses.swap_contract_address); + let node = TestNode { + url: GETH_RPC_URL.to_string(), + }; + + // Helper function for activating coins + let enable_coins = |mm: &MarketMakerIt, coins: &[&str]| { + for &coin in coins { + log!( + "{:?}", + block_on(enable_eth_coin_v2( + mm, + coin, + &swap_contract_address, + contracts.clone(), + None, + &[node.clone()] + )) + ); + } + }; + + // start Bob and Alice + let (_, bob_priv_key) = + eth_coin_v2_activation_with_random_privkey(&MM_CTX, ETH, ð_dev_conf(), swap_addresses, false); + let (_, alice_priv_key) = + eth_coin_v2_activation_with_random_privkey(&MM_CTX1, ETH1, ð1_dev_conf(), swap_addresses, false); + let coins = json!([eth_dev_conf(), eth1_dev_conf()]); + + let mut bob_conf = Mm2TestConf::seednode_trade_v2(&format!("0x{}", hex::encode(bob_priv_key)), &coins); + let mut mm_bob = MarketMakerIt::start(bob_conf.conf.clone(), bob_conf.rpc_password.clone(), None).unwrap(); + let (_bob_dump_log, _bob_dump_dashboard) = mm_dump(&mm_bob.log_path); + log!("Bob log path: {}", mm_bob.log_path.display()); + + let mut alice_conf = + Mm2TestConf::light_node_trade_v2(&format!("0x{}", hex::encode(alice_priv_key)), &coins, &[&mm_bob + .ip + .to_string()]); + let mut mm_alice = MarketMakerIt::start(alice_conf.conf.clone(), alice_conf.rpc_password.clone(), None).unwrap(); + let (_alice_dump_log, _alice_dump_dashboard) = mm_dump(&mm_alice.log_path); + log!("Alice log path: {}", mm_alice.log_path.display()); + + // Enable ETH and ETH1 for both Bob and Alice + enable_coins(&mm_bob, &[ETH, ETH1]); + enable_coins(&mm_alice, &[ETH, ETH1]); + + let uuids = block_on(start_swaps(&mut mm_bob, &mut mm_alice, &[(ETH, ETH1)], 1.0, 1.0, 77.)); + log!("{:?}", uuids); + let parsed_uuids: Vec = uuids.iter().map(|u| u.parse().unwrap()).collect(); + + for uuid in uuids.iter() { + log_swap_status_before_stop(&mm_bob, uuid, "Maker"); + log_swap_status_before_stop(&mm_alice, uuid, "Taker"); + } + + block_on(mm_bob.stop()).unwrap(); + block_on(mm_alice.stop()).unwrap(); + + // Restart Bob and Alice + bob_conf.conf["dbdir"] = mm_bob.folder.join("DB").to_str().unwrap().into(); + bob_conf.conf["log"] = mm_bob.folder.join("mm2_dup.log").to_str().unwrap().into(); + + let mm_bob = MarketMakerIt::start(bob_conf.conf, bob_conf.rpc_password, None).unwrap(); + let (_bob_dump_log, _bob_dump_dashboard) = mm_dump(&mm_bob.log_path); + log!("Bob log path: {}", mm_bob.log_path.display()); + + alice_conf.conf["dbdir"] = mm_alice.folder.join("DB").to_str().unwrap().into(); + alice_conf.conf["log"] = mm_alice.folder.join("mm2_dup.log").to_str().unwrap().into(); + alice_conf.conf["seednodes"] = vec![mm_bob.ip.to_string()].into(); + + let mm_alice = MarketMakerIt::start(alice_conf.conf, alice_conf.rpc_password, None).unwrap(); + let (_alice_dump_log, _alice_dump_dashboard) = mm_dump(&mm_alice.log_path); + log!("Alice log path: {}", mm_alice.log_path.display()); + + verify_coins_needed_for_kickstart(&mm_bob, &[ETH, ETH1]); + verify_coins_needed_for_kickstart(&mm_alice, &[ETH, ETH1]); + + enable_coins(&mm_bob, &[ETH, ETH1]); + enable_coins(&mm_alice, &[ETH, ETH1]); + + // give swaps 1 second to restart + thread::sleep(Duration::from_secs(1)); + + verify_active_swaps(&mm_bob, &parsed_uuids); + verify_active_swaps(&mm_alice, &parsed_uuids); + + // coins must be virtually locked after kickstart until swap transactions are sent + verify_locked_amount(&mm_alice, "Taker", ETH1); + verify_locked_amount(&mm_bob, "Maker", ETH); +} + +fn log_swap_status_before_stop(mm: &MarketMakerIt, uuid: &str, role: &str) { + let status = block_on(my_swap_status(mm, uuid)); + log!("{} swap {} status before stop: {:?}", role, uuid, status); +} + +fn verify_coins_needed_for_kickstart(mm: &MarketMakerIt, expected_coins: &[&str]) { + let mut coins_needed = block_on(coins_needed_for_kickstart(mm)); + coins_needed.sort(); + assert_eq!(coins_needed, expected_coins); +} + +fn verify_active_swaps(mm: &MarketMakerIt, expected_uuids: &[Uuid]) { + let active_swaps = block_on(active_swaps(mm)); + assert_eq!(active_swaps.uuids, expected_uuids); +} + +fn verify_locked_amount(mm: &MarketMakerIt, role: &str, coin: &str) { + let locked = block_on(get_locked_amount(mm, coin)); + log!("{} {} locked amount: {:?}", role, coin, locked.locked_amount); + assert_eq!(locked.coin, coin); +} diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index 7592384696..6aaee66488 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -820,8 +820,16 @@ pub fn eth_testnet_conf_trezor() -> Json { /// ETH configuration used for dockerized Geth dev node pub fn eth_dev_conf() -> Json { + eth_conf("ETH") +} + +pub fn eth1_dev_conf() -> Json { + eth_conf("ETH1") +} + +fn eth_conf(coin: &str) -> Json { json!({ - "coin": "ETH", + "coin": coin, "name": "ethereum", "mm2": 1, "chain_id": 1337, @@ -2041,6 +2049,51 @@ pub async fn enable_eth_coin( json::from_str(&enable.1).unwrap() } +#[derive(Clone)] +pub struct SwapV2TestContracts { + pub maker_swap_v2_contract: String, + pub taker_swap_v2_contract: String, + pub nft_maker_swap_v2_contract: String, +} + +#[derive(Clone)] +pub struct TestNode { + pub url: String, +} + +pub async fn enable_eth_coin_v2( + mm: &MarketMakerIt, + ticker: &str, + swap_contract_address: &str, + swap_v2_contracts: SwapV2TestContracts, + fallback_swap_contract: Option<&str>, + nodes: &[TestNode], +) -> Json { + let enable = mm + .rpc(&json!({ + "userpass": mm.userpass, + "method": "enable_eth_with_tokens", + "mmrpc": "2.0", + "params": { + "ticker": ticker, + "mm2": 1, + "swap_contract_address": swap_contract_address, + "swap_v2_contracts": { + "maker_swap_v2_contract": swap_v2_contracts.maker_swap_v2_contract, + "taker_swap_v2_contract": swap_v2_contracts.taker_swap_v2_contract, + "nft_maker_swap_v2_contract": swap_v2_contracts.nft_maker_swap_v2_contract + }, + "fallback_swap_contract": fallback_swap_contract, + "nodes": nodes.iter().map(|node| json!({ "url": node.url })).collect::>(), + "erc20_tokens_requests": [] + } + })) + .await + .unwrap(); + assert_eq!(enable.0, StatusCode::OK, "'enable_eth_with_tokens' failed: {}", enable.1); + json::from_str(&enable.1).unwrap() +} + pub async fn enable_slp(mm: &MarketMakerIt, coin: &str) -> Json { let enable = mm .rpc(&json!({