diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a76e867..9d9e03b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - GUI: Changed terminology from "swap providers" to "makers" - GUI: For each maker, we now display a unique deterministically generated avatar derived from the maker's public key +- ASB (experimental): We now listen on an onion address by default using an internal Tor client. You do not need to run a Tor daemon on your own anymore. The `tor.control_port` and `tor.socks5_port` properties in the config file have been removed. A new `tor.register_hidden_service` property has been added which when set to `true` will run a hidden service on which connections will be accepted. You can configure the number of introduction points to use by setting the `tor.hidden_service_num_intro_points` (3 - 20) property in the config file. The onion address will be advertised to all rendezvous points without having to be added to `network.external_addresses`. For now, this feature is experimental and may be unstable. We recommend you use it in combination with a clearnet address. This feature is powered by [arti](https://tpo.pages.torproject.net/core/arti/), an implementation of the Tor protocol in Rust by the Tor Project. +- CLI + GUI: We can now dial makers over `/onion3/****` addresses using the integrated Tor client. ## [1.0.0-rc.6] - 2024-11-21 diff --git a/Cargo.lock b/Cargo.lock index b23a5ea9..b8f4d576 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -299,6 +299,9 @@ dependencies = [ "tor-dirmgr", "tor-error", "tor-guardmgr", + "tor-hsclient", + "tor-hscrypto", + "tor-hsservice", "tor-keymgr", "tor-linkspec", "tor-llcrypto", @@ -331,7 +334,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror 1.0.69", - "time 0.3.36", + "time 0.3.37", ] [[package]] @@ -347,7 +350,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror 1.0.69", - "time 0.3.36", + "time 0.3.37", ] [[package]] @@ -755,12 +758,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" -[[package]] -name = "base32" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" - [[package]] name = "base58-monero" version = "0.3.2" @@ -925,7 +922,7 @@ dependencies = [ "bitcoincore-rpc-json", "futures", "hex", - "hmac 0.12.1", + "hmac", "jsonrpc_client", "rand 0.8.5", "reqwest", @@ -1018,7 +1015,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding", "generic-array", ] @@ -1031,12 +1027,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - [[package]] name = "block2" version = "0.5.1" @@ -1640,7 +1630,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" dependencies = [ - "time 0.3.36", + "time 0.3.37", "version_check", ] @@ -1863,16 +1853,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-mac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" -dependencies = [ - "generic-array", - "subtle", -] - [[package]] name = "cssparser" version = "0.27.2" @@ -2176,7 +2156,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "sha3 0.10.8", + "sha3", "strum", "syn 2.0.90", "void", @@ -2889,9 +2869,9 @@ dependencies = [ [[package]] name = "fs-mistrust" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12a327e6e1ee5595f66105852c644a2d65dfbc62c30c90f53a2783d270002de" +checksum = "050503efe568c5c90c13ef9b6a47fd5b657fb9605d6230a179aa190d004b65db" dependencies = [ "derive_builder_fork_arti", "dirs", @@ -2899,7 +2879,7 @@ dependencies = [ "once_cell", "pwd-grp", "serde", - "thiserror 1.0.69", + "thiserror 2.0.4", "walkdir", ] @@ -2923,6 +2903,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "fslock-arti-fork" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b21bd626aaab7b904b20bef6d9e06298914a0c8d9fb8b010483766b2e532791" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "fslock-guard" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f261f25f1e94963fe8f72863f4da841b280fa3b5a573990b425a26b585a54578" +dependencies = [ + "fslock-arti-fork", + "thiserror 2.0.4", + "winapi", +] + [[package]] name = "funty" version = "2.0.0" @@ -3416,6 +3417,18 @@ dependencies = [ "subtle", ] +[[package]] +name = "growable-bloom-filter" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d174ccb4ba660d431329e7f0797870d0a4281e36353ec4b4a3c5eab6c2cfb6f1" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "xxhash-rust", +] + [[package]] name = "gtk" version = "0.18.1" @@ -3679,17 +3692,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ - "hmac 0.12.1", -] - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac", - "digest 0.9.0", + "hmac", ] [[package]] @@ -4548,6 +4551,16 @@ dependencies = [ "jsonrpsee-types", ] +[[package]] +name = "k12" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4dc5fdb62af2f520116927304f15d25b3c2667b4817b90efdc045194c912c54" +dependencies = [ + "digest 0.10.7", + "sha3", +] + [[package]] name = "keccak" version = "0.1.5" @@ -4730,13 +4743,19 @@ dependencies = [ [[package]] name = "libp2p-community-tor" -version = "0.4.1" -source = "git+https://github.com/UnstoppableSwap/libp2p-tor?branch=main#b7e67aeb551ba2e72634be33837a00428286da38" +version = "0.5.0" +source = "git+https://github.com/UnstoppableSwap/libp2p-tor?branch=fix/announce-address-immed#3b227a639fb2169662a0b6fba8fd116560ed0adf" dependencies = [ + "anyhow", "arti-client", + "data-encoding", "futures", "libp2p", + "thiserror 1.0.69", "tokio", + "tor-cell", + "tor-hsservice", + "tor-proto", "tor-rtcompat", "tracing", ] @@ -6646,7 +6665,7 @@ dependencies = [ "indexmap 2.7.0", "quick-xml", "serde", - "time 0.3.36", + "time 0.3.37", ] [[package]] @@ -6981,7 +7000,7 @@ dependencies = [ "rustc-hash 2.1.0", "rustls 0.23.19", "socket2", - "thiserror 2.0.3", + "thiserror 2.0.4", "tokio", "tracing", ] @@ -7000,7 +7019,7 @@ dependencies = [ "rustls 0.23.19", "rustls-pki-types", "slab", - "thiserror 2.0.3", + "thiserror 2.0.4", "tinyvec", "tracing", "web-time", @@ -7159,7 +7178,7 @@ checksum = "52c4f3084aa3bc7dfbba4eff4fab2a54db4324965d8872ab933565e6fbd83bc6" dependencies = [ "pem", "ring 0.16.20", - "time 0.3.36", + "time 0.3.37", "yasna", ] @@ -7312,9 +7331,9 @@ dependencies = [ [[package]] name = "retry-error" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ef93545b13f6dd83a9f98c8a656ccbd7bc2b95a747844346c70f7e6f5a5932" +checksum = "424b17c3ab6f4584c2a079c282ada3b63c660551749c9d814da23a07c9a3dd08" [[package]] name = "rfc6979" @@ -7322,7 +7341,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "hmac 0.12.1", + "hmac", "subtle", ] @@ -7436,7 +7455,7 @@ dependencies = [ "hashlink", "libsqlite3-sys", "smallvec", - "time 0.3.36", + "time 0.3.37", ] [[package]] @@ -7681,15 +7700,15 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safelog" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00c331d3dad51d67db003b70b4e1ab8408c5b89f5830af4d282e612a75a84f3" +checksum = "5738eff432cfb1f861b0d7d2cfc7c3fabef53b8585840f16ce2eb980c782133b" dependencies = [ "derive_more 1.0.0", "educe", "either", "fluid-let", - "thiserror 1.0.69", + "thiserror 2.0.4", ] [[package]] @@ -7984,6 +8003,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + [[package]] name = "serde_cbor" version = "0.11.2" @@ -8094,7 +8122,7 @@ dependencies = [ "serde_derive", "serde_json", "serde_with_macros 3.11.0", - "time 0.3.36", + "time 0.3.37", ] [[package]] @@ -8226,18 +8254,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug", -] - [[package]] name = "sha3" version = "0.10.8" @@ -8390,14 +8406,14 @@ dependencies = [ [[package]] name = "slotmap-careful" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0521c412b8940cf10d63e88faa7b63839ced20547e6d49d86417d90d0c1af8ad" +checksum = "b0a59a806f2fa2def01b97bba3a7947cf47daac2ddf6a1b0701063aeafe5b129" dependencies = [ "paste", "serde", "slotmap", - "thiserror 1.0.69", + "thiserror 2.0.4", "void", ] @@ -8652,7 +8668,7 @@ dependencies = [ "generic-array", "hex", "hkdf", - "hmac 0.12.1", + "hmac", "itoa 1.0.14", "log", "md-5", @@ -8691,7 +8707,7 @@ dependencies = [ "futures-util", "hex", "hkdf", - "hmac 0.12.1", + "hmac", "home", "itoa 1.0.14", "log", @@ -8960,14 +8976,13 @@ dependencies = [ "tempfile", "testcontainers", "thiserror 1.0.69", - "time 0.3.36", + "time 0.3.37", "tokio", "tokio-tar", "tokio-tungstenite", "tokio-util", "toml 0.8.19", "tor-rtcompat", - "torut", "tower", "tower-http", "tracing", @@ -9207,7 +9222,7 @@ dependencies = [ "tauri-runtime", "tauri-runtime-wry", "tauri-utils", - "thiserror 2.0.3", + "thiserror 2.0.4", "tokio", "tray-icon", "url", @@ -9260,8 +9275,8 @@ dependencies = [ "sha2 0.10.8", "syn 2.0.90", "tauri-utils", - "thiserror 2.0.3", - "time 0.3.36", + "thiserror 2.0.4", + "time 0.3.37", "url", "uuid", "walkdir", @@ -9368,7 +9383,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "thiserror 2.0.3", + "thiserror 2.0.4", "tracing", "windows-sys 0.59.0", "zbus", @@ -9412,8 +9427,8 @@ dependencies = [ "tauri", "tauri-plugin", "tempfile", - "thiserror 2.0.3", - "time 0.3.36", + "thiserror 2.0.4", + "time 0.3.37", "tokio", "url", "windows-sys 0.59.0", @@ -9434,7 +9449,7 @@ dependencies = [ "serde", "serde_json", "tauri-utils", - "thiserror 2.0.3", + "thiserror 2.0.4", "url", "windows 0.58.0", ] @@ -9495,7 +9510,7 @@ dependencies = [ "serde_json", "serde_with 3.11.0", "swift-rs", - "thiserror 2.0.3", + "thiserror 2.0.4", "toml 0.8.19", "url", "urlpattern", @@ -9546,7 +9561,7 @@ dependencies = [ "bollard-stubs", "futures", "hex", - "hmac 0.12.1", + "hmac", "log", "rand 0.8.5", "serde", @@ -9580,11 +9595,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "2f49a1853cf82743e3b7950f77e0f4d622ca36cf4317cba00c767838bac8d490" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.4", ] [[package]] @@ -9600,9 +9615,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "8381894bb3efe0c4acac3ded651301ceee58a15d47c2e34885ed1908ad667061" dependencies = [ "proc-macro2", "quote", @@ -9643,9 +9658,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa 1.0.14", @@ -9666,9 +9681,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -9710,9 +9725,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -9982,6 +9997,7 @@ dependencies = [ "tor-bytes", "tor-cert", "tor-error", + "tor-hscrypto", "tor-linkspec", "tor-llcrypto", "tor-memquota", @@ -9996,6 +10012,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b8eaa55aa20a3cab77943e176ed48f34c90d9ba0dc98c64adef6c15aef0bc8" dependencies = [ "caret", + "derive_builder_fork_arti", "derive_more 1.0.0", "digest 0.10.7", "thiserror 1.0.69", @@ -10179,6 +10196,7 @@ dependencies = [ "thiserror 1.0.69", "tor-circmgr", "tor-error", + "tor-hscrypto", "tor-linkspec", "tor-llcrypto", "tor-netdoc", @@ -10220,7 +10238,7 @@ dependencies = [ "signature 2.2.0", "strum", "thiserror 1.0.69", - "time 0.3.36", + "time 0.3.37", "tor-async-utils", "tor-basic-utils", "tor-checkable", @@ -10310,13 +10328,58 @@ dependencies = [ "tracing", ] +[[package]] +name = "tor-hsclient" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ac236cd5ea5e96590e10adaf71cb0f48678d24da59b724b9cc7cfa552a14ba0" +dependencies = [ + "async-trait", + "derive-deftly", + "derive_more 1.0.0", + "educe", + "either", + "futures", + "itertools", + "oneshot-fused-workaround", + "postage", + "rand 0.8.5", + "retry-error", + "safelog", + "slotmap-careful", + "strum", + "thiserror 1.0.69", + "tor-async-utils", + "tor-basic-utils", + "tor-bytes", + "tor-cell", + "tor-checkable", + "tor-circmgr", + "tor-config", + "tor-dirclient", + "tor-error", + "tor-hscrypto", + "tor-keymgr", + "tor-linkspec", + "tor-llcrypto", + "tor-memquota", + "tor-netdir", + "tor-netdoc", + "tor-persist", + "tor-proto", + "tor-rtcompat", + "tracing", +] + [[package]] name = "tor-hscrypto" version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f00099189e52d3376082b58139759249f16a53119d3d4f5f023168881c87d0a0" dependencies = [ + "cipher", "data-encoding", + "derive-deftly", "derive_more 1.0.0", "digest 0.10.7", "itertools", @@ -10330,8 +10393,67 @@ dependencies = [ "tor-bytes", "tor-error", "tor-llcrypto", + "tor-memquota", "tor-units", "void", + "zeroize", +] + +[[package]] +name = "tor-hsservice" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eaf9ac91fff7b5e009da2a4c88b34db4ee8d6416a8cd2907659e715641169bd" +dependencies = [ + "amplify", + "async-trait", + "base64ct", + "cfg-if", + "derive-deftly", + "derive_builder_fork_arti", + "derive_more 1.0.0", + "digest 0.10.7", + "educe", + "fs-mistrust", + "futures", + "growable-bloom-filter", + "hex", + "humantime", + "itertools", + "k12", + "once_cell", + "oneshot-fused-workaround", + "postage", + "rand 0.8.5", + "rand_core 0.6.4", + "retry-error", + "safelog", + "serde", + "serde_with 3.11.0", + "strum", + "thiserror 1.0.69", + "tor-async-utils", + "tor-basic-utils", + "tor-bytes", + "tor-cell", + "tor-circmgr", + "tor-config", + "tor-dirclient", + "tor-error", + "tor-hscrypto", + "tor-keymgr", + "tor-linkspec", + "tor-llcrypto", + "tor-log-ratelim", + "tor-netdir", + "tor-netdoc", + "tor-persist", + "tor-proto", + "tor-protover", + "tor-relay-selection", + "tor-rtcompat", + "tracing", + "void", ] [[package]] @@ -10440,7 +10562,7 @@ dependencies = [ "serde", "sha1", "sha2 0.10.8", - "sha3 0.10.8", + "sha3", "signature 2.2.0", "subtle", "thiserror 1.0.69", @@ -10502,7 +10624,9 @@ checksum = "68a99ad35659954aa280e678c3af2ab68934caaf55b94b947e2fb6f850598b5a" dependencies = [ "bitflags 2.6.0", "derive_more 1.0.0", + "digest 0.10.7", "futures", + "hex", "humantime", "itertools", "num_enum", @@ -10511,8 +10635,10 @@ dependencies = [ "static_assertions", "strum", "thiserror 1.0.69", + "time 0.3.37", "tor-basic-utils", "tor-error", + "tor-hscrypto", "tor-linkspec", "tor-llcrypto", "tor-netdoc", @@ -10541,13 +10667,14 @@ dependencies = [ "itertools", "once_cell", "phf 0.11.2", + "rand 0.8.5", "serde", "serde_with 3.11.0", "signature 2.2.0", "smallvec", "subtle", "thiserror 1.0.69", - "time 0.3.36", + "time 0.3.37", "tinystr", "tor-basic-utils", "tor-bytes", @@ -10555,8 +10682,11 @@ dependencies = [ "tor-cert", "tor-checkable", "tor-error", + "tor-hscrypto", + "tor-linkspec", "tor-llcrypto", "tor-protover", + "tor-units", "void", "weak-table", "zeroize", @@ -10568,11 +10698,13 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69b035192b529f6316c77d969f1e3be9f85d61ca1e1f946c91a96f987fdaba5e" dependencies = [ + "amplify", "derive-deftly", "derive_more 1.0.0", "filetime", "fs-mistrust", "fslock", + "fslock-guard", "futures", "itertools", "oneshot-fused-workaround", @@ -10606,7 +10738,7 @@ dependencies = [ "educe", "futures", "hkdf", - "hmac 0.12.1", + "hmac", "oneshot-fused-workaround", "pin-project", "rand 0.8.5", @@ -10624,6 +10756,7 @@ dependencies = [ "tor-checkable", "tor-config", "tor-error", + "tor-hscrypto", "tor-linkspec", "tor-llcrypto", "tor-log-ratelim", @@ -10633,6 +10766,7 @@ dependencies = [ "tor-units", "tracing", "typenum", + "visibility", "void", "zeroize", ] @@ -10745,24 +10879,6 @@ dependencies = [ "tor-memquota", ] -[[package]] -name = "torut" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99febc413f26cf855b3a309c5872edff5c31e0ffe9c2fce5681868761df36f69" -dependencies = [ - "base32", - "base64 0.13.1", - "derive_more 0.99.18", - "ed25519-dalek 1.0.1", - "hex", - "hmac 0.11.0", - "rand 0.7.3", - "sha2 0.9.9", - "sha3 0.9.1", - "tokio", -] - [[package]] name = "tower" version = "0.4.13" @@ -10846,7 +10962,7 @@ checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", "thiserror 1.0.69", - "time 0.3.36", + "time 0.3.37", "tracing-subscriber", ] @@ -10908,7 +11024,7 @@ dependencies = [ "sharded-slab", "smallvec", "thread_local", - "time 0.3.36", + "time 0.3.37", "tracing", "tracing-core", "tracing-log", @@ -11323,7 +11439,7 @@ dependencies = [ "cfg-if", "git2", "rustversion", - "time 0.3.36", + "time 0.3.37", ] [[package]] @@ -12295,7 +12411,7 @@ dependencies = [ "oid-registry 0.6.1", "rusticata-macros", "thiserror 1.0.69", - "time 0.3.36", + "time 0.3.37", ] [[package]] @@ -12312,7 +12428,7 @@ dependencies = [ "oid-registry 0.7.1", "rusticata-macros", "thiserror 1.0.69", - "time 0.3.36", + "time 0.3.37", ] [[package]] @@ -12348,9 +12464,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af310deaae937e48a26602b730250b4949e125f468f11e6990be3e5304ddd96f" +checksum = "ea8b391c9a790b496184c29f7f93b9ed5b16abb306c05415b68bcc16e4d06432" [[package]] name = "xmltree" @@ -12361,6 +12477,12 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "xxhash-rust" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" + [[package]] name = "yamux" version = "0.12.1" @@ -12398,7 +12520,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.36", + "time 0.3.37", ] [[package]] @@ -12597,7 +12719,7 @@ dependencies = [ "displaydoc", "indexmap 2.7.0", "memchr", - "thiserror 2.0.3", + "thiserror 2.0.4", ] [[package]] diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 758114b5..f4b9ce5e 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -275,8 +275,14 @@ async fn initialize_context( .to_string_lossy() .starts_with("monero-wallet-rpc") { - println!("Killing monero-wallet-rpc process with pid: {}", pid); - process.kill(); + #[cfg(not(debug_assertions))] + { + println!("Killing monero-wallet-rpc process with pid: {}", pid); + process.kill(); + } + + #[cfg(debug_assertions)] + println!("Would kill monero-wallet-rpc process with pid: {}", pid); } } diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 4293cabe..8576fe87 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -42,7 +42,7 @@ hex = "0.4" jsonrpsee = { version = "0.16.2", features = [ "server" ] } jsonrpsee-core = "0.16.2" libp2p = { version = "0.53.2", features = [ "tcp", "yamux", "dns", "noise", "request-response", "ping", "rendezvous", "identify", "macros", "cbor", "json", "tokio", "serde", "rsa" ] } -libp2p-community-tor = { git = "https://github.com/UnstoppableSwap/libp2p-tor", branch = "main" } +libp2p-community-tor = { git = "https://github.com/UnstoppableSwap/libp2p-tor", branch = "fix/announce-address-immed", features = [ "listen-onion-service" ] } monero = { version = "0.12", features = [ "serde_support" ] } monero-rpc = { path = "../monero-rpc" } once_cell = "1.19" @@ -96,10 +96,6 @@ tokio-tungstenite = { version = "0.15", features = [ "rustls-tls" ] } tokio-util = { version = "0.7", features = [ "io", "codec" ] } toml = "0.8" tor-rtcompat = "0.24.0" -torut = { version = "0.2", default-features = false, features = [ - "v3", - "control", -] } tower = { version = "0.4.13", features = [ "full" ] } tower-http = { version = "0.3.4", features = [ "full" ] } tracing = { version = "0.1", features = [ "attributes" ] } diff --git a/swap/src/asb/config.rs b/swap/src/asb/config.rs index 4f595dcd..dee3fca9 100644 --- a/swap/src/asb/config.rs +++ b/swap/src/asb/config.rs @@ -1,10 +1,9 @@ use crate::env::{Mainnet, Testnet}; use crate::fs::{ensure_directory_exists, system_config_dir, system_data_dir}; -use crate::tor::{DEFAULT_CONTROL_PORT, DEFAULT_SOCKS5_PORT}; use anyhow::{bail, Context, Result}; use config::ConfigError; use dialoguer::theme::ColorfulTheme; -use dialoguer::Input; +use dialoguer::{Input, Select}; use libp2p::core::Multiaddr; use rust_decimal::prelude::FromPrimitive; use rust_decimal::Decimal; @@ -200,8 +199,8 @@ pub struct Monero { #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] pub struct TorConf { - pub control_port: u16, - pub socks5_port: u16, + pub register_hidden_service: bool, + pub hidden_service_num_intro_points: u8, } #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] @@ -219,8 +218,8 @@ pub struct Maker { impl Default for TorConf { fn default() -> Self { Self { - control_port: DEFAULT_CONTROL_PORT, - socks5_port: DEFAULT_SOCKS5_PORT, + register_hidden_service: true, + hidden_service_num_intro_points: 5, } } } @@ -313,15 +312,12 @@ pub fn query_user_for_initial_config(testnet: bool) -> Result { .default(defaults.monero_wallet_rpc_url) .interact_text()?; - let tor_control_port = Input::with_theme(&ColorfulTheme::default()) - .with_prompt("Enter Tor control port or hit enter to use default. If Tor is not running on your machine, no hidden service will be created.") - .default(DEFAULT_CONTROL_PORT.to_owned()) - .interact_text()?; - - let tor_socks5_port = Input::with_theme(&ColorfulTheme::default()) - .with_prompt("Enter Tor socks5 port or hit enter to use default") - .default(DEFAULT_SOCKS5_PORT.to_owned()) - .interact_text()?; + let register_hidden_service = Select::with_theme(&ColorfulTheme::default()) + .with_prompt("Do you want a Tor hidden service to be created? This will allow you to run from behind a firewall without opening ports, and hide your IP address. You do not have to run a Tor daemon yourself. We recommend this for most users. (y/n)") + .items(&["yes", "no"]) + .default(0) + .interact()? + == 0; let min_buy = Input::with_theme(&ColorfulTheme::default()) .with_prompt("Enter minimum Bitcoin amount you are willing to accept per swap or hit enter to use default.") @@ -387,8 +383,8 @@ pub fn query_user_for_initial_config(testnet: bool) -> Result { network: monero_network, }, tor: TorConf { - control_port: tor_control_port, - socks5_port: tor_socks5_port, + register_hidden_service, + ..Default::default() }, maker: Maker { min_buy_btc: min_buy, diff --git a/swap/src/asb/event_loop.rs b/swap/src/asb/event_loop.rs index e40bf850..4fc45b21 100644 --- a/swap/src/asb/event_loop.rs +++ b/swap/src/asb/event_loop.rs @@ -490,7 +490,7 @@ where ) })?; - tracing::debug!(%ask_price, %xmr_balance, %max_bitcoin_for_monero, "Computed quote"); + tracing::trace!(%ask_price, %xmr_balance, %max_bitcoin_for_monero, "Computed quote"); if min_buy > max_bitcoin_for_monero { tracing::trace!( diff --git a/swap/src/asb/network.rs b/swap/src/asb/network.rs index a2a0df51..03102146 100644 --- a/swap/src/asb/network.rs +++ b/swap/src/asb/network.rs @@ -22,16 +22,81 @@ use std::time::Duration; use uuid::Uuid; pub mod transport { - use libp2p::{dns, identity, tcp, Transport}; + use std::sync::Arc; + + use arti_client::{config::onion_service::OnionServiceConfigBuilder, TorClient}; + use libp2p::{core::transport::OptionalTransport, dns, identity, tcp, Transport}; + use libp2p_community_tor::AddressConversion; + use tor_rtcompat::tokio::TokioRustlsRuntime; use super::*; + static ASB_ONION_SERVICE_NICKNAME: &str = "asb"; + static ASB_ONION_SERVICE_PORT: u16 = 9939; + + type OnionTransportWithAddresses = (Boxed<(PeerId, StreamMuxerBox)>, Vec); + /// Creates the libp2p transport for the ASB. - pub fn new(identity: &identity::Keypair) -> Result> { - let tcp = tcp::tokio::Transport::new(tcp::Config::new().nodelay(true)); + /// + /// If you pass in a `None` for `maybe_tor_client`, the ASB will not use Tor at all. + /// + /// If you pass in a `Some(tor_client)`, the ASB will listen on an onion service and return + /// the onion address. If it fails to listen on the onion address, it will only use tor for + /// dialing and not listening. + pub fn new( + identity: &identity::Keypair, + maybe_tor_client: Option>>, + num_intro_points: u8, + register_hidden_service: bool, + ) -> Result { + let (maybe_tor_transport, onion_addresses) = if let Some(tor_client) = maybe_tor_client { + let mut tor_transport = libp2p_community_tor::TorTransport::from_client( + tor_client, + AddressConversion::DnsOnly, + ); + + let addresses = if register_hidden_service { + let onion_service_config = OnionServiceConfigBuilder::default() + .nickname( + ASB_ONION_SERVICE_NICKNAME + .parse() + .expect("Static nickname to be valid"), + ) + .num_intro_points(num_intro_points) + .build() + .expect("We specified a valid nickname"); + + match tor_transport.add_onion_service(onion_service_config, ASB_ONION_SERVICE_PORT) + { + Ok(addr) => { + tracing::debug!( + %addr, + "Setting up onion service for libp2p to listen on" + ); + vec![addr] + } + Err(err) => { + tracing::warn!(error=%err, "Failed to listen on onion address"); + vec![] + } + } + } else { + vec![] + }; + + (OptionalTransport::some(tor_transport), addresses) + } else { + (OptionalTransport::none(), vec![]) + }; + + let tcp = maybe_tor_transport + .or_transport(tcp::tokio::Transport::new(tcp::Config::new().nodelay(true))); let tcp_with_dns = dns::tokio::Transport::system(tcp)?; - authenticate_and_multiplex(tcp_with_dns.boxed(), identity) + Ok(( + authenticate_and_multiplex(tcp_with_dns.boxed(), identity)?, + onion_addresses, + )) } } diff --git a/swap/src/bin/asb.rs b/swap/src/bin/asb.rs index 9ca4da0b..b7d85b23 100644 --- a/swap/src/bin/asb.rs +++ b/swap/src/bin/asb.rs @@ -14,12 +14,9 @@ use anyhow::{bail, Context, Result}; use comfy_table::Table; -use libp2p::core::multiaddr::Protocol; -use libp2p::core::Multiaddr; use libp2p::Swarm; use std::convert::TryInto; use std::env; -use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::sync::Arc; use structopt::clap; use structopt::clap::ErrorKind; @@ -28,6 +25,7 @@ use swap::asb::config::{ initial_setup, query_user_for_initial_config, read_config, Config, ConfigNotInitialized, }; use swap::asb::{cancel, punish, redeem, refund, safely_abort, EventLoop, Finality, KrakenRate}; +use swap::common::tor::init_tor_client; use swap::common::tracing_util::Format; use swap::common::{self, get_logs, warn_if_outdated}; use swap::database::{open_db, AccessMode}; @@ -35,8 +33,7 @@ use swap::network::rendezvous::XmrBtcNamespace; use swap::network::swarm; use swap::protocol::alice::{run, AliceState}; use swap::seed::Seed; -use swap::tor::AuthenticatedClient; -use swap::{bitcoin, kraken, monero, tor}; +use swap::{bitcoin, kraken, monero}; use tracing_subscriber::filter::LevelFilter; const DEFAULT_WALLET_NAME: &str = "asb-wallet"; @@ -149,29 +146,16 @@ pub async fn main() -> Result<()> { let bitcoin_balance = bitcoin_wallet.balance().await?; tracing::info!(%bitcoin_balance, "Bitcoin wallet balance"); + // Connect to Kraken let kraken_price_updates = kraken::connect(config.maker.price_ticker_ws_url.clone())?; - // Setup Tor hidden services - let tor_client = - tor::Client::new(config.tor.socks5_port).with_control_port(config.tor.control_port); - let _ac = match tor_client.assert_tor_running().await { - Ok(_) => { - tracing::info!("Setting up Tor hidden service"); - let ac = - register_tor_services(config.network.clone().listen, tor_client, &seed) - .await?; - Some(ac) - } - Err(_) => { - tracing::warn!("Tor not found. Running on clear net"); - None - } - }; - let kraken_rate = KrakenRate::new(config.maker.ask_spread, kraken_price_updates); let namespace = XmrBtcNamespace::from_is_testnet(testnet); - let mut swarm = swarm::asb( + // Initialize Tor client + let tor_client = init_tor_client(&config.data.dir).await?.into(); + + let (mut swarm, onion_addresses) = swarm::asb( &seed, config.maker.min_buy_btc, config.maker.max_buy_btc, @@ -180,6 +164,8 @@ pub async fn main() -> Result<()> { env_config, namespace, &rendezvous_addrs, + tor_client, + config.tor, )?; for listen in config.network.listen.clone() { @@ -188,10 +174,25 @@ pub async fn main() -> Result<()> { } } + for onion_address in onion_addresses { + match swarm.listen_on(onion_address.clone()) { + Err(e) => { + tracing::warn!( + "Failed to listen on onion address {}: {}", + onion_address, + e + ); + } + _ => { + swarm.add_external_address(onion_address); + } + } + } + tracing::info!(peer_id = %swarm.local_peer_id(), "Network layer initialized"); for external_address in config.network.external_addresses { - Swarm::add_external_address(&mut swarm, external_address); + swarm.add_external_address(external_address); } let (event_loop, mut swap_receiver) = EventLoop::new( @@ -391,46 +392,3 @@ async fn init_monero_wallet( Ok(wallet) } - -/// Registers a hidden service for each network. -/// Note: Once ac goes out of scope, the services will be de-registered. -async fn register_tor_services( - networks: Vec, - tor_client: tor::Client, - seed: &Seed, -) -> Result { - let mut ac = tor_client.into_authenticated_client().await?; - - let hidden_services_details = networks - .iter() - .flat_map(|network| { - network.iter().map(|protocol| match protocol { - Protocol::Tcp(port) => Some(( - port, - SocketAddr::new(IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)), port), - )), - _ => { - // We only care for Tcp for now. - None - } - }) - }) - .flatten() - .collect::>(); - - let key = seed.derive_torv3_key(); - - ac.add_services(&hidden_services_details, &key).await?; - - let onion_address = key - .public() - .get_onion_address() - .get_address_without_dot_onion(); - - hidden_services_details.iter().for_each(|(port, _)| { - let onion_address = format!("/onion3/{}:{}", onion_address, port); - tracing::info!(%onion_address, "Successfully created hidden service"); - }); - - Ok(ac) -} diff --git a/swap/src/cli.rs b/swap/src/cli.rs index 7fc460d2..51658e64 100644 --- a/swap/src/cli.rs +++ b/swap/src/cli.rs @@ -4,7 +4,6 @@ pub mod cancel_and_refund; pub mod command; mod event_loop; mod list_sellers; -mod tor; pub mod transport; pub mod watcher; diff --git a/swap/src/cli/api.rs b/swap/src/cli/api.rs index b6476f74..c97daac7 100644 --- a/swap/src/cli/api.rs +++ b/swap/src/cli/api.rs @@ -2,6 +2,7 @@ pub mod request; pub mod tauri_bindings; use crate::cli::command::{Bitcoin, Monero}; +use crate::common::tor::init_tor_client; use crate::common::tracing_util::Format; use crate::database::{open_db, AccessMode}; use crate::env::{Config as EnvConfig, GetConfig, Mainnet, Testnet}; @@ -29,7 +30,6 @@ use tracing::Level; use url::Url; use uuid::Uuid; -use super::tor::init_tor_client; use super::watcher::Watcher; static START: Once = Once::new(); diff --git a/swap/src/common/mod.rs b/swap/src/common/mod.rs index a7858869..cfc958f9 100644 --- a/swap/src/common/mod.rs +++ b/swap/src/common/mod.rs @@ -1,3 +1,4 @@ +pub mod tor; pub mod tracing_util; use anyhow::anyhow; diff --git a/swap/src/cli/tor.rs b/swap/src/common/tor.rs similarity index 96% rename from swap/src/cli/tor.rs rename to swap/src/common/tor.rs index 070669a0..c92090f9 100644 --- a/swap/src/cli/tor.rs +++ b/swap/src/common/tor.rs @@ -21,6 +21,8 @@ pub async fn init_tor_client(data_dir: &Path) -> Result, tauri_handle: Option, ) -> Result<()> { - // file logger will always write in JSON format and with timestamps + let ALL_CRATES: Vec<&str> = vec![ + "swap", + "asb", + "libp2p_community_tor", + "unstoppableswap-gui-rs", + "arti", + ]; + let OUR_CRATES: Vec<&str> = vec!["swap", "asb"]; + + // General log file for non-verbose logs let file_appender: RollingFileAppender = tracing_appender::rolling::never(&dir, "swap-all.log"); + // Verbose log file, rotated hourly, with a maximum of 24 files let tracing_file_appender: RollingFileAppender = RollingFileAppender::builder() .rotation(Rotation::HOURLY) .filename_prefix("tracing") @@ -42,24 +52,31 @@ pub fn init( .build(&dir) .expect("initializing rolling file appender failed"); - // Log to file + // Layer for writing to the general log file + // Crates: swap, asb + // Level: Passed in let file_layer = fmt::layer() .with_writer(file_appender) .with_ansi(false) .with_timer(UtcTime::rfc_3339()) .with_target(false) .json() - .with_filter(env_filter(level_filter)?); + .with_filter(env_filter(level_filter, OUR_CRATES.clone())?); + // Layer for writing to the verbose log file + // Crates: swap, asb, libp2p_community_tor, unstoppableswap-gui-rs, arti (all relevant crates) + // Level: TRACE let tracing_file_layer = fmt::layer() .with_writer(tracing_file_appender) .with_ansi(false) .with_timer(UtcTime::rfc_3339()) .with_target(false) .json() - .with_filter(env_filter(LevelFilter::TRACE)?); + .with_filter(env_filter(LevelFilter::TRACE, ALL_CRATES.clone())?); - // Log to stdout + // Layer for writing to the terminal + // Crates: swap, asb + // Level: Passed in let is_terminal = atty::is(atty::Stream::Stderr); let terminal_layer = fmt::layer() .with_writer(std::io::stdout) @@ -67,17 +84,23 @@ pub fn init( .with_timer(UtcTime::rfc_3339()) .with_target(false); - // Forwards logs to the tauri guest + // Layer for writing to the Tauri guest. This will be displayed in the GUI. + // Crates: swap, asb, libp2p_community_tor, unstoppableswap-gui-rs, arti + // Level: Passed in let tauri_layer = fmt::layer() .with_writer(TauriWriter::new(tauri_handle)) .with_ansi(false) .with_timer(UtcTime::rfc_3339()) .with_target(true) .json() - .with_filter(env_filter(level_filter)?); + .with_filter(env_filter(level_filter, ALL_CRATES.clone())?); - let env_filtered = env_filter(level_filter)?; + // We only log the bare minimum to the terminal + // Crates: swap, asb + // Level: Passed in + let env_filtered = env_filter(level_filter, OUR_CRATES.clone())?; + // Apply the environment filter and box the layer for the terminal let final_terminal_layer = match format { Format::Json => terminal_layer.json().with_filter(env_filtered).boxed(), Format::Raw => terminal_layer.with_filter(env_filtered).boxed(), @@ -97,19 +120,18 @@ pub fn init( } /// This function controls which crate's logs actually get logged and from which level. -fn env_filter(level_filter: LevelFilter) -> Result { - Ok(EnvFilter::from_default_env() - .add_directive(Directive::from_str(&format!("asb={}", &level_filter))?) - .add_directive(Directive::from_str(&format!("swap={}", &level_filter))?) - .add_directive(Directive::from_str(&format!("arti={}", &level_filter))?) - .add_directive(Directive::from_str(&format!( - "libp2p_community_tor={}", - &level_filter - ))?) - .add_directive(Directive::from_str(&format!( - "unstoppableswap-gui-rs={}", - &level_filter - ))?)) +fn env_filter(level_filter: LevelFilter, crates: Vec<&str>) -> Result { + let mut filter = EnvFilter::from_default_env(); + + // Add directives for each crate in the provided list + for crate_name in crates { + filter = filter.add_directive(Directive::from_str(&format!( + "{}={}", + crate_name, &level_filter + ))?); + } + + Ok(filter) } /// A writer that forwards tracing log messages to the tauri guest. diff --git a/swap/src/lib.rs b/swap/src/lib.rs index ddad3eab..6714fb80 100644 --- a/swap/src/lib.rs +++ b/swap/src/lib.rs @@ -31,7 +31,6 @@ pub mod network; pub mod protocol; pub mod rpc; pub mod seed; -pub mod tor; pub mod tracing_ext; #[cfg(test)] diff --git a/swap/src/network/swarm.rs b/swap/src/network/swarm.rs index 9a89c2d5..79d483b4 100644 --- a/swap/src/network/swarm.rs +++ b/swap/src/network/swarm.rs @@ -1,3 +1,4 @@ +use crate::asb::config::TorConf; use crate::asb::{LatestRate, RendezvousNode}; use crate::libp2p_ext::MultiAddrExt; use crate::network::rendezvous::XmrBtcNamespace; @@ -23,7 +24,9 @@ pub fn asb( env_config: env::Config, namespace: XmrBtcNamespace, rendezvous_addrs: &[Multiaddr], -) -> Result>> + maybe_tor_client: Option>>, + tor_conf: TorConf, +) -> Result<(Swarm>, Vec)> where LR: LatestRate + Send + 'static + Debug + Clone, { @@ -50,7 +53,12 @@ where rendezvous_nodes, ); - let transport = asb::transport::new(&identity)?; + let (transport, onion_addresses) = asb::transport::new( + &identity, + maybe_tor_client, + tor_conf.hidden_service_num_intro_points, + tor_conf.register_hidden_service, + )?; let swarm = SwarmBuilder::with_existing_identity(identity) .with_tokio() @@ -59,7 +67,7 @@ where .with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::MAX)) .build(); - Ok(swarm) + Ok((swarm, onion_addresses)) } pub async fn cli( diff --git a/swap/src/seed.rs b/swap/src/seed.rs index 7b20564b..b713da90 100644 --- a/swap/src/seed.rs +++ b/swap/src/seed.rs @@ -12,7 +12,6 @@ use std::fmt; use std::fs::{self, File}; use std::io::{self, Write}; use std::path::{Path, PathBuf}; -use torut::onion::TorSecretKeyV3; pub const SEED_LENGTH: usize = 32; @@ -47,14 +46,6 @@ impl Seed { identity::Keypair::ed25519_from_bytes(bytes).expect("we always pass 32 bytes") } - pub fn derive_torv3_key(&self) -> TorSecretKeyV3 { - let bytes = self.derive(b"TOR").bytes(); - let sk = ed25519_dalek::SecretKey::from_bytes(&bytes) - .expect("Failed to create a new extended secret key for Tor."); - let esk = ed25519_dalek::ExpandedSecretKey::from(&sk); - esk.to_bytes().into() - } - pub fn from_file_or_generate(data_dir: &Path) -> Result { let file_path_buf = data_dir.join("seed.pem"); let file_path = Path::new(&file_path_buf); diff --git a/swap/src/tor.rs b/swap/src/tor.rs deleted file mode 100644 index bbbcb16b..00000000 --- a/swap/src/tor.rs +++ /dev/null @@ -1,128 +0,0 @@ -use anyhow::{bail, Context, Result}; -use std::future::Future; -use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; -use tokio::net::TcpStream; -use torut::control::{AsyncEvent, AuthenticatedConn, ConnError, UnauthenticatedConn}; -use torut::onion::TorSecretKeyV3; - -pub const DEFAULT_SOCKS5_PORT: u16 = 9050; -pub const DEFAULT_CONTROL_PORT: u16 = 9051; - -#[derive(Debug, Clone, Copy)] -pub struct Client { - socks5_address: SocketAddrV4, - control_port_address: SocketAddr, -} - -impl Default for Client { - fn default() -> Self { - Self { - socks5_address: SocketAddrV4::new(Ipv4Addr::LOCALHOST, DEFAULT_SOCKS5_PORT), - control_port_address: SocketAddr::V4(SocketAddrV4::new( - Ipv4Addr::LOCALHOST, - DEFAULT_CONTROL_PORT, - )), - } - } -} - -impl Client { - pub fn new(socks5_port: u16) -> Self { - Self { - socks5_address: SocketAddrV4::new(Ipv4Addr::LOCALHOST, socks5_port), - control_port_address: SocketAddr::V4(SocketAddrV4::new( - Ipv4Addr::LOCALHOST, - DEFAULT_CONTROL_PORT, - )), - } - } - pub fn with_control_port(self, control_port: u16) -> Self { - Self { - control_port_address: SocketAddr::V4(SocketAddrV4::new( - Ipv4Addr::LOCALHOST, - control_port, - )), - ..self - } - } - - /// checks if tor is running - pub async fn assert_tor_running(&self) -> Result<()> { - // Make sure you are running tor and this is your socks port - let proxy = reqwest::Proxy::all(format!("socks5h://{}", self.socks5_address).as_str()) - .context("Failed to construct Tor proxy URL")?; - let client = reqwest::Client::builder().proxy(proxy).build()?; - - let res = client.get("https://check.torproject.org").send().await?; - let text = res.text().await?; - - if !text.contains("Congratulations. This browser is configured to use Tor.") { - bail!("Tor is currently not running") - } - - Ok(()) - } - - async fn init_unauthenticated_connection(&self) -> Result> { - // Connect to local tor service via control port - let sock = TcpStream::connect(self.control_port_address).await?; - let uc = UnauthenticatedConn::new(sock); - Ok(uc) - } - - /// Create a new authenticated connection to your local Tor service - pub async fn into_authenticated_client(self) -> Result { - self.assert_tor_running().await?; - - let mut uc = self - .init_unauthenticated_connection() - .await - .context("Failed to connect to Tor")?; - - let tor_info = uc - .load_protocol_info() - .await - .context("Failed to load protocol info from Tor")?; - - let tor_auth_data = tor_info - .make_auth_data()? - .context("Failed to make Tor auth data")?; - - // Get an authenticated connection to the Tor via the Tor Controller protocol. - uc.authenticate(&tor_auth_data) - .await - .context("Failed to authenticate with Tor")?; - - Ok(AuthenticatedClient { - inner: uc.into_authenticated().await, - }) - } - - pub fn tor_proxy_port(&self) -> u16 { - self.socks5_address.port() - } -} - -type Handler = fn(AsyncEvent<'_>) -> Box> + Unpin>; - -#[allow(missing_debug_implementations)] -pub struct AuthenticatedClient { - inner: AuthenticatedConn, -} - -impl AuthenticatedClient { - /// Add an ephemeral tor service on localhost with the provided key - /// `service_port` and `onion_port` can be different but don't have to as - /// they are on different networks. - pub async fn add_services( - &mut self, - services: &[(u16, SocketAddr)], - tor_key: &TorSecretKeyV3, - ) -> Result<()> { - let mut listeners = services.iter(); - self.inner - .add_onion_v3(tor_key, false, false, false, None, &mut listeners) - .await - .context("Failed to add onion service") - } -} diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 9abd0413..71f4005e 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -243,7 +243,7 @@ async fn start_alice( let latest_rate = FixedRate::default(); let resume_only = false; - let mut swarm = swarm::asb( + let (mut swarm, _) = swarm::asb( seed, min_buy, max_buy, @@ -252,6 +252,7 @@ async fn start_alice( env_config, XmrBtcNamespace::Testnet, &[], + None, ) .unwrap(); swarm.listen_on(listen_address).unwrap();