From 100f749e27451546cdacb489d2730b722b1f89af Mon Sep 17 00:00:00 2001 From: einliterflasche Date: Thu, 19 Mar 2026 17:31:53 +0100 Subject: [PATCH 01/10] build: add warning to sqlx cache if version is mismatched --- ...702c946bc4d37d50f40670b4f51d2efcce595aa6.json | 4 +++- ...9c73cad023c30705d5b41a1399ef79d8d2571d7c.json | 4 +++- ...e755d82ff1cdc2690eb464ccc607d3a613fa76a1.json | 4 +++- ...d952956edd582a0edecd45710e22dcb28785eeab.json | 6 +++++- ...54cd9431ee68360941f341386cbacf44ea598de8.json | 5 ++++- ...94e67cf98eb7d6176515e6a28c4e8ce9fda6ef15.json | 4 +++- ...460741f5cf23b5237fb676faed009106627a4ca6.json | 5 ++++- ...09ae88e56672e95e0e638af99e82df5b00595e77.json | 6 +++++- ...662b88afcef6fc5246f11c85a35869f79da61c34.json | 5 ++++- ...bebb1c0a27b2a45656549b23076d7542cfa21ecf.json | 4 +++- ...7defb220a7f5403da62a07e131cb5c399f0bf2e.json} | 8 +++++--- ...33482b2ff081234c7f9f848a7223ae04234995d9.json | 5 ++++- ...886aa665aae3c6f1e312ee444e65df1c95afe8b2.json | 4 +++- ...48a58564fa346b038866699210a63f8a33b03f0b.json | 6 +++++- ...cda35821da948bd86cc57798b4d8375baf0b51ae.json | 4 +++- dev-scripts/regenerate_sqlx_cache.sh | 16 ++++++++++++++++ 16 files changed, 73 insertions(+), 17 deletions(-) rename .sqlx/{query-e05620f420f8c1022971eeb66a803323a8cf258cbebb2834e3f7cf8f812fa646.json => query-ad44e2e0bae766c1b524a857c7defb220a7f5403da62a07e131cb5c399f0bf2e.json} (59%) diff --git a/.sqlx/query-081c729a0f1ad6e4ff3e13d6702c946bc4d37d50f40670b4f51d2efcce595aa6.json b/.sqlx/query-081c729a0f1ad6e4ff3e13d6702c946bc4d37d50f40670b4f51d2efcce595aa6.json index 8f1a96994b..94b77425c0 100644 --- a/.sqlx/query-081c729a0f1ad6e4ff3e13d6702c946bc4d37d50f40670b4f51d2efcce595aa6.json +++ b/.sqlx/query-081c729a0f1ad6e4ff3e13d6702c946bc4d37d50f40670b4f51d2efcce595aa6.json @@ -12,7 +12,9 @@ "parameters": { "Right": 1 }, - "nullable": [false] + "nullable": [ + false + ] }, "hash": "081c729a0f1ad6e4ff3e13d6702c946bc4d37d50f40670b4f51d2efcce595aa6" } diff --git a/.sqlx/query-0d465a17ebbb5761421def759c73cad023c30705d5b41a1399ef79d8d2571d7c.json b/.sqlx/query-0d465a17ebbb5761421def759c73cad023c30705d5b41a1399ef79d8d2571d7c.json index e746a4c0e9..58fbb3f892 100644 --- a/.sqlx/query-0d465a17ebbb5761421def759c73cad023c30705d5b41a1399ef79d8d2571d7c.json +++ b/.sqlx/query-0d465a17ebbb5761421def759c73cad023c30705d5b41a1399ef79d8d2571d7c.json @@ -12,7 +12,9 @@ "parameters": { "Right": 1 }, - "nullable": [true] + "nullable": [ + true + ] }, "hash": "0d465a17ebbb5761421def759c73cad023c30705d5b41a1399ef79d8d2571d7c" } diff --git a/.sqlx/query-1f332be08a5426f3fbcadea4e755d82ff1cdc2690eb464ccc607d3a613fa76a1.json b/.sqlx/query-1f332be08a5426f3fbcadea4e755d82ff1cdc2690eb464ccc607d3a613fa76a1.json index 52e81ff839..4c1f9abe8a 100644 --- a/.sqlx/query-1f332be08a5426f3fbcadea4e755d82ff1cdc2690eb464ccc607d3a613fa76a1.json +++ b/.sqlx/query-1f332be08a5426f3fbcadea4e755d82ff1cdc2690eb464ccc607d3a613fa76a1.json @@ -12,7 +12,9 @@ "parameters": { "Right": 0 }, - "nullable": [true] + "nullable": [ + true + ] }, "hash": "1f332be08a5426f3fbcadea4e755d82ff1cdc2690eb464ccc607d3a613fa76a1" } diff --git a/.sqlx/query-4ce7c42906ba69e0c8e1c0dad952956edd582a0edecd45710e22dcb28785eeab.json b/.sqlx/query-4ce7c42906ba69e0c8e1c0dad952956edd582a0edecd45710e22dcb28785eeab.json index c35d06f749..8a964df568 100644 --- a/.sqlx/query-4ce7c42906ba69e0c8e1c0dad952956edd582a0edecd45710e22dcb28785eeab.json +++ b/.sqlx/query-4ce7c42906ba69e0c8e1c0dad952956edd582a0edecd45710e22dcb28785eeab.json @@ -22,7 +22,11 @@ "parameters": { "Right": 2 }, - "nullable": [false, false, false] + "nullable": [ + false, + false, + false + ] }, "hash": "4ce7c42906ba69e0c8e1c0dad952956edd582a0edecd45710e22dcb28785eeab" } diff --git a/.sqlx/query-5cc61dd0315571bc198401a354cd9431ee68360941f341386cbacf44ea598de8.json b/.sqlx/query-5cc61dd0315571bc198401a354cd9431ee68360941f341386cbacf44ea598de8.json index 7fc74b316e..7f58635ffd 100644 --- a/.sqlx/query-5cc61dd0315571bc198401a354cd9431ee68360941f341386cbacf44ea598de8.json +++ b/.sqlx/query-5cc61dd0315571bc198401a354cd9431ee68360941f341386cbacf44ea598de8.json @@ -17,7 +17,10 @@ "parameters": { "Right": 0 }, - "nullable": [true, true] + "nullable": [ + true, + true + ] }, "hash": "5cc61dd0315571bc198401a354cd9431ee68360941f341386cbacf44ea598de8" } diff --git a/.sqlx/query-60462ce4f45f174eb4603a2d94e67cf98eb7d6176515e6a28c4e8ce9fda6ef15.json b/.sqlx/query-60462ce4f45f174eb4603a2d94e67cf98eb7d6176515e6a28c4e8ce9fda6ef15.json index 12194afa4c..c05a8a7654 100644 --- a/.sqlx/query-60462ce4f45f174eb4603a2d94e67cf98eb7d6176515e6a28c4e8ce9fda6ef15.json +++ b/.sqlx/query-60462ce4f45f174eb4603a2d94e67cf98eb7d6176515e6a28c4e8ce9fda6ef15.json @@ -12,7 +12,9 @@ "parameters": { "Right": 1 }, - "nullable": [false] + "nullable": [ + false + ] }, "hash": "60462ce4f45f174eb4603a2d94e67cf98eb7d6176515e6a28c4e8ce9fda6ef15" } diff --git a/.sqlx/query-6130b6cdd184181f890964eb460741f5cf23b5237fb676faed009106627a4ca6.json b/.sqlx/query-6130b6cdd184181f890964eb460741f5cf23b5237fb676faed009106627a4ca6.json index a3d9d364d0..2dfabcfb69 100644 --- a/.sqlx/query-6130b6cdd184181f890964eb460741f5cf23b5237fb676faed009106627a4ca6.json +++ b/.sqlx/query-6130b6cdd184181f890964eb460741f5cf23b5237fb676faed009106627a4ca6.json @@ -17,7 +17,10 @@ "parameters": { "Right": 0 }, - "nullable": [false, false] + "nullable": [ + false, + false + ] }, "hash": "6130b6cdd184181f890964eb460741f5cf23b5237fb676faed009106627a4ca6" } diff --git a/.sqlx/query-7bc8d637e7cf020bff58d05109ae88e56672e95e0e638af99e82df5b00595e77.json b/.sqlx/query-7bc8d637e7cf020bff58d05109ae88e56672e95e0e638af99e82df5b00595e77.json index 7e94ecbb1e..ea77f24f2e 100644 --- a/.sqlx/query-7bc8d637e7cf020bff58d05109ae88e56672e95e0e638af99e82df5b00595e77.json +++ b/.sqlx/query-7bc8d637e7cf020bff58d05109ae88e56672e95e0e638af99e82df5b00595e77.json @@ -22,7 +22,11 @@ "parameters": { "Right": 1 }, - "nullable": [false, true, true] + "nullable": [ + false, + true, + true + ] }, "hash": "7bc8d637e7cf020bff58d05109ae88e56672e95e0e638af99e82df5b00595e77" } diff --git a/.sqlx/query-7e58428584d28a238ab37a83662b88afcef6fc5246f11c85a35869f79da61c34.json b/.sqlx/query-7e58428584d28a238ab37a83662b88afcef6fc5246f11c85a35869f79da61c34.json index 6be7d85eba..d9f7da1d82 100644 --- a/.sqlx/query-7e58428584d28a238ab37a83662b88afcef6fc5246f11c85a35869f79da61c34.json +++ b/.sqlx/query-7e58428584d28a238ab37a83662b88afcef6fc5246f11c85a35869f79da61c34.json @@ -17,7 +17,10 @@ "parameters": { "Right": 1 }, - "nullable": [false, false] + "nullable": [ + false, + false + ] }, "hash": "7e58428584d28a238ab37a83662b88afcef6fc5246f11c85a35869f79da61c34" } diff --git a/.sqlx/query-88f761a4f7a0429cad1df0b1bebb1c0a27b2a45656549b23076d7542cfa21ecf.json b/.sqlx/query-88f761a4f7a0429cad1df0b1bebb1c0a27b2a45656549b23076d7542cfa21ecf.json index d13a0de08b..b7429dcdd7 100644 --- a/.sqlx/query-88f761a4f7a0429cad1df0b1bebb1c0a27b2a45656549b23076d7542cfa21ecf.json +++ b/.sqlx/query-88f761a4f7a0429cad1df0b1bebb1c0a27b2a45656549b23076d7542cfa21ecf.json @@ -12,7 +12,9 @@ "parameters": { "Right": 1 }, - "nullable": [false] + "nullable": [ + false + ] }, "hash": "88f761a4f7a0429cad1df0b1bebb1c0a27b2a45656549b23076d7542cfa21ecf" } diff --git a/.sqlx/query-e05620f420f8c1022971eeb66a803323a8cf258cbebb2834e3f7cf8f812fa646.json b/.sqlx/query-ad44e2e0bae766c1b524a857c7defb220a7f5403da62a07e131cb5c399f0bf2e.json similarity index 59% rename from .sqlx/query-e05620f420f8c1022971eeb66a803323a8cf258cbebb2834e3f7cf8f812fa646.json rename to .sqlx/query-ad44e2e0bae766c1b524a857c7defb220a7f5403da62a07e131cb5c399f0bf2e.json index 1835133ff0..2864bd9b4b 100644 --- a/.sqlx/query-e05620f420f8c1022971eeb66a803323a8cf258cbebb2834e3f7cf8f812fa646.json +++ b/.sqlx/query-ad44e2e0bae766c1b524a857c7defb220a7f5403da62a07e131cb5c399f0bf2e.json @@ -1,6 +1,6 @@ { "db_name": "SQLite", - "query": "\n SELECT state\n FROM swap_states\n WHERE swap_id = ?\n ", + "query": "\n SELECT state\n FROM swap_states\n WHERE swap_id = ?\n ORDER BY id ASC\n ", "describe": { "columns": [ { @@ -12,7 +12,9 @@ "parameters": { "Right": 1 }, - "nullable": [false] + "nullable": [ + false + ] }, - "hash": "e05620f420f8c1022971eeb66a803323a8cf258cbebb2834e3f7cf8f812fa646" + "hash": "ad44e2e0bae766c1b524a857c7defb220a7f5403da62a07e131cb5c399f0bf2e" } diff --git a/.sqlx/query-d32d91ca2debc4212841282533482b2ff081234c7f9f848a7223ae04234995d9.json b/.sqlx/query-d32d91ca2debc4212841282533482b2ff081234c7f9f848a7223ae04234995d9.json index b7cd990e4e..f1dcd349cb 100644 --- a/.sqlx/query-d32d91ca2debc4212841282533482b2ff081234c7f9f848a7223ae04234995d9.json +++ b/.sqlx/query-d32d91ca2debc4212841282533482b2ff081234c7f9f848a7223ae04234995d9.json @@ -17,7 +17,10 @@ "parameters": { "Right": 1 }, - "nullable": [true, true] + "nullable": [ + true, + true + ] }, "hash": "d32d91ca2debc4212841282533482b2ff081234c7f9f848a7223ae04234995d9" } diff --git a/.sqlx/query-d78acba5eb8563826dd190e0886aa665aae3c6f1e312ee444e65df1c95afe8b2.json b/.sqlx/query-d78acba5eb8563826dd190e0886aa665aae3c6f1e312ee444e65df1c95afe8b2.json index 4b61e1a597..cf0105e218 100644 --- a/.sqlx/query-d78acba5eb8563826dd190e0886aa665aae3c6f1e312ee444e65df1c95afe8b2.json +++ b/.sqlx/query-d78acba5eb8563826dd190e0886aa665aae3c6f1e312ee444e65df1c95afe8b2.json @@ -12,7 +12,9 @@ "parameters": { "Right": 1 }, - "nullable": [false] + "nullable": [ + false + ] }, "hash": "d78acba5eb8563826dd190e0886aa665aae3c6f1e312ee444e65df1c95afe8b2" } diff --git a/.sqlx/query-dff8b986c3dde27b8121775e48a58564fa346b038866699210a63f8a33b03f0b.json b/.sqlx/query-dff8b986c3dde27b8121775e48a58564fa346b038866699210a63f8a33b03f0b.json index 180b4d0c9c..ec1acabcd6 100644 --- a/.sqlx/query-dff8b986c3dde27b8121775e48a58564fa346b038866699210a63f8a33b03f0b.json +++ b/.sqlx/query-dff8b986c3dde27b8121775e48a58564fa346b038866699210a63f8a33b03f0b.json @@ -22,7 +22,11 @@ "parameters": { "Right": 1 }, - "nullable": [true, false, false] + "nullable": [ + true, + false, + false + ] }, "hash": "dff8b986c3dde27b8121775e48a58564fa346b038866699210a63f8a33b03f0b" } diff --git a/.sqlx/query-e9d422daf774d099fcbde6c4cda35821da948bd86cc57798b4d8375baf0b51ae.json b/.sqlx/query-e9d422daf774d099fcbde6c4cda35821da948bd86cc57798b4d8375baf0b51ae.json index 952f282c28..f375b6b68d 100644 --- a/.sqlx/query-e9d422daf774d099fcbde6c4cda35821da948bd86cc57798b4d8375baf0b51ae.json +++ b/.sqlx/query-e9d422daf774d099fcbde6c4cda35821da948bd86cc57798b4d8375baf0b51ae.json @@ -12,7 +12,9 @@ "parameters": { "Right": 1 }, - "nullable": [false] + "nullable": [ + false + ] }, "hash": "e9d422daf774d099fcbde6c4cda35821da948bd86cc57798b4d8375baf0b51ae" } diff --git a/dev-scripts/regenerate_sqlx_cache.sh b/dev-scripts/regenerate_sqlx_cache.sh index 659b9cc8a4..f0cde0dde0 100755 --- a/dev-scripts/regenerate_sqlx_cache.sh +++ b/dev-scripts/regenerate_sqlx_cache.sh @@ -23,6 +23,22 @@ set -e # Exit on any error +# Ensure sqlx-cli is installed and is at least version 0.8 +if ! command -v cargo-sqlx &> /dev/null; then + echo "❌ sqlx-cli is not installed. Install it with: cargo install sqlx-cli --version 0.8.6 --features sqlite --no-default-features" + exit 1 +fi + +SQLX_VERSION=$(cargo sqlx --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') +SQLX_MAJOR=$(echo "$SQLX_VERSION" | cut -d. -f1) +SQLX_MINOR=$(echo "$SQLX_VERSION" | cut -d. -f2) + +if [ "$SQLX_MAJOR" -lt 1 ] && [ "$SQLX_MINOR" -lt 8 ]; then + echo "❌ sqlx-cli version $SQLX_VERSION is too old. Version 0.8+ is required (--workspace flag)." + echo " Upgrade with: cargo install sqlx-cli --version 0.8.6 --features sqlite --no-default-features" + exit 1 +fi + echo "🔄 Regenerating SQLx query cache..." WORKSPACE_ROOT="$PWD" From 52ed4930b689bfe5347d55ab27cfa9e3d39451c8 Mon Sep 17 00:00:00 2001 From: einliterflasche Date: Thu, 19 Mar 2026 18:00:16 +0100 Subject: [PATCH 02/10] asb: log duration need to compute quote / snapshot --- CHANGELOG.md | 2 ++ monero-wallet/src/wallets.rs | 7 +++++-- swap/src/asb/event_loop.rs | 18 +++++++++++++++--- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba133e3ca5..445c8a5514 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- ASB: Log time needed to compute quote / wallet snapshot + ## [4.0.3] - 2026-03-18 - ASB: Attempt fix of `get-swaps` not showing swaps. diff --git a/monero-wallet/src/wallets.rs b/monero-wallet/src/wallets.rs index a86bb874ff..b6a3ba6eba 100644 --- a/monero-wallet/src/wallets.rs +++ b/monero-wallet/src/wallets.rs @@ -96,10 +96,13 @@ impl Wallets { .call(move |wallet| { wallet.add_listener(Box::new(tauri_wallet_listener)); }) - .await?; + .await + .context("Failed to install tauri wallet listener")?; } - let rpc_client = SimpleRequestTransport::new(daemon.to_url_string()).await?; + let rpc_client = SimpleRequestTransport::new(daemon.to_url_string()) + .await + .context("Failed to initialize rpc client")?; let daemon = Arc::new(RwLock::new((daemon, rpc_client))); let wallets = Self { diff --git a/swap/src/asb/event_loop.rs b/swap/src/asb/event_loop.rs index 94eaba933e..f851e25a3a 100644 --- a/swap/src/asb/event_loop.rs +++ b/swap/src/asb/event_loop.rs @@ -28,7 +28,7 @@ use std::convert::TryInto; use std::fmt::Debug; use std::io::Write; use std::sync::Arc; -use std::time::Duration; +use std::time::{Duration, Instant}; use swap_core::bitcoin; use swap_env::config::RefundPolicy; use swap_env::env; @@ -1056,6 +1056,8 @@ async fn capture_wallet_snapshot( external_redeem_address: &Option, transfer_amount: bitcoin::Amount, ) -> Result { + let start_time = Instant::now(); + let unlocked_balance = monero_wallet.main_wallet().await.unlocked_balance().await?; let total_balance = monero_wallet.main_wallet().await.total_balance().await?; @@ -1078,6 +1080,10 @@ async fn capture_wallet_snapshot( .estimate_fee(bitcoin::TxWithhold::weight(), Some(transfer_amount)) .await?; + let end_time = Instant::now(); + + tracing::debug!(duration_ms=%end_time.duration_since(start_time).as_millis(), "Finished capturing wallet snapshot"); + Ok(WalletSnapshot::new( unlocked_balance.into(), redeem_address, @@ -1199,7 +1205,10 @@ mod quote { use crate::monero::{Amount, AmountExt}; use anyhow::{Context, anyhow}; use rust_decimal::Decimal; - use std::{sync::Arc, time::Duration}; + use std::{ + sync::Arc, + time::{Duration, Instant}, + }; use swap_feed::LatestRate; use tokio::time::timeout; @@ -1240,6 +1249,8 @@ mod quote { P: FnOnce() -> Fut3, Fut3: futures::Future>, { + let start_time = Instant::now(); + let ask_price = latest_rate .latest_rate() .map_err(|e| Arc::new(anyhow!(e).context("Failed to get latest rate")))? @@ -1286,7 +1297,8 @@ mod quote { )) })?; - tracing::trace!(%ask_price, %unreserved_xmr_balance, %max_bitcoin_for_monero, "Computed quote"); + let end_time = Instant::now(); + tracing::info!(%ask_price, %unreserved_xmr_balance, %max_bitcoin_for_monero, duration_ms=%end_time.duration_since(start_time).as_millis(), "Computed quote"); if min_buy > max_bitcoin_for_monero { tracing::trace!( From eae22f98f468d8a0abad397dbbca62ff25e1a921 Mon Sep 17 00:00:00 2001 From: einliterflasche Date: Thu, 19 Mar 2026 18:20:35 +0100 Subject: [PATCH 03/10] asb: log when we receive instruction to withhold the deposit --- swap/src/protocol/alice/swap.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/swap/src/protocol/alice/swap.rs b/swap/src/protocol/alice/swap.rs index 9e2b28c2be..acd1512edf 100644 --- a/swap/src/protocol/alice/swap.rs +++ b/swap/src/protocol/alice/swap.rs @@ -680,6 +680,8 @@ where let mut updated_state3 = (*state3).clone(); updated_state3.should_publish_tx_withhold = Some(burn); + tracing::info!(withhold=%burn, "Received withhold decision"); + AliceState::BtcCancelled { monero_wallet_restore_blockheight, transfer_proof, From 7ae5356d77796d924d4c1423a14aa6b8e798cef8 Mon Sep 17 00:00:00 2001 From: einliterflasche Date: Fri, 20 Mar 2026 14:06:54 +0100 Subject: [PATCH 04/10] asb: reduce idle connection timeout, enable pow for onion service --- swap/src/asb/network.rs | 5 +++-- swap/src/network/swarm.rs | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/swap/src/asb/network.rs b/swap/src/asb/network.rs index 2cdaaf9aed..02d20d6359 100644 --- a/swap/src/asb/network.rs +++ b/swap/src/asb/network.rs @@ -17,8 +17,8 @@ use swap_feed::LatestRate; pub mod transport { use std::sync::Arc; - use arti_client::{config::onion_service::OnionServiceConfigBuilder, TorClient}; - use libp2p::{core::transport::OptionalTransport, dns, identity, tcp, Transport}; + use arti_client::{TorClient, config::onion_service::OnionServiceConfigBuilder}; + use libp2p::{Transport, core::transport::OptionalTransport, dns, identity, tcp}; use libp2p_tor::AddressConversion; use tor_rtcompat::tokio::TokioRustlsRuntime; @@ -54,6 +54,7 @@ pub mod transport { .expect("Static nickname to be valid"), ) .num_intro_points(num_intro_points) + .enable_pow(true) .build() .expect("We specified a valid nickname"); diff --git a/swap/src/network/swarm.rs b/swap/src/network/swarm.rs index 71fd79b947..f1ec9bf626 100644 --- a/swap/src/network/swarm.rs +++ b/swap/src/network/swarm.rs @@ -5,7 +5,7 @@ use crate::{asb, cli}; use anyhow::Result; use arti_client::TorClient; use libp2p::swarm::NetworkBehaviour; -use libp2p::{identity, Multiaddr, Swarm}; +use libp2p::{Multiaddr, Swarm, identity}; use libp2p::{PeerId, SwarmBuilder}; use std::fmt::Debug; use std::sync::Arc; @@ -15,8 +15,8 @@ use swap_env::env; use swap_p2p::libp2p_ext::MultiAddrExt; use tor_rtcompat::tokio::TokioRustlsRuntime; -// We keep connections open for 15 minutes -const IDLE_CONNECTION_TIMEOUT: Duration = Duration::from_secs(60 * 15); +// We keep connections open for 2 minutes +const IDLE_CONNECTION_TIMEOUT: Duration = Duration::from_secs(60 * 2); #[allow(clippy::too_many_arguments)] pub fn asb( From 151f52ad11a1a7f7f2f30c4661a0ebc10ac94858 Mon Sep 17 00:00:00 2001 From: einliterflasche Date: Fri, 20 Mar 2026 15:32:28 +0100 Subject: [PATCH 05/10] asb: reduce streams per connection (tor + yamux), reduce auth timeout --- Cargo.lock | 1 + swap-env/src/config.rs | 1 - swap/Cargo.toml | 1 + swap/src/asb/network.rs | 9 +++++++++ swap/src/network/transport.rs | 10 +++++++--- 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a2f4c420fc..4fa3482747 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10698,6 +10698,7 @@ dependencies = [ "time", "tokio", "tokio-util", + "tor-hsservice", "tor-rtcompat", "tracing", "tracing-appender", diff --git a/swap-env/src/config.rs b/swap-env/src/config.rs index abd7db8786..539b2abe1e 100644 --- a/swap-env/src/config.rs +++ b/swap-env/src/config.rs @@ -163,7 +163,6 @@ fn default_anti_spam_deposit_ratio() -> Decimal { Decimal::ZERO } - impl Config { pub fn read(config_file: D) -> Result where diff --git a/swap/Cargo.toml b/swap/Cargo.toml index fb8f4207dd..9e37d7f992 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -24,6 +24,7 @@ monero-wallet = { path = "../monero-wallet" } # Tor arti-client = { workspace = true, features = ["static-sqlite", "tokio", "rustls", "onion-service-service"] } tor-rtcompat = { workspace = true, features = ["tokio"] } +tor-hsservice = { workspace = true } # LibP2P libp2p = { workspace = true, features = ["tcp", "yamux", "dns", "noise", "request-response", "ping", "rendezvous", "identify", "macros", "cbor", "json", "tokio", "serde", "rsa"] } diff --git a/swap/src/asb/network.rs b/swap/src/asb/network.rs index 02d20d6359..5425fbc773 100644 --- a/swap/src/asb/network.rs +++ b/swap/src/asb/network.rs @@ -20,6 +20,7 @@ pub mod transport { use arti_client::{TorClient, config::onion_service::OnionServiceConfigBuilder}; use libp2p::{Transport, core::transport::OptionalTransport, dns, identity, tcp}; use libp2p_tor::AddressConversion; + use tor_hsservice::config::TokenBucketConfig; use tor_rtcompat::tokio::TokioRustlsRuntime; use super::*; @@ -42,6 +43,11 @@ pub mod transport { register_hidden_service: bool, num_intro_points: u8, ) -> Result { + // Streams are multiplexed via yamux, we don't need more than one. + const MAX_STREAMS_PER_CIRCUIT: u32 = 2; + // Default value + const POW_QUEUE_DEPTH: usize = 8192; + let (maybe_tor_transport, onion_addresses) = if let Some(tor_client) = maybe_tor_client { let mut tor_transport = libp2p_tor::TorTransport::from_client(tor_client, AddressConversion::DnsOnly); @@ -54,6 +60,9 @@ pub mod transport { .expect("Static nickname to be valid"), ) .num_intro_points(num_intro_points) + // DOS mitigations + .max_concurrent_streams_per_circuit(MAX_STREAMS_PER_CIRCUIT) + .pow_rend_queue_depth(POW_QUEUE_DEPTH) .enable_pow(true) .build() .expect("We specified a valid nickname"); diff --git a/swap/src/network/transport.rs b/swap/src/network/transport.rs index 0b74b22448..8742ffa2b9 100644 --- a/swap/src/network/transport.rs +++ b/swap/src/network/transport.rs @@ -4,10 +4,12 @@ use libp2p::core::muxing::StreamMuxerBox; use libp2p::core::transport::Boxed; use libp2p::core::upgrade::Version; use libp2p::noise; -use libp2p::{identity, yamux, PeerId, Transport}; +use libp2p::{PeerId, Transport, identity, yamux}; use std::time::Duration; -const AUTH_AND_MULTIPLEX_TIMEOUT: Duration = Duration::from_secs(60); +const AUTH_AND_MULTIPLEX_TIMEOUT: Duration = Duration::from_secs(15); +// We have 5 protcols, not more than 2 of which should be active at the same time. +const MAX_NUM_STREAMS: usize = 5; /// "Completes" a transport by applying the authentication and multiplexing /// upgrades. @@ -23,7 +25,9 @@ where T: AsyncRead + AsyncWrite + Unpin + Send + 'static, { let auth_upgrade = noise::Config::new(identity)?; - let multiplex_upgrade = yamux::Config::default(); + let mut multiplex_upgrade = yamux::Config::default(); + + multiplex_upgrade.set_max_num_streams(MAX_NUM_STREAMS); let transport = transport .upgrade(Version::V1) From 557045dc0210d91429ee7401a36cb5123849167d Mon Sep 17 00:00:00 2001 From: einliterflasche Date: Fri, 20 Mar 2026 15:50:27 +0100 Subject: [PATCH 06/10] update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 445c8a5514..9c645ef897 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- ASB: Log time needed to compute quote / wallet snapshot +- ASB: Tweak some networking configurations ## [4.0.3] - 2026-03-18 From 9e38dd8ef2f08134839d42ef782a6c2ec44885fd Mon Sep 17 00:00:00 2001 From: einliterflasche Date: Fri, 20 Mar 2026 18:23:35 +0100 Subject: [PATCH 07/10] asb: fix arti panic By enabling the `hs-pow-full` feature --- Cargo.lock | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ swap/Cargo.toml | 2 +- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 4fa3482747..a27df5c401 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -264,6 +264,9 @@ name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +dependencies = [ + "serde", +] [[package]] name = "arti-client" @@ -2956,6 +2959,33 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +[[package]] +name = "dynasm" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d36219658beb39702975c707dee7895943ca281ca46eebbc5ea395171b9c182b" +dependencies = [ + "bitflags 2.11.0", + "byteorder", + "lazy_static", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dynasmrt" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc32ed2a02b82bc43a7631dd624e8c5731a8377e40a468da28e62fc2e028952" +dependencies = [ + "byteorder", + "dynasm", + "fnv", + "memmap2", +] + [[package]] name = "ecdsa" version = "0.16.9" @@ -3248,6 +3278,18 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "equix" +version = "0.5.1" +source = "git+https://github.com/eigenwallet/arti?branch=downgraded_rusqlite_arti_1_8_0#2a5db5823e2a5eb413d8ad433a4d3aba902bac07" +dependencies = [ + "arrayvec", + "hashx", + "num-traits", + "thiserror 2.0.18", + "visibility", +] + [[package]] name = "erased-serde" version = "0.4.10" @@ -3421,6 +3463,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "fixed-capacity-vec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b31a14f5ee08ed1a40e1252b35af18bed062e3f39b69aab34decde36bc43e40" + [[package]] name = "fixedbitset" version = "0.5.7" @@ -4258,6 +4306,20 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "hashx" +version = "0.6.1" +source = "git+https://github.com/eigenwallet/arti?branch=downgraded_rusqlite_arti_1_8_0#2a5db5823e2a5eb413d8ad433a4d3aba902bac07" +dependencies = [ + "arrayvec", + "blake2", + "dynasmrt", + "fixed-capacity-vec", + "hex", + "rand_core 0.9.5", + "thiserror 2.0.18", +] + [[package]] name = "heck" version = "0.3.3" @@ -12470,11 +12532,14 @@ name = "tor-hscrypto" version = "0.37.0" source = "git+https://github.com/eigenwallet/arti?branch=downgraded_rusqlite_arti_1_8_0#2a5db5823e2a5eb413d8ad433a4d3aba902bac07" dependencies = [ + "arrayvec", + "blake2", "cipher", "data-encoding", "derive-deftly", "derive_more 2.1.1", "digest 0.10.7", + "equix", "hex", "humantime", "itertools 0.14.0", @@ -12502,6 +12567,7 @@ version = "0.37.0" source = "git+https://github.com/eigenwallet/arti?branch=downgraded_rusqlite_arti_1_8_0#2a5db5823e2a5eb413d8ad433a4d3aba902bac07" dependencies = [ "amplify", + "arrayvec", "async-trait", "base64ct", "cfg-if", @@ -12510,6 +12576,7 @@ dependencies = [ "derive_more 2.1.1", "digest 0.10.7", "educe", + "equix", "fs-mistrust", "futures", "growable-bloom-filter", @@ -12517,6 +12584,7 @@ dependencies = [ "humantime", "itertools 0.14.0", "k12", + "num-traits", "once_cell", "oneshot-fused-workaround", "postage", @@ -12532,6 +12600,7 @@ dependencies = [ "tor-basic-utils", "tor-bytes", "tor-cell", + "tor-checkable", "tor-circmgr", "tor-config", "tor-config-path", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 9e37d7f992..16aa07d282 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -22,7 +22,7 @@ bitcoin-wallet = { path = "../bitcoin-wallet" } monero-wallet = { path = "../monero-wallet" } # Tor -arti-client = { workspace = true, features = ["static-sqlite", "tokio", "rustls", "onion-service-service"] } +arti-client = { workspace = true, features = ["static-sqlite", "tokio", "rustls", "onion-service-service", "hs-pow-full"] } tor-rtcompat = { workspace = true, features = ["tokio"] } tor-hsservice = { workspace = true } From d6beaf78e9174bfbdf3bbb08cd1b59a96a710db1 Mon Sep 17 00:00:00 2001 From: einliterflasche Date: Fri, 20 Mar 2026 18:13:00 +0100 Subject: [PATCH 08/10] begin: protcol: add proof of work challenge to connection setup This commit does not implement the actual POW challenge yet, just a dummy. It does provide a working protocol upgrade though. A custom `InboundConnectionUpgrade`/`OutboundConnectionUpgrade` implementation that wraps `noise` (authentication + encryption) but before running the `noise` handshake the listening party sends a proof of work challenge, to which the dialing party must respond correctly. Else the connection is terminated before it is setup. This will be a breaking change. --- libp2p-rendezvous-node/src/swarm.rs | 8 +- swap-p2p/Cargo.toml | 2 +- swap-p2p/src/protocols.rs | 1 + swap-p2p/src/protocols/pow_noise.rs | 112 ++++++++++++++++++++++++++++ swap/src/network/transport.rs | 4 +- 5 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 swap-p2p/src/protocols/pow_noise.rs diff --git a/libp2p-rendezvous-node/src/swarm.rs b/libp2p-rendezvous-node/src/swarm.rs index 65e82353e4..0dff174814 100644 --- a/libp2p-rendezvous-node/src/swarm.rs +++ b/libp2p-rendezvous-node/src/swarm.rs @@ -5,12 +5,13 @@ use libp2p::core::upgrade::Version; use libp2p::identity::{self}; use libp2p::tcp; use libp2p::yamux; -use libp2p::{core::muxing::StreamMuxerBox, SwarmBuilder}; -use libp2p::{dns, noise, Multiaddr, PeerId, Swarm, Transport}; +use libp2p::{Multiaddr, PeerId, Swarm, Transport, dns, noise}; +use libp2p::{SwarmBuilder, core::muxing::StreamMuxerBox}; use libp2p_tor::{AddressConversion, TorTransport}; use std::fmt; use std::path::Path; use swap_p2p::libp2p_ext::MultiAddrVecExt; +use swap_p2p::protocols::pow_noise; use tor_hsservice::config::OnionServiceConfigBuilder; use crate::behaviour::Behaviour; @@ -178,10 +179,11 @@ where T: AsyncRead + AsyncWrite + Unpin + Send + 'static, { let noise_config = noise::Config::new(identity).unwrap(); + let pow_noise_config = pow_noise::Config::new(noise_config, 10); let transport = transport .upgrade(Version::V1) - .authenticate(noise_config) + .authenticate(pow_noise_config) .multiplex(yamux::Config::default()) .timeout(defaults::MULTIPLEX_TIMEOUT) .map(|(peer, muxer), _| (peer, StreamMuxerBox::new(muxer))) diff --git a/swap-p2p/Cargo.toml b/swap-p2p/Cargo.toml index adf0ee152a..96194d1e5e 100644 --- a/swap-p2p/Cargo.toml +++ b/swap-p2p/Cargo.toml @@ -14,7 +14,7 @@ swap-serde = { path = "../swap-serde" } # Networking async-trait = { workspace = true, optional = true } -libp2p = { workspace = true, features = ["serde", "request-response", "rendezvous", "cbor", "json", "ping", "identify"] } +libp2p = { workspace = true, features = ["serde", "request-response", "noise", "rendezvous", "cbor", "json", "ping", "identify"] } # Serialization diff --git a/swap-p2p/src/protocols.rs b/swap-p2p/src/protocols.rs index de3bf7e37a..d2be282d6c 100644 --- a/swap-p2p/src/protocols.rs +++ b/swap-p2p/src/protocols.rs @@ -1,6 +1,7 @@ pub mod cooperative_xmr_redeem_after_punish; pub mod encrypted_signature; pub mod notice; +pub mod pow_noise; pub mod quote; pub mod quotes; pub mod quotes_cached; diff --git a/swap-p2p/src/protocols/pow_noise.rs b/swap-p2p/src/protocols/pow_noise.rs new file mode 100644 index 0000000000..dda5ea1000 --- /dev/null +++ b/swap-p2p/src/protocols/pow_noise.rs @@ -0,0 +1,112 @@ +//! This protocol wraps the noise authentication protocol. +//! It requires a proof of work challenge to be completed before +//! authentication is done. + +use std::pin::Pin; + +use futures::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, FutureExt}; +use libp2p::{ + PeerId, + core::{ + UpgradeInfo, + upgrade::{InboundConnectionUpgrade, OutboundConnectionUpgrade}, + }, + noise::{self, Output}, +}; +use thiserror::Error; + +#[derive(Clone)] +pub struct Config { + inner: noise::Config, + pow_difficulty: usize, +} + +#[derive(Debug, Error)] +pub enum Error { + #[error("noise error: {}", .0)] + Noise(#[from] noise::Error), + #[error("proof of work error: {}", .0)] + Pow(#[from] PowError), +} + +#[derive(Debug, Error)] +pub enum PowError { + #[error("interface error: {}", .0)] + Io(#[from] std::io::Error), + #[error("peer sent invalid solution to pow challenge")] + InvalidSolution, +} + +impl Config { + pub fn new(noise_config: noise::Config, pow_difficulty: usize) -> Self { + Config { + inner: noise_config, + pow_difficulty, + } + } +} + +impl UpgradeInfo for Config { + type Info = &'static str; + type InfoIter = + std::iter::Chain<::InfoIter, std::iter::Once>; + + fn protocol_info(&self) -> Self::InfoIter { + self.inner.protocol_info().chain(std::iter::once("/pow")) + } +} + +impl InboundConnectionUpgrade for Config +where + T: AsyncRead + AsyncWrite + Unpin + Send + 'static, +{ + type Output = (PeerId, noise::Output); + type Error = Error; + type Future = Pin> + Send>>; + + fn upgrade_inbound(self, mut socket: T, info: Self::Info) -> Self::Future { + async move { + let challenge = b"hello, world"; + socket.write_all(challenge).await.map_err(PowError::Io)?; + let mut answer = [0u8; 12]; + socket.read_exact(&mut answer).await.map_err(PowError::Io)?; + + if &answer != b"this: answer" { + tracing::warn!("Incoming connection failed proof of work challenge"); + return Err(PowError::InvalidSolution)?; + } + + tracing::trace!("Incoming connection completed proof of work challenge"); + + Ok(self.inner.upgrade_inbound(socket, info).await?) + } + .boxed() + } +} + +impl OutboundConnectionUpgrade for Config +where + T: AsyncRead + AsyncWrite + Unpin + Send + 'static, +{ + type Output = (PeerId, Output); + type Error = Error; + type Future = Pin> + Send>>; + + fn upgrade_outbound(self, mut socket: T, info: Self::Info) -> Self::Future { + async move { + let mut challenge = [0u8; 12]; + socket + .read_exact(&mut challenge) + .await + .map_err(PowError::Io)?; + let answer = b"this: answer"; + socket.write_all(answer).await.map_err(PowError::Io)?; + + // TODO: find some way to check whether the peer accepted our solution. + // One more packet from peer? + + Ok(self.inner.upgrade_outbound(socket, info).await?) + } + .boxed() + } +} diff --git a/swap/src/network/transport.rs b/swap/src/network/transport.rs index 8742ffa2b9..2380286ab8 100644 --- a/swap/src/network/transport.rs +++ b/swap/src/network/transport.rs @@ -6,6 +6,7 @@ use libp2p::core::upgrade::Version; use libp2p::noise; use libp2p::{PeerId, Transport, identity, yamux}; use std::time::Duration; +use swap_p2p::protocols::pow_noise; const AUTH_AND_MULTIPLEX_TIMEOUT: Duration = Duration::from_secs(15); // We have 5 protcols, not more than 2 of which should be active at the same time. @@ -25,13 +26,14 @@ where T: AsyncRead + AsyncWrite + Unpin + Send + 'static, { let auth_upgrade = noise::Config::new(identity)?; + let pow_and_auth_upgrade = pow_noise::Config::new(auth_upgrade, 123); let mut multiplex_upgrade = yamux::Config::default(); multiplex_upgrade.set_max_num_streams(MAX_NUM_STREAMS); let transport = transport .upgrade(Version::V1) - .authenticate(auth_upgrade) + .authenticate(pow_and_auth_upgrade) .multiplex(multiplex_upgrade) .timeout(AUTH_AND_MULTIPLEX_TIMEOUT) .map(|(peer, muxer), _| (peer, StreamMuxerBox::new(muxer))) From 625eadb9f0fd3815dc3f4b6e080bd6c8e766fc8f Mon Sep 17 00:00:00 2001 From: einliterflasche Date: Fri, 20 Mar 2026 22:29:09 +0100 Subject: [PATCH 09/10] Revert "begin: protcol: add proof of work challenge to connection setup" This reverts commit d6beaf78e9174bfbdf3bbb08cd1b59a96a710db1. We will do that in another PR. --- libp2p-rendezvous-node/src/swarm.rs | 8 +- swap-p2p/Cargo.toml | 2 +- swap-p2p/src/protocols.rs | 1 - swap-p2p/src/protocols/pow_noise.rs | 112 ---------------------------- swap/src/network/transport.rs | 4 +- 5 files changed, 5 insertions(+), 122 deletions(-) delete mode 100644 swap-p2p/src/protocols/pow_noise.rs diff --git a/libp2p-rendezvous-node/src/swarm.rs b/libp2p-rendezvous-node/src/swarm.rs index 0dff174814..65e82353e4 100644 --- a/libp2p-rendezvous-node/src/swarm.rs +++ b/libp2p-rendezvous-node/src/swarm.rs @@ -5,13 +5,12 @@ use libp2p::core::upgrade::Version; use libp2p::identity::{self}; use libp2p::tcp; use libp2p::yamux; -use libp2p::{Multiaddr, PeerId, Swarm, Transport, dns, noise}; -use libp2p::{SwarmBuilder, core::muxing::StreamMuxerBox}; +use libp2p::{core::muxing::StreamMuxerBox, SwarmBuilder}; +use libp2p::{dns, noise, Multiaddr, PeerId, Swarm, Transport}; use libp2p_tor::{AddressConversion, TorTransport}; use std::fmt; use std::path::Path; use swap_p2p::libp2p_ext::MultiAddrVecExt; -use swap_p2p::protocols::pow_noise; use tor_hsservice::config::OnionServiceConfigBuilder; use crate::behaviour::Behaviour; @@ -179,11 +178,10 @@ where T: AsyncRead + AsyncWrite + Unpin + Send + 'static, { let noise_config = noise::Config::new(identity).unwrap(); - let pow_noise_config = pow_noise::Config::new(noise_config, 10); let transport = transport .upgrade(Version::V1) - .authenticate(pow_noise_config) + .authenticate(noise_config) .multiplex(yamux::Config::default()) .timeout(defaults::MULTIPLEX_TIMEOUT) .map(|(peer, muxer), _| (peer, StreamMuxerBox::new(muxer))) diff --git a/swap-p2p/Cargo.toml b/swap-p2p/Cargo.toml index 96194d1e5e..adf0ee152a 100644 --- a/swap-p2p/Cargo.toml +++ b/swap-p2p/Cargo.toml @@ -14,7 +14,7 @@ swap-serde = { path = "../swap-serde" } # Networking async-trait = { workspace = true, optional = true } -libp2p = { workspace = true, features = ["serde", "request-response", "noise", "rendezvous", "cbor", "json", "ping", "identify"] } +libp2p = { workspace = true, features = ["serde", "request-response", "rendezvous", "cbor", "json", "ping", "identify"] } # Serialization diff --git a/swap-p2p/src/protocols.rs b/swap-p2p/src/protocols.rs index d2be282d6c..de3bf7e37a 100644 --- a/swap-p2p/src/protocols.rs +++ b/swap-p2p/src/protocols.rs @@ -1,7 +1,6 @@ pub mod cooperative_xmr_redeem_after_punish; pub mod encrypted_signature; pub mod notice; -pub mod pow_noise; pub mod quote; pub mod quotes; pub mod quotes_cached; diff --git a/swap-p2p/src/protocols/pow_noise.rs b/swap-p2p/src/protocols/pow_noise.rs deleted file mode 100644 index dda5ea1000..0000000000 --- a/swap-p2p/src/protocols/pow_noise.rs +++ /dev/null @@ -1,112 +0,0 @@ -//! This protocol wraps the noise authentication protocol. -//! It requires a proof of work challenge to be completed before -//! authentication is done. - -use std::pin::Pin; - -use futures::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, FutureExt}; -use libp2p::{ - PeerId, - core::{ - UpgradeInfo, - upgrade::{InboundConnectionUpgrade, OutboundConnectionUpgrade}, - }, - noise::{self, Output}, -}; -use thiserror::Error; - -#[derive(Clone)] -pub struct Config { - inner: noise::Config, - pow_difficulty: usize, -} - -#[derive(Debug, Error)] -pub enum Error { - #[error("noise error: {}", .0)] - Noise(#[from] noise::Error), - #[error("proof of work error: {}", .0)] - Pow(#[from] PowError), -} - -#[derive(Debug, Error)] -pub enum PowError { - #[error("interface error: {}", .0)] - Io(#[from] std::io::Error), - #[error("peer sent invalid solution to pow challenge")] - InvalidSolution, -} - -impl Config { - pub fn new(noise_config: noise::Config, pow_difficulty: usize) -> Self { - Config { - inner: noise_config, - pow_difficulty, - } - } -} - -impl UpgradeInfo for Config { - type Info = &'static str; - type InfoIter = - std::iter::Chain<::InfoIter, std::iter::Once>; - - fn protocol_info(&self) -> Self::InfoIter { - self.inner.protocol_info().chain(std::iter::once("/pow")) - } -} - -impl InboundConnectionUpgrade for Config -where - T: AsyncRead + AsyncWrite + Unpin + Send + 'static, -{ - type Output = (PeerId, noise::Output); - type Error = Error; - type Future = Pin> + Send>>; - - fn upgrade_inbound(self, mut socket: T, info: Self::Info) -> Self::Future { - async move { - let challenge = b"hello, world"; - socket.write_all(challenge).await.map_err(PowError::Io)?; - let mut answer = [0u8; 12]; - socket.read_exact(&mut answer).await.map_err(PowError::Io)?; - - if &answer != b"this: answer" { - tracing::warn!("Incoming connection failed proof of work challenge"); - return Err(PowError::InvalidSolution)?; - } - - tracing::trace!("Incoming connection completed proof of work challenge"); - - Ok(self.inner.upgrade_inbound(socket, info).await?) - } - .boxed() - } -} - -impl OutboundConnectionUpgrade for Config -where - T: AsyncRead + AsyncWrite + Unpin + Send + 'static, -{ - type Output = (PeerId, Output); - type Error = Error; - type Future = Pin> + Send>>; - - fn upgrade_outbound(self, mut socket: T, info: Self::Info) -> Self::Future { - async move { - let mut challenge = [0u8; 12]; - socket - .read_exact(&mut challenge) - .await - .map_err(PowError::Io)?; - let answer = b"this: answer"; - socket.write_all(answer).await.map_err(PowError::Io)?; - - // TODO: find some way to check whether the peer accepted our solution. - // One more packet from peer? - - Ok(self.inner.upgrade_outbound(socket, info).await?) - } - .boxed() - } -} diff --git a/swap/src/network/transport.rs b/swap/src/network/transport.rs index 2380286ab8..8742ffa2b9 100644 --- a/swap/src/network/transport.rs +++ b/swap/src/network/transport.rs @@ -6,7 +6,6 @@ use libp2p::core::upgrade::Version; use libp2p::noise; use libp2p::{PeerId, Transport, identity, yamux}; use std::time::Duration; -use swap_p2p::protocols::pow_noise; const AUTH_AND_MULTIPLEX_TIMEOUT: Duration = Duration::from_secs(15); // We have 5 protcols, not more than 2 of which should be active at the same time. @@ -26,14 +25,13 @@ where T: AsyncRead + AsyncWrite + Unpin + Send + 'static, { let auth_upgrade = noise::Config::new(identity)?; - let pow_and_auth_upgrade = pow_noise::Config::new(auth_upgrade, 123); let mut multiplex_upgrade = yamux::Config::default(); multiplex_upgrade.set_max_num_streams(MAX_NUM_STREAMS); let transport = transport .upgrade(Version::V1) - .authenticate(pow_and_auth_upgrade) + .authenticate(auth_upgrade) .multiplex(multiplex_upgrade) .timeout(AUTH_AND_MULTIPLEX_TIMEOUT) .map(|(peer, muxer), _| (peer, StreamMuxerBox::new(muxer))) From a4126e1f6fac4ced5512d9607563ce107b106ee4 Mon Sep 17 00:00:00 2001 From: einliterflasche Date: Fri, 20 Mar 2026 22:31:05 +0100 Subject: [PATCH 10/10] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c645ef897..31f24d6724 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- ASB: Tweak some networking configurations +- ASB: Tweak some networking configurations to make DOS harder. ## [4.0.3] - 2026-03-18