diff --git a/Cargo.lock b/Cargo.lock index 92649835e2..f24abff6fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6969,11 +6969,12 @@ dependencies = [ [[package]] name = "timed-map" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07be2341cfbd1b8b9a84eb9212476ea383ef5cddeb85fa3ef89dc66666196619" +checksum = "ac74a5331850dc3b08de854b57674af757b6e286e7ef930baf71e0a196f53790" dependencies = [ "rustc-hash", + "serde", "web-time", ] diff --git a/mm2src/coins/Cargo.toml b/mm2src/coins/Cargo.toml index 47a5baace0..26c3b39c97 100644 --- a/mm2src/coins/Cargo.toml +++ b/mm2src/coins/Cargo.toml @@ -125,7 +125,7 @@ mm2_db = { path = "../mm2_db" } mm2_metamask = { path = "../mm2_metamask" } mm2_test_helpers = { path = "../mm2_test_helpers" } time = { version = "0.3.20", features = ["wasm-bindgen"] } -timed-map = { version = "1.3", features = ["rustc-hash", "wasm"] } +timed-map = { version = "1.4", features = ["rustc-hash", "wasm"] } tonic = { version = "0.10", default-features = false, features = ["prost", "codegen", "gzip"] } tower-service = "0.3" wasm-bindgen = "0.2.86" @@ -148,7 +148,7 @@ lightning-net-tokio = "0.0.113" rust-ini = { version = "0.13" } rustls = { version = "0.21", features = ["dangerous_configuration"] } secp256k1v24 = { version = "0.24", package = "secp256k1" } -timed-map = { version = "1.3", features = ["rustc-hash"] } +timed-map = { version = "1.4", features = ["rustc-hash"] } tokio = { version = "1.20" } tokio-rustls = { version = "0.24" } tonic = { version = "0.10", features = ["tls", "tls-webpki-roots", "gzip"] } diff --git a/mm2src/mm2_core/Cargo.toml b/mm2src/mm2_core/Cargo.toml index b3756f9b94..37cf759a9d 100644 --- a/mm2src/mm2_core/Cargo.toml +++ b/mm2src/mm2_core/Cargo.toml @@ -37,10 +37,10 @@ uuid = { version = "1.2.2", features = ["fast-rng", "serde", "v4"] } [target.'cfg(target_arch = "wasm32")'.dependencies] mm2_rpc = { path = "../mm2_rpc", features = [ "rpc_facilities" ] } -timed-map = { version = "1.3", features = ["rustc-hash", "wasm"] } +timed-map = { version = "1.4", features = ["rustc-hash", "wasm"] } wasm-bindgen-test = { version = "0.3.2" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] rustls = { version = "0.21", default-features = false } tokio = { version = "1.20", features = ["io-util", "rt-multi-thread", "net"] } -timed-map = { version = "1.3", features = ["rustc-hash"] } +timed-map = { version = "1.4", features = ["rustc-hash"] } diff --git a/mm2src/mm2_main/Cargo.toml b/mm2src/mm2_main/Cargo.toml index 28291cb210..f1a365d38a 100644 --- a/mm2src/mm2_main/Cargo.toml +++ b/mm2src/mm2_main/Cargo.toml @@ -108,7 +108,7 @@ instant = { version = "0.1.12", features = ["wasm-bindgen"] } js-sys = { version = "0.3.27" } mm2_db = { path = "../mm2_db" } mm2_test_helpers = { path = "../mm2_test_helpers" } -timed-map = { version = "1.3", features = ["rustc-hash", "wasm"] } +timed-map = { version = "1.4", features = ["rustc-hash", "wasm"] } wasm-bindgen = "0.2.86" wasm-bindgen-futures = { version = "0.4.1" } wasm-bindgen-test = { version = "0.3.1" } @@ -121,7 +121,7 @@ hyper = { version = "0.14.26", features = ["client", "http2", "server", "tcp"] } rcgen = "0.10" rustls = { version = "0.21", default-features = false } rustls-pemfile = "1.0.2" -timed-map = { version = "1.3", features = ["rustc-hash"] } +timed-map = { version = "1.4", features = ["rustc-hash"] } tokio = { version = "1.20", features = ["io-util", "rt-multi-thread", "net", "signal"] } [target.'cfg(windows)'.dependencies] diff --git a/mm2src/mm2_main/src/lp_swap.rs b/mm2src/mm2_main/src/lp_swap.rs index b15806c059..7f6cf266e8 100644 --- a/mm2src/mm2_main/src/lp_swap.rs +++ b/mm2src/mm2_main/src/lp_swap.rs @@ -532,7 +532,7 @@ struct LockedAmountInfo { struct SwapsContext { running_swaps: Mutex>>, active_swaps_v2_infos: Mutex>, - banned_pubkeys: Mutex>, + banned_pubkeys: Mutex>, swap_msgs: Mutex>, swap_v2_msgs: Mutex>, taker_swap_watchers: PaMutex, ()>>, @@ -548,7 +548,7 @@ impl SwapsContext { Ok(SwapsContext { running_swaps: Mutex::new(HashMap::new()), active_swaps_v2_infos: Mutex::new(HashMap::new()), - banned_pubkeys: Mutex::new(HashMap::new()), + banned_pubkeys: Mutex::new(TimedMap::new_with_map_kind(MapKind::FxHashMap)), swap_msgs: Mutex::new(HashMap::new()), swap_v2_msgs: Mutex::new(HashMap::new()), taker_swap_watchers: PaMutex::new(TimedMap::new_with_map_kind(MapKind::FxHashMap)), diff --git a/mm2src/mm2_main/src/lp_swap/pubkey_banning.rs b/mm2src/mm2_main/src/lp_swap/pubkey_banning.rs index 5aa8f94103..a9aded8a97 100644 --- a/mm2src/mm2_main/src/lp_swap/pubkey_banning.rs +++ b/mm2src/mm2_main/src/lp_swap/pubkey_banning.rs @@ -1,10 +1,12 @@ +use std::collections::HashMap; + use super::{SwapEvent, SwapsContext}; use chain::hash::H256; +use compatible_time::Duration; use http::Response; use mm2_core::mm_ctx::MmArc; use rpc::v1::types::H256 as H256Json; use serde_json::{self as json, Value as Json}; -use std::collections::hash_map::{Entry, HashMap}; use uuid::Uuid; #[derive(Serialize)] @@ -21,12 +23,19 @@ pub enum BanReason { } pub fn ban_pubkey_on_failed_swap(ctx: &MmArc, pubkey: H256, swap_uuid: &Uuid, event: SwapEvent) { + // Ban them for an hour. + const PENALTY: Duration = Duration::from_secs(60 * 60); + let ctx = SwapsContext::from_ctx(ctx).unwrap(); let mut banned = ctx.banned_pubkeys.lock().unwrap(); - banned.insert(pubkey.into(), BanReason::FailedSwap { - caused_by_swap: *swap_uuid, - caused_by_event: event, - }); + banned.insert_expirable( + pubkey.into(), + BanReason::FailedSwap { + caused_by_swap: *swap_uuid, + caused_by_event: event, + }, + PENALTY, + ); } pub fn is_pubkey_banned(ctx: &MmArc, pubkey: &H256Json) -> bool { @@ -47,6 +56,7 @@ pub async fn list_banned_pubkeys_rpc(ctx: MmArc) -> Result>, St struct BanPubkeysReq { pubkey: H256Json, reason: String, + duration_min: Option, } pub async fn ban_pubkey_rpc(ctx: MmArc, req: Json) -> Result>, String> { @@ -54,16 +64,25 @@ pub async fn ban_pubkey_rpc(ctx: MmArc, req: Json) -> Result>, let ctx = try_s!(SwapsContext::from_ctx(&ctx)); let mut banned_pubs = try_s!(ctx.banned_pubkeys.lock()); - match banned_pubs.entry(req.pubkey) { - Entry::Occupied(_) => ERR!("Pubkey is banned already"), - Entry::Vacant(entry) => { - entry.insert(BanReason::Manual { reason: req.reason }); - let res = try_s!(json::to_vec(&json!({ - "result": "success", - }))); - Ok(try_s!(Response::builder().body(res))) - }, + if banned_pubs.contains_key(&req.pubkey) { + return ERR!("Pubkey is banned already"); } + + if let Some(duration_min) = req.duration_min { + banned_pubs.insert_expirable( + req.pubkey, + BanReason::Manual { reason: req.reason }, + Duration::from_secs(duration_min as u64 * 60), + ); + } else { + banned_pubs.insert_constant(req.pubkey, BanReason::Manual { reason: req.reason }); + } + + let res = try_s!(json::to_vec(&json!({ + "result": "success", + }))); + + Response::builder().body(res).map_err(|e| e.to_string()) } #[derive(Deserialize)] @@ -77,13 +96,16 @@ pub async fn unban_pubkeys_rpc(ctx: MmArc, req: Json) -> Result let req: UnbanPubkeysReq = try_s!(json::from_value(req["unban_by"].clone())); let ctx = try_s!(SwapsContext::from_ctx(&ctx)); let mut banned_pubs = try_s!(ctx.banned_pubkeys.lock()); - let mut unbanned = HashMap::new(); let mut were_not_banned = vec![]; - match req { + + let unbanned = match req { UnbanPubkeysReq::All => { - unbanned = banned_pubs.drain().collect(); + let unbanned = json!(*banned_pubs); + banned_pubs.clear(); + unbanned }, UnbanPubkeysReq::Few(pubkeys) => { + let mut unbanned = HashMap::new(); for pubkey in pubkeys { match banned_pubs.remove(&pubkey) { Some(removed) => { @@ -92,8 +114,11 @@ pub async fn unban_pubkeys_rpc(ctx: MmArc, req: Json) -> Result None => were_not_banned.push(pubkey), } } + + json!(unbanned) }, - } + }; + let res = try_s!(json::to_vec(&json!({ "result": { "still_banned": *banned_pubs, diff --git a/mm2src/mm2_p2p/Cargo.toml b/mm2src/mm2_p2p/Cargo.toml index 6cc38db4d6..813e74dba6 100644 --- a/mm2src/mm2_p2p/Cargo.toml +++ b/mm2src/mm2_p2p/Cargo.toml @@ -40,13 +40,13 @@ void = "1.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] futures-rustls = "0.24" libp2p = { git = "https://github.com/KomodoPlatform/rust-libp2p.git", tag = "k-0.52.12", default-features = false, features = ["dns", "identify", "floodsub", "gossipsub", "noise", "ping", "request-response", "secp256k1", "tcp", "tokio", "websocket", "macros", "yamux"] } -timed-map = { version = "1.3", features = ["rustc-hash"] } +timed-map = { version = "1.4", features = ["rustc-hash"] } tokio = { version = "1.20", default-features = false } [target.'cfg(target_arch = "wasm32")'.dependencies] futures-rustls = "0.22" libp2p = { git = "https://github.com/KomodoPlatform/rust-libp2p.git", tag = "k-0.52.12", default-features = false, features = ["identify", "floodsub", "noise", "gossipsub", "ping", "request-response", "secp256k1", "wasm-ext", "wasm-ext-websocket", "macros", "yamux"] } -timed-map = { version = "1.3", features = ["rustc-hash", "wasm"] } +timed-map = { version = "1.4", features = ["rustc-hash", "wasm"] } [dev-dependencies] async-std = "1.6.2"