diff --git a/README.md b/README.md index 441c23ba8c..ded2234d07 100755 --- a/README.md +++ b/README.md @@ -116,7 +116,8 @@ For example: "gui": "core_readme", "netid": 8762, "rpc_password": "Ent3r_Un1Qu3_Pa$$w0rd", - "passphrase": "ENTER_UNIQUE_SEED_PHRASE_DONT_USE_THIS_CHANGE_IT_OR_FUNDS_NOT_SAFU" + "passphrase": "ENTER_UNIQUE_SEED_PHRASE_DONT_USE_THIS_CHANGE_IT_OR_FUNDS_NOT_SAFU", + "seednodes": ["example-seed-address1.com", "example-seed-address2.com", "example-seed-address3.com", "example-seed-address4.com"] } ``` diff --git a/mm2src/mm2_core/src/mm_ctx.rs b/mm2src/mm2_core/src/mm_ctx.rs index 5d01b81245..83944e2d5a 100644 --- a/mm2src/mm2_core/src/mm_ctx.rs +++ b/mm2src/mm2_core/src/mm_ctx.rs @@ -425,6 +425,29 @@ impl MmCtx { netid as u16 } + pub fn disable_p2p(&self) -> bool { + if let Some(disable_p2p) = self.conf["disable_p2p"].as_bool() { + return disable_p2p; + } + + let default = !self.conf["is_bootstrap_node"].as_bool().unwrap_or(false) + && self.conf["seednodes"].as_array().is_none() + && !self.p2p_in_memory(); + + default + } + + pub fn is_bootstrap_node(&self) -> bool { + if let Some(is_bootstrap_node) = self.conf["is_bootstrap_node"].as_bool() { + return is_bootstrap_node; + } + + let default = !self.conf["disable_p2p"].as_bool().unwrap_or(false) + && self.conf["seednodes"].as_array().map_or(true, |t| t.is_empty()); + + default + } + pub fn p2p_in_memory(&self) -> bool { self.conf["p2p_in_memory"].as_bool().unwrap_or(false) } pub fn p2p_in_memory_port(&self) -> Option { self.conf["p2p_in_memory_port"].as_u64() } diff --git a/mm2src/mm2_main/src/lp_native_dex.rs b/mm2src/mm2_main/src/lp_native_dex.rs index fc37bc8624..a24a75d8ce 100644 --- a/mm2src/mm2_main/src/lp_native_dex.rs +++ b/mm2src/mm2_main/src/lp_native_dex.rs @@ -40,8 +40,8 @@ use mm2_err_handle::common_errors::InternalError; use mm2_err_handle::prelude::*; use mm2_libp2p::behaviours::atomicdex::{generate_ed25519_keypair, GossipsubConfig, DEPRECATED_NETID_LIST}; use mm2_libp2p::p2p_ctx::P2PContext; -use mm2_libp2p::{spawn_gossipsub, AdexBehaviourError, NodeType, RelayAddress, RelayAddressError, SeedNodeInfo, - SwarmRuntime, WssCerts}; +use mm2_libp2p::{spawn_gossipsub, AdexBehaviourError, NodeType, RelayAddress, RelayAddressError, SwarmRuntime, + WssCerts}; use mm2_metrics::mm_gauge; use rpc_task::RpcTaskError; use serde_json as json; @@ -69,45 +69,6 @@ cfg_wasm32! { pub mod init_metamask; } -const DEFAULT_NETID_SEEDNODES: &[SeedNodeInfo] = &[ - SeedNodeInfo::new( - "12D3KooWHKkHiNhZtKceQehHhPqwU5W1jXpoVBgS1qst899GjvTm", - "viserion.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWAToxtunEBWCoAHjefSv74Nsmxranw8juy3eKEdrQyGRF", - "rhaegal.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWSmEi8ypaVzFA1AGde2RjxNW5Pvxw3qa2fVe48PjNs63R", - "drogon.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWMrjLmrv8hNgAoVf1RfumfjyPStzd4nv5XL47zN4ZKisb", - "falkor.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWEWzbYcosK2JK9XpFXzumfgsWJW1F7BZS15yLTrhfjX2Z", - "smaug.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWJWBnkVsVNjiqUEPjLyHpiSmQVAJ5t6qt1Txv5ctJi9Xd", - "balerion.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWPR2RoPi19vQtLugjCdvVmCcGLP2iXAzbDfP3tp81ZL4d", - "kalessin.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWEaZpH61H4yuQkaNG5AsyGdpBhKRppaLdAY52a774ab5u", - "seed01.kmdefi.net", - ), - SeedNodeInfo::new( - "12D3KooWAd5gPXwX7eDvKWwkr2FZGfoJceKDCA53SHmTFFVkrN7Q", - "seed02.kmdefi.net", - ), -]; - pub type P2PResult = Result>; pub type MmInitResult = Result>; @@ -132,8 +93,10 @@ pub enum P2PInitError { #[display(fmt = "Invalid relay address: '{}'", _0)] InvalidRelayAddress(RelayAddressError), #[cfg_attr(not(target_arch = "wasm32"), allow(dead_code))] - #[display(fmt = "WASM node can be a seed if only 'p2p_in_memory' is true")] + #[display(fmt = "WASM node can be a seed only if 'p2p_in_memory' is true")] WasmNodeCannotBeSeed, + #[display(fmt = "Precheck failed: '{}'", reason)] + Precheck { reason: String }, #[display(fmt = "Internal error: '{}'", _0)] Internal(String), } @@ -295,31 +258,6 @@ impl MmInitError { } } -#[cfg(target_arch = "wasm32")] -fn default_seednodes(netid: u16) -> Vec { - if netid == 8762 { - DEFAULT_NETID_SEEDNODES - .iter() - .map(|SeedNodeInfo { domain, .. }| RelayAddress::Dns(domain.to_string())) - .collect() - } else { - Vec::new() - } -} - -#[cfg(not(target_arch = "wasm32"))] -fn default_seednodes(netid: u16) -> Vec { - if netid == 8762 { - DEFAULT_NETID_SEEDNODES - .iter() - .filter_map(|SeedNodeInfo { domain, .. }| mm2_net::ip_addr::addr_to_ipv4_string(domain).ok()) - .map(RelayAddress::IPv4) - .collect() - } else { - Vec::new() - } -} - #[cfg(not(target_arch = "wasm32"))] pub fn fix_directories(ctx: &MmCtx) -> MmInitResult<()> { fix_shared_dbdir(ctx)?; @@ -535,9 +473,9 @@ async fn kick_start(ctx: MmArc) -> MmInitResult<()> { Ok(()) } -fn get_p2p_key(ctx: &MmArc, i_am_seed: bool) -> P2PResult<[u8; 32]> { +fn get_p2p_key(ctx: &MmArc, is_seed_node: bool) -> P2PResult<[u8; 32]> { // TODO: Use persistent peer ID regardless the node type. - if i_am_seed { + if is_seed_node { if let Ok(crypto_ctx) = CryptoCtx::from_ctx(ctx) { let key = sha256(crypto_ctx.mm2_internal_privkey_slice()); return Ok(key.take()); @@ -549,21 +487,74 @@ fn get_p2p_key(ctx: &MmArc, i_am_seed: bool) -> P2PResult<[u8; 32]> { Ok(p2p_key) } -pub async fn init_p2p(ctx: MmArc) -> P2PResult<()> { - let i_am_seed = ctx.is_seed_node(); +fn p2p_precheck(ctx: &MmArc) -> P2PResult<()> { + let is_seed_node = ctx.is_seed_node(); + let is_bootstrap_node = ctx.is_bootstrap_node(); + let disable_p2p = ctx.disable_p2p(); + let p2p_in_memory = ctx.p2p_in_memory(); let netid = ctx.netid(); if DEPRECATED_NETID_LIST.contains(&netid) { return MmError::err(P2PInitError::InvalidNetId(NetIdError::Deprecated { netid })); } + let seednodes = seednodes(ctx)?; + + let precheck_err = |reason: &str| { + MmError::err(P2PInitError::Precheck { + reason: reason.to_owned(), + }) + }; + + if is_bootstrap_node { + if !is_seed_node { + return precheck_err("Bootstrap node must also be a seed node."); + } + + if !seednodes.is_empty() { + return precheck_err("Bootstrap node cannot have seed nodes to connect."); + } + } + + if !is_bootstrap_node && seednodes.is_empty() && !disable_p2p { + return precheck_err("Non-bootstrap node must have seed nodes configured to connect."); + } + + if disable_p2p { + if !seednodes.is_empty() { + return precheck_err("Cannot disable P2P while seed nodes are configured."); + } + + if p2p_in_memory { + return precheck_err("Cannot disable P2P while using in-memory P2P mode."); + } + + if is_seed_node { + return precheck_err("Seed nodes cannot disable P2P."); + } + } + + Ok(()) +} + +pub async fn init_p2p(ctx: MmArc) -> P2PResult<()> { + p2p_precheck(&ctx)?; + + if ctx.disable_p2p() { + warn!("P2P is disabled. Features that require a P2P network (like swaps, peer health checks, etc.) will not work."); + return Ok(()); + } + + let is_seed_node = ctx.is_seed_node(); + let netid = ctx.netid(); + let seednodes = seednodes(&ctx)?; let ctx_on_poll = ctx.clone(); - let p2p_key = get_p2p_key(&ctx, i_am_seed)?; + let p2p_key = get_p2p_key(&ctx, is_seed_node)?; - let node_type = if i_am_seed { + let node_type = if is_seed_node { relay_node_type(&ctx).await? } else { light_node_type(&ctx)? @@ -616,7 +607,7 @@ pub async fn init_p2p(ctx: MmArc) -> P2PResult<()> { let p2p_context = P2PContext::new(cmd_tx, generate_ed25519_keypair(p2p_key)); p2p_context.store_to_mm_arc(&ctx); - let fut = p2p_event_process_loop(ctx.weak(), event_rx, i_am_seed); + let fut = p2p_event_process_loop(ctx.weak(), event_rx, is_seed_node); ctx.spawner().spawn(fut); // Listen for health check messages. @@ -626,15 +617,9 @@ pub async fn init_p2p(ctx: MmArc) -> P2PResult<()> { } fn seednodes(ctx: &MmArc) -> P2PResult> { - if ctx.conf["seednodes"].is_null() { - if ctx.p2p_in_memory() { - // If the network is in memory, there is no need to use default seednodes. - return Ok(Vec::new()); - } - return Ok(default_seednodes(ctx.netid())); - } + let seednodes_value = ctx.conf.get("seednodes").unwrap_or(&json!([])).clone(); - json::from_value(ctx.conf["seednodes"].clone()).map_to_mm(|e| P2PInitError::ErrorDeserializingConfig { + json::from_value(seednodes_value).map_to_mm(|e| P2PInitError::ErrorDeserializingConfig { field: "seednodes".to_owned(), error: e.to_string(), }) diff --git a/mm2src/mm2_main/src/lp_swap.rs b/mm2src/mm2_main/src/lp_swap.rs index 2c41131927..7744b555d8 100644 --- a/mm2src/mm2_main/src/lp_swap.rs +++ b/mm2src/mm2_main/src/lp_swap.rs @@ -2154,6 +2154,7 @@ mod lp_swap_tests { "p2p_in_memory": true, "p2p_in_memory_port": 777, "i_am_seed": true, + "is_bootstrap_node": true }); let maker_ctx = MmCtxBuilder::default().with_conf(maker_ctx_conf).into_mm_arc(); diff --git a/mm2src/mm2_main/tests/docker_tests/docker_ordermatch_tests.rs b/mm2src/mm2_main/tests/docker_tests/docker_ordermatch_tests.rs index 8f090c91f2..45345ef4d5 100644 --- a/mm2src/mm2_main/tests/docker_tests/docker_ordermatch_tests.rs +++ b/mm2src/mm2_main/tests/docker_tests/docker_ordermatch_tests.rs @@ -199,6 +199,7 @@ fn test_ordermatch_custom_orderbook_ticker_both_on_maker() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -334,6 +335,7 @@ fn test_ordermatch_custom_orderbook_ticker_both_on_taker() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -467,6 +469,7 @@ fn test_ordermatch_custom_orderbook_ticker_mixed_case_one() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -608,6 +611,7 @@ fn test_ordermatch_custom_orderbook_ticker_mixed_case_two() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1183,6 +1187,7 @@ fn test_zombie_order_after_balance_reduce_and_mm_restart() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }); let mm_seed = MarketMakerIt::start(seed_conf, "pass".to_string(), None).unwrap(); 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 2425bf8fbb..d513ada2d2 100644 --- a/mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs +++ b/mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs @@ -978,6 +978,7 @@ pub fn trade_base_rel((base, rel): (&str, &str)) { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1154,6 +1155,7 @@ pub fn slp_supplied_node() -> MarketMakerIt { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, diff --git a/mm2src/mm2_main/tests/docker_tests/docker_tests_inner.rs b/mm2src/mm2_main/tests/docker_tests/docker_tests_inner.rs index 936272b063..c34a2afe55 100644 --- a/mm2src/mm2_main/tests/docker_tests/docker_tests_inner.rs +++ b/mm2src/mm2_main/tests/docker_tests/docker_tests_inner.rs @@ -405,6 +405,7 @@ fn order_should_be_cancelled_when_entire_balance_is_withdrawn() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -521,6 +522,7 @@ fn order_should_be_updated_when_balance_is_decreased_alice_subscribes_after_upda "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -654,6 +656,7 @@ fn order_should_be_updated_when_balance_is_decreased_alice_subscribes_before_upd "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -801,6 +804,7 @@ fn test_order_should_be_updated_when_matched_partially() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -906,6 +910,7 @@ fn test_match_and_trade_setprice_max() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1005,6 +1010,7 @@ fn test_max_taker_vol_swap() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1125,6 +1131,7 @@ fn test_buy_when_coins_locked_by_other_swap() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1218,6 +1225,7 @@ fn test_sell_when_coins_locked_by_other_swap() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1310,6 +1318,7 @@ fn test_buy_max() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1374,6 +1383,7 @@ fn test_maker_trade_preimage() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1511,6 +1521,7 @@ fn test_taker_trade_preimage() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1652,6 +1663,7 @@ fn test_trade_preimage_not_sufficient_balance() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1771,6 +1783,7 @@ fn test_trade_preimage_additional_validation() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1910,6 +1923,7 @@ fn test_trade_preimage_legacy() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1980,6 +1994,7 @@ fn test_get_max_taker_vol() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -2032,6 +2047,7 @@ fn test_get_max_taker_vol_dex_fee_min_tx_amount() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -2093,6 +2109,7 @@ fn test_get_max_taker_vol_dust_threshold() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -2144,6 +2161,7 @@ fn test_get_max_taker_vol_with_kmd() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -2250,6 +2268,7 @@ fn test_set_price_max() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -2305,6 +2324,7 @@ fn swaps_should_stop_on_stop_rpc() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -2395,6 +2415,7 @@ fn test_maker_order_should_kick_start_and_appear_in_orderbook_on_restart() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }); let mm_bob = MarketMakerIt::start(bob_conf.clone(), "pass".to_string(), None).unwrap(); let (_bob_dump_log, _bob_dump_dashboard) = mm_dump(&mm_bob.log_path); @@ -2452,6 +2473,7 @@ fn test_maker_order_should_not_kick_start_and_appear_in_orderbook_if_balance_is_ "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }); let mm_bob = MarketMakerIt::start(bob_conf.clone(), "pass".to_string(), None).unwrap(); let (_bob_dump_log, _bob_dump_dashboard) = mm_dump(&mm_bob.log_path); @@ -2547,6 +2569,7 @@ fn test_maker_order_kick_start_should_trigger_subscription_and_match() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }); let relay = MarketMakerIt::start(relay_conf, "pass".to_string(), None).unwrap(); let (_relay_dump_log, _relay_dump_dashboard) = mm_dump(&relay.log_path); @@ -2559,7 +2582,6 @@ fn test_maker_order_kick_start_should_trigger_subscription_and_match() { "coins": coins, "rpc_password": "pass", "seednodes": vec![format!("{}", relay.ip)], - "i_am_seed": false, }); let mm_bob = MarketMakerIt::start(bob_conf.clone(), "pass".to_string(), None).unwrap(); let (_bob_dump_log, _bob_dump_dashboard) = mm_dump(&mm_bob.log_path); @@ -2638,6 +2660,7 @@ fn test_orders_should_match_on_both_nodes_with_same_priv() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -2741,6 +2764,7 @@ fn test_maker_and_taker_order_created_with_same_priv_should_not_match() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -2812,6 +2836,7 @@ fn test_taker_order_converted_to_maker_should_cancel_properly_when_matched() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -2935,6 +2960,7 @@ fn test_utxo_merge() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -2988,6 +3014,7 @@ fn test_utxo_merge_max_merge_at_once() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -3036,6 +3063,7 @@ fn test_withdraw_not_sufficient_balance() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -3122,6 +3150,7 @@ fn test_taker_should_match_with_best_price_buy() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -3255,6 +3284,7 @@ fn test_taker_should_match_with_best_price_sell() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -3393,6 +3423,7 @@ fn test_match_utxo_with_eth_taker_sell() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -3469,6 +3500,7 @@ fn test_match_utxo_with_eth_taker_buy() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -3972,6 +4004,7 @@ fn test_withdraw_and_send_eth_erc20() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, diff --git a/mm2src/mm2_main/tests/docker_tests/qrc20_tests.rs b/mm2src/mm2_main/tests/docker_tests/qrc20_tests.rs index 7f759443a5..dfc6f3fabf 100644 --- a/mm2src/mm2_main/tests/docker_tests/qrc20_tests.rs +++ b/mm2src/mm2_main/tests/docker_tests/qrc20_tests.rs @@ -888,6 +888,7 @@ fn test_check_balance_on_order_post_base_coin_locked() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -987,6 +988,7 @@ fn test_get_max_taker_vol_and_trade_with_dynamic_trade_fee(coin: QtumCoin, priv_ "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1162,6 +1164,7 @@ fn test_trade_preimage_not_sufficient_base_coin_balance_for_ticker() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1221,6 +1224,7 @@ fn test_trade_preimage_dynamic_fee_not_sufficient_balance() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1282,6 +1286,7 @@ fn test_trade_preimage_deduct_fee_from_output_failed() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1341,6 +1346,7 @@ fn test_segwit_native_balance() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1387,6 +1393,7 @@ fn test_withdraw_and_send_from_segwit() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1435,6 +1442,7 @@ fn test_withdraw_and_send_legacy_to_segwit() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -1635,6 +1643,7 @@ fn segwit_address_in_the_orderbook() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, diff --git a/mm2src/mm2_main/tests/docker_tests/swaps_confs_settings_sync_tests.rs b/mm2src/mm2_main/tests/docker_tests/swaps_confs_settings_sync_tests.rs index 31c6c264e3..bda9b8fdfd 100644 --- a/mm2src/mm2_main/tests/docker_tests/swaps_confs_settings_sync_tests.rs +++ b/mm2src/mm2_main/tests/docker_tests/swaps_confs_settings_sync_tests.rs @@ -37,6 +37,7 @@ fn test_confirmation_settings_sync_correctly_on_buy( "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, @@ -202,6 +203,7 @@ fn test_confirmation_settings_sync_correctly_on_sell( "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".to_string(), None, diff --git a/mm2src/mm2_main/tests/docker_tests/swaps_file_lock_tests.rs b/mm2src/mm2_main/tests/docker_tests/swaps_file_lock_tests.rs index 785eb0a849..6446fa3a4f 100644 --- a/mm2src/mm2_main/tests/docker_tests/swaps_file_lock_tests.rs +++ b/mm2src/mm2_main/tests/docker_tests/swaps_file_lock_tests.rs @@ -45,6 +45,7 @@ fn swap_file_lock_prevents_double_swap_start_on_kick_start(swap_json: &str) { "rpc_password": "pass", "i_am_seed": true, "dbdir": db_folder.to_str().unwrap(), + "is_bootstrap_node": true }); let mut mm_bob = MarketMakerIt::start(bob_conf, "pass".to_string(), None).unwrap(); let (_bob_dump_log, _bob_dump_dashboard) = mm_dump(&mm_bob.log_path); @@ -88,6 +89,7 @@ fn test_swaps_should_kick_start_if_process_was_killed() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }); let mut mm_bob = MarketMakerIt::start(bob_conf.clone(), "pass".to_string(), None).unwrap(); let (_bob_dump_log, _bob_dump_dashboard) = mm_dump(&mm_bob.log_path); @@ -211,6 +213,7 @@ fn swap_should_not_kick_start_if_finished_during_waiting_for_file_lock( "rpc_password": "pass", "i_am_seed": true, "dbdir": db_folder.to_str().unwrap(), + "is_bootstrap_node": true }); let mut mm_bob = MarketMakerIt::start(bob_conf, "pass".to_string(), None).unwrap(); let (_bob_dump_log, _bob_dump_dashboard) = mm_dump(&mm_bob.log_path); diff --git a/mm2src/mm2_main/tests/docker_tests/tendermint_tests.rs b/mm2src/mm2_main/tests/docker_tests/tendermint_tests.rs index d51bc50d34..58ad67e645 100644 --- a/mm2src/mm2_main/tests/docker_tests/tendermint_tests.rs +++ b/mm2src/mm2_main/tests/docker_tests/tendermint_tests.rs @@ -850,6 +850,7 @@ mod swap { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -941,6 +942,7 @@ mod swap { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -1036,6 +1038,7 @@ mod swap { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, diff --git a/mm2src/mm2_main/tests/mm2_tests/bch_and_slp_tests.rs b/mm2src/mm2_main/tests/mm2_tests/bch_and_slp_tests.rs index cc1094e668..f03cb18e06 100644 --- a/mm2src/mm2_main/tests/mm2_tests/bch_and_slp_tests.rs +++ b/mm2src/mm2_main/tests/mm2_tests/bch_and_slp_tests.rs @@ -34,6 +34,7 @@ fn test_withdraw_cashaddresses() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -238,6 +239,7 @@ fn test_withdraw_to_different_cashaddress_network_should_fail() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -299,6 +301,7 @@ fn test_common_cashaddresses() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -502,6 +505,7 @@ fn test_sign_verify_message_bch() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -571,6 +575,7 @@ fn test_sign_verify_message_slp() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, diff --git a/mm2src/mm2_main/tests/mm2_tests/best_orders_tests.rs b/mm2src/mm2_main/tests/mm2_tests/best_orders_tests.rs index f1149c15f3..705dec58f4 100644 --- a/mm2src/mm2_main/tests/mm2_tests/best_orders_tests.rs +++ b/mm2src/mm2_main/tests/mm2_tests/best_orders_tests.rs @@ -30,6 +30,7 @@ fn test_best_orders_v2_exclude_mine() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -137,6 +138,7 @@ fn test_best_orders_no_duplicates_after_update() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -291,6 +293,7 @@ fn test_best_orders_address_and_confirmations() { "coins": bob_coins_config, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -603,6 +606,7 @@ fn zhtlc_best_orders() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, diff --git a/mm2src/mm2_main/tests/mm2_tests/lightning_tests.rs b/mm2src/mm2_main/tests/mm2_tests/lightning_tests.rs index 4fde665bd6..22c52114ce 100644 --- a/mm2src/mm2_main/tests/mm2_tests/lightning_tests.rs +++ b/mm2src/mm2_main/tests/mm2_tests/lightning_tests.rs @@ -112,6 +112,7 @@ fn start_lightning_nodes(enable_0_confs: bool) -> (MarketMakerIt, MarketMakerIt, "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -368,6 +369,7 @@ fn test_enable_lightning() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -1055,6 +1057,7 @@ fn test_sign_verify_message_lightning() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, diff --git a/mm2src/mm2_main/tests/mm2_tests/lp_bot_tests.rs b/mm2src/mm2_main/tests/mm2_tests/lp_bot_tests.rs index 846508d2f2..e95fbcff38 100644 --- a/mm2src/mm2_main/tests/mm2_tests/lp_bot_tests.rs +++ b/mm2src/mm2_main/tests/mm2_tests/lp_bot_tests.rs @@ -19,6 +19,7 @@ fn test_start_and_stop_simple_market_maker_bot() { "rpc_password": "password", "coins": coins, "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, diff --git a/mm2src/mm2_main/tests/mm2_tests/mm2_tests_inner.rs b/mm2src/mm2_main/tests/mm2_tests/mm2_tests_inner.rs index 7ad99c3b8c..988f7f6a4d 100644 --- a/mm2src/mm2_main/tests/mm2_tests/mm2_tests_inner.rs +++ b/mm2src/mm2_main/tests/mm2_tests/mm2_tests_inner.rs @@ -118,6 +118,7 @@ fn orders_of_banned_pubkeys_should_not_be_displayed() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -222,6 +223,7 @@ fn test_my_balance() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -363,6 +365,7 @@ fn test_check_balance_on_order_post() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -423,6 +426,7 @@ fn test_rpc_password_from_json() { "rpc_password": "", "i_am_seed": true, "skip_startup_checks": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -440,6 +444,7 @@ fn test_rpc_password_from_json() { "rpc_password": {"key":"value"}, "i_am_seed": true, "skip_startup_checks": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -455,6 +460,7 @@ fn test_rpc_password_from_json() { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -549,6 +555,7 @@ fn test_mmrpc_v2() { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -653,7 +660,7 @@ fn test_rpc_password_from_json_no_userpass() { "netid": 9998, "passphrase": "bob passphrase", "coins": coins, - "i_am_seed": true, + "disable_p2p": true }), "password".into(), None, @@ -943,6 +950,7 @@ fn test_withdraw_and_send() { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -1262,6 +1270,7 @@ fn test_swap_status() { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -1315,6 +1324,7 @@ fn test_order_errors_when_base_equal_rel() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -1374,6 +1384,7 @@ fn startup_passphrase(passphrase: &str, expected_address: &str) { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -1441,6 +1452,7 @@ fn test_cancel_order() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -1586,6 +1598,7 @@ fn test_cancel_all_orders() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -1734,6 +1747,7 @@ fn test_electrum_enable_conn_errors() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -1780,6 +1794,7 @@ fn test_order_should_not_be_displayed_when_node_is_down() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -1892,6 +1907,7 @@ fn test_own_orders_should_not_be_removed_from_orderbook() { "i_am_seed": true, "rpc_password": "pass", "maker_order_timeout": 5, + "is_bootstrap_node": true }), "pass".into(), None, @@ -1968,6 +1984,7 @@ fn test_show_priv_key() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -2008,6 +2025,7 @@ fn test_electrum_and_enable_response() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -2111,6 +2129,7 @@ fn set_price_with_cancel_previous_should_broadcast_cancelled_message() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -2236,6 +2255,7 @@ fn test_batch_requests() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -2311,6 +2331,7 @@ fn test_metrics_method() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -2361,7 +2382,8 @@ fn test_electrum_tx_history() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", - "metrics_interval": 30. + "metrics_interval": 30., + "is_bootstrap_node": true }), "pass".into(), None, @@ -2462,6 +2484,7 @@ fn test_convert_utxo_address() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -2673,6 +2696,7 @@ fn test_convert_eth_address() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -2779,6 +2803,7 @@ fn test_add_delegation_qtum() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -2865,6 +2890,7 @@ fn test_remove_delegation_qtum() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -2922,6 +2948,7 @@ fn test_query_delegations_info_qtum() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -2978,6 +3005,7 @@ fn test_convert_qrc20_address() { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -3125,6 +3153,7 @@ fn test_validateaddress() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -3339,6 +3368,7 @@ fn qrc20_activate_electrum() { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -3387,6 +3417,7 @@ fn test_qrc20_withdraw() { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -3469,6 +3500,7 @@ fn test_qrc20_withdraw_error() { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -3552,6 +3584,7 @@ fn test_get_raw_transaction() { "i_am_seed": true, "rpc_password": "pass", "metrics_interval": 30., + "is_bootstrap_node": true }), "pass".into(), None, @@ -3947,6 +3980,7 @@ fn test_update_maker_order() { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -4087,6 +4121,7 @@ fn test_update_maker_order_fail() { "coins": coins, "rpc_password": "password", "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -4290,6 +4325,7 @@ fn test_trade_fee_returns_numbers_in_various_formats() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -4332,6 +4368,7 @@ fn test_orderbook_is_mine_orders() { "coins": coins, "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true }), "pass".into(), None, @@ -4511,6 +4548,7 @@ fn test_mm2_db_migration() { "rpc_password": "password", "i_am_seed": true, "dbdir": mm2_folder.display().to_string(), + "is_bootstrap_node": true }), "password".into(), None, @@ -4570,6 +4608,7 @@ fn test_get_public_key() { "rpc_password": "password", "coins": coins, "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -4612,6 +4651,7 @@ fn test_get_public_key_hash() { "rpc_password": "password", "coins": coins, "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -4652,6 +4692,7 @@ fn test_get_orderbook_with_same_orderbook_ticker() { "rpc_password": "password", "coins": coins, "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -4699,6 +4740,7 @@ fn test_conf_settings_in_orderbook() { "rpc_password": "password", "coins": coins, "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -4822,6 +4864,7 @@ fn alice_can_see_confs_in_orderbook_after_sync() { "rpc_password": "password", "coins": bob_coins, "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -4973,6 +5016,7 @@ fn test_sign_verify_message_utxo() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -5040,6 +5084,7 @@ fn test_sign_verify_message_utxo_segwit() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -5121,6 +5166,7 @@ fn test_sign_verify_message_eth() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -5568,6 +5614,7 @@ fn test_enable_btc_with_sync_starting_header() { "passphrase": "bob passphrase", "coins": coins, "rpc_password": "pass", + "disable_p2p": true }), "pass".into(), None, @@ -5598,6 +5645,7 @@ fn test_btc_block_header_sync() { "passphrase": "bob passphrase", "coins": coins, "rpc_password": "pass", + "disable_p2p": true }), "pass".into(), None, @@ -5636,6 +5684,7 @@ fn test_tbtc_block_header_sync() { "passphrase": "bob passphrase", "coins": coins, "rpc_password": "pass", + "disable_p2p": true }), "pass".into(), None, @@ -6056,6 +6105,7 @@ fn test_connection_healthcheck_rpc() { thread::sleep(Duration::from_secs(2)); let mut alice_conf = Mm2TestConf::seednode(ALICE_SEED, &json!([])); + alice_conf.conf["is_bootstrap_node"] = json!(false); alice_conf.conf["seednodes"] = json!([bob_mm.my_seed_addr()]); alice_conf.conf["skip_startup_checks"] = json!(true); let alice_mm = MarketMakerIt::start(alice_conf.conf, alice_conf.rpc_password, None).unwrap(); 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 187404a580..832f23cfae 100644 --- a/mm2src/mm2_main/tests/mm2_tests/orderbook_sync_tests.rs +++ b/mm2src/mm2_main/tests/mm2_tests/orderbook_sync_tests.rs @@ -36,6 +36,7 @@ fn alice_can_see_the_active_order_after_connection() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -254,6 +255,7 @@ fn alice_can_see_the_active_order_after_orderbook_sync_segwit() { "coins": bob_coins_config, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -427,6 +429,7 @@ fn test_orderbook_segwit() { "coins": bob_coins_config, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -540,6 +543,7 @@ fn test_get_orderbook_with_same_orderbook_ticker() { "rpc_password": "password", "coins": coins, "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -586,6 +590,7 @@ fn test_conf_settings_in_orderbook() { "rpc_password": "password", "coins": coins, "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -708,6 +713,7 @@ fn alice_can_see_confs_in_orderbook_after_sync() { "rpc_password": "password", "coins": bob_coins, "i_am_seed": true, + "is_bootstrap_node": true }), "password".into(), None, @@ -848,6 +854,7 @@ fn orderbook_extended_data() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -960,6 +967,7 @@ fn orderbook_should_display_base_rel_volumes() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -1058,6 +1066,7 @@ fn orderbook_should_work_without_coins_activation() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -1139,6 +1148,7 @@ fn test_all_orders_per_pair_per_node_must_be_displayed_in_orderbook() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, @@ -1210,6 +1220,7 @@ fn setprice_min_volume_should_be_displayed_in_orderbook() { "coins": coins, "rpc_password": "pass", "i_am_seed": true, + "is_bootstrap_node": true }), "pass".into(), None, diff --git a/mm2src/mm2_p2p/src/behaviours/atomicdex.rs b/mm2src/mm2_p2p/src/behaviours/atomicdex.rs index ad649328b4..5d5806582c 100644 --- a/mm2src/mm2_p2p/src/behaviours/atomicdex.rs +++ b/mm2src/mm2_p2p/src/behaviours/atomicdex.rs @@ -22,7 +22,6 @@ use rand::seq::SliceRandom; use std::collections::hash_map::DefaultHasher; use std::collections::HashMap; use std::hash::{Hash, Hasher}; -use std::iter; use std::net::IpAddr; use std::sync::{Mutex, MutexGuard}; use std::task::{Context, Poll}; @@ -34,7 +33,6 @@ use super::request_response::{build_request_response_behaviour, PeerRequest, Pee RequestResponseSender}; use crate::application::request_response::network_info::NetworkInfoRequest; use crate::application::request_response::P2PRequest; -use crate::network::{get_all_network_seednodes, DEFAULT_NETID}; use crate::relay_address::{RelayAddress, RelayAddressError}; use crate::swarm_runtime::SwarmRuntime; use crate::{decode_message, encode_message, NetworkInfo, NetworkPorts, RequestResponseBehaviourEvent}; @@ -54,6 +52,7 @@ const CONNECTED_RELAYS_CHECK_INTERVAL: Duration = Duration::from_secs(30); const ANNOUNCE_INTERVAL: Duration = Duration::from_secs(600); const ANNOUNCE_INITIAL_DELAY: Duration = Duration::from_secs(60); const CHANNEL_BUF_SIZE: usize = 1024 * 8; +const DEFAULT_NETID: u16 = 8762; /// Used in time validation logic for each peer which runs immediately after the /// `ConnectionEstablished` event. @@ -714,23 +713,12 @@ fn start_gossipsub( .map_err(|e| AdexBehaviourError::InitializationError(e.to_owned()))?; // build a gossipsub network behaviour - let mut gossipsub = Gossipsub::new(MessageAuthenticity::Author(local_peer_id), gossipsub_config) + let gossipsub = Gossipsub::new(MessageAuthenticity::Author(local_peer_id), gossipsub_config) .map_err(|e| AdexBehaviourError::InitializationError(e.to_owned()))?; let floodsub = Floodsub::new(local_peer_id, config.netid != DEFAULT_NETID); - let mut peers_exchange = PeersExchange::new(network_info); - if !network_info.in_memory() { - // Please note WASM nodes don't support `PeersExchange` currently, - // so `get_all_network_seednodes` returns an empty list. - for (peer_id, addr, _domain) in get_all_network_seednodes(config.netid) { - let multiaddr = addr.try_to_multiaddr(network_info)?; - peers_exchange.add_peer_addresses_to_known_peers(&peer_id, iter::once(multiaddr).collect()); - if peer_id != local_peer_id { - gossipsub.add_explicit_relay(peer_id); - } - } - } + let peers_exchange = PeersExchange::new(network_info); // build a request-response network behaviour let request_response = build_request_response_behaviour(); @@ -795,6 +783,14 @@ fn start_gossipsub( Err(e) => error!("Dial {:?} failed: {:?}", relay, e), } } + + // All currently connected peers come from the config file (because we didn't connect any other + // ones yet), so it's safe to treat them as trusted nodes. + let peers: Vec<_> = libp2p::Swarm::connected_peers(&swarm).cloned().collect(); + for peer in peers { + swarm.behaviour_mut().core.gossipsub.add_explicit_peer(&peer); + } + drop(recently_dialed_peers); let mut check_connected_relays_interval = @@ -817,6 +813,7 @@ fn start_gossipsub( if swarm.disconnect_peer_id(peer_id).is_err() { error!("Disconnection from `{peer_id}` failed unexpectedly, which should never happen."); } + swarm.behaviour_mut().core.gossipsub.remove_explicit_peer(&peer_id); } loop { diff --git a/mm2src/mm2_p2p/src/lib.rs b/mm2src/mm2_p2p/src/lib.rs index b1d0283be0..ff05a6d4f6 100644 --- a/mm2src/mm2_p2p/src/lib.rs +++ b/mm2src/mm2_p2p/src/lib.rs @@ -2,7 +2,6 @@ pub mod behaviours; -mod network; mod relay_address; mod swarm_runtime; @@ -39,7 +38,6 @@ pub use libp2p::identity::{secp256k1::PublicKey as Libp2pSecpPublic, Keypair, Pu pub use libp2p::{Multiaddr, PeerId}; // relay-address related re-exports -pub use network::SeedNodeInfo; pub use relay_address::RelayAddress; pub use relay_address::RelayAddressError; diff --git a/mm2src/mm2_p2p/src/network.rs b/mm2src/mm2_p2p/src/network.rs deleted file mode 100644 index 6d5524a31e..0000000000 --- a/mm2src/mm2_p2p/src/network.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::relay_address::RelayAddress; -use libp2p::PeerId; - -pub const DEFAULT_NETID: u16 = 8762; - -pub struct SeedNodeInfo { - pub id: &'static str, - pub domain: &'static str, -} - -impl SeedNodeInfo { - pub const fn new(id: &'static str, domain: &'static str) -> Self { Self { id, domain } } -} - -#[cfg_attr(target_arch = "wasm32", allow(dead_code))] -const ALL_DEFAULT_NETID_SEEDNODES: &[SeedNodeInfo] = &[ - SeedNodeInfo::new( - "12D3KooWHKkHiNhZtKceQehHhPqwU5W1jXpoVBgS1qst899GjvTm", - "viserion.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWAToxtunEBWCoAHjefSv74Nsmxranw8juy3eKEdrQyGRF", - "rhaegal.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWSmEi8ypaVzFA1AGde2RjxNW5Pvxw3qa2fVe48PjNs63R", - "drogon.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWMrjLmrv8hNgAoVf1RfumfjyPStzd4nv5XL47zN4ZKisb", - "falkor.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWEWzbYcosK2JK9XpFXzumfgsWJW1F7BZS15yLTrhfjX2Z", - "smaug.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWJWBnkVsVNjiqUEPjLyHpiSmQVAJ5t6qt1Txv5ctJi9Xd", - "balerion.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWPR2RoPi19vQtLugjCdvVmCcGLP2iXAzbDfP3tp81ZL4d", - "kalessin.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWJDoV9vJdy6PnzwVETZ3fWGMhV41VhSbocR1h2geFqq9Y", - "icefyre.dragon-seed.com", - ), - SeedNodeInfo::new( - "12D3KooWEaZpH61H4yuQkaNG5AsyGdpBhKRppaLdAY52a774ab5u", - "seed01.kmdefi.net", - ), - SeedNodeInfo::new( - "12D3KooWAd5gPXwX7eDvKWwkr2FZGfoJceKDCA53SHmTFFVkrN7Q", - "seed02.kmdefi.net", - ), -]; - -#[cfg(target_arch = "wasm32")] -pub fn get_all_network_seednodes(_netid: u16) -> Vec<(PeerId, RelayAddress, String)> { Vec::new() } - -#[cfg(not(target_arch = "wasm32"))] -pub fn get_all_network_seednodes(netid: u16) -> Vec<(PeerId, RelayAddress, String)> { - use std::str::FromStr; - - if netid != DEFAULT_NETID { - return Vec::new(); - } - ALL_DEFAULT_NETID_SEEDNODES - .iter() - .map(|SeedNodeInfo { id, domain }| { - let peer_id = PeerId::from_str(id).unwrap_or_else(|e| panic!("Valid peer id {id}: {e}")); - let ip = - mm2_net::ip_addr::addr_to_ipv4_string(domain).unwrap_or_else(|e| panic!("Valid domain {domain}: {e}")); - let address = RelayAddress::IPv4(ip); - let domain = domain.to_string(); - (peer_id, address, domain) - }) - .collect() -} diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index 5f5fa8edfc..7fd4dc4c35 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -275,6 +275,7 @@ impl Mm2TestConf { "coins": coins, "rpc_password": DEFAULT_RPC_PASSWORD, "i_am_seed": true, + "is_bootstrap_node": true }), rpc_password: DEFAULT_RPC_PASSWORD.into(), } @@ -291,6 +292,7 @@ impl Mm2TestConf { "rpc_password": DEFAULT_RPC_PASSWORD, "i_am_seed": true, "use_trading_proto_v2": true, + "is_bootstrap_node": true }), rpc_password: DEFAULT_RPC_PASSWORD.into(), } @@ -306,6 +308,7 @@ impl Mm2TestConf { "rpc_password": DEFAULT_RPC_PASSWORD, "i_am_seed": true, "enable_hd": true, + "is_bootstrap_node": true }), rpc_password: DEFAULT_RPC_PASSWORD.into(), } @@ -322,6 +325,7 @@ impl Mm2TestConf { "i_am_seed": true, "enable_hd": true, "use_trading_proto_v2": true, + "is_bootstrap_node": true }), rpc_password: DEFAULT_RPC_PASSWORD.into(), } @@ -337,6 +341,7 @@ impl Mm2TestConf { "i_am_seed": true, "wallet_name": wallet_name, "wallet_password": wallet_password, + "is_bootstrap_node": true }), rpc_password: DEFAULT_RPC_PASSWORD.into(), } @@ -1863,6 +1868,7 @@ pub fn mm_spat() -> (&'static str, MarketMakerIt, RaiiDump, RaiiDump) { ], "i_am_seed": true, "rpc_password": "pass", + "is_bootstrap_node": true, }), "pass".into(), None, @@ -3722,6 +3728,8 @@ pub async fn test_qrc20_history_impl(local_start: Option) { "coins": coins, "rpc_password": "pass", "metrics_interval": 30., + "disable_p2p": true, + "p2p_in_memory": false }), "pass".into(), local_start,