mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Merge #438
438: Add support for swapping through Tor. r=bonomat a=bonomat Resolves: #447 This PR does a few things. * It adds a TorTransport which either dials through Tor's socks5 proxy or via clearnet. * It enables ASB to register hidden services for each network it is listening on. We assume that we only care about different ports and re-use the same onion-address for all of them. The ASB requires to have access to Tor's control port. * It adds support to dial through a local Tor socks5 proxy. We assume that Tor is always available on localhost. Swap cli only requires Tor to be running so that it can send messages via Tor's socks5 proxy. * It adds a new e2e test which swaps through Tor. For this we assume that Tor is currently running on localhost. All other tests are running via clear net. Note: It is expected that the new test will fail on CI because we do not have Tor running. That's why it wasn't added yet. I'll play around in my own fork to not use precious CI resources :) The rest is ready for review. // edit: Swapping through Tor on one machine seems to be working: Asb: ``` cargo run --bin asb -- --config "/Users/bonomat/Library/Application Support/xmr-btc-swap/asb/config.toml" start Finished dev [unoptimized + debuginfo] target(s) in 0.30s Running `target/debug/asb --config '/Users/bonomat/Library/Application Support/xmr-btc-swap/asb/config.toml' start` Apr 22 11:14:05.090 INFO Initialized tracing with level: debug Apr 22 11:14:05.092 INFO Using config file at default path: /Users/bonomat/Library/Application Support/xmr-btc-swap/asb/config.toml Apr 22 11:14:05.094 INFO Database and Seed will be stored in directory: /Users/bonomat/Library/Application Support/xmr-btc-swap/asb Apr 22 11:14:05.094 DEBUG Opening database at /Users/bonomat/Library/Application Support/xmr-btc-swap/asb/database Apr 22 11:14:05.226 DEBUG Reading in seed from /Users/bonomat/Library/Application Support/xmr-btc-swap/asb/seed.pem Apr 22 11:14:06.903 INFO Tor found. Setting up hidden service. Apr 22 11:14:08.805 INFO /onion3/jugnrrdp7imu5tqphvlrctudguq3sapmjideu6d63i5y7qqtzzwvf4id:9939 Apr 22 11:14:08.805 INFO /onion3/jugnrrdp7imu5tqphvlrctudguq3sapmjideu6d63i5y7qqtzzwvf4id:9940 Apr 22 11:14:13.431 DEBUG Opened Monero wallet asb-wallet Apr 22 11:14:13.433 INFO Bitcoin balance: 0.00000000 BTC Apr 22 11:14:13.433 WARN The Monero balance is 0, make sure to deposit funds at: 5A3iBfDbhGfUUL5WKFcdY5JK7oLcMXYmD9VnUjxmBgFHXswtENMjFsHUDeeCWVvRYaNRCAJDRS7jY85iyNt7s3syVNJtwLd Apr 22 11:14:13.436 DEBUG Trying to listen on: /ip4/0.0.0.0/tcp/9939 Apr 22 11:14:13.437 DEBUG Trying to listen on: /ip4/0.0.0.0/tcp/9940 Apr 22 11:14:13.437 INFO Our peer id is 12D3KooWNqWpoLUp6YSoUYTinwJFh92wzggeanLgSutmZbZYG9cN Apr 22 11:14:13.438 INFO Listening on /ip4/127.0.0.1/tcp/9940/ws Apr 22 11:14:13.438 INFO Listening on /ip4/127.0.0.1/tcp/9939 Apr 22 11:14:13.438 INFO Listening on /ip4/192.168.1.63/tcp/9940/ws Apr 22 11:14:13.438 INFO Listening on /ip4/192.168.1.63/tcp/9939 Apr 22 11:14:14.275 DEBUG Connected to Kraken websocket API Apr 22 11:14:14.462 DEBUG Subscribed to updates for ticker Apr 22 11:23:11.833 DEBUG New connection established peer=12D3KooWHBMKm8Wnq4WD7ehVdSHaf4ccjdzR97UTFtMGT6LBmRev address=/ip4/127.0.0.1/tcp/63655 Apr 22 11:23:25.700 INFO swap{id=c4f51a28-b2fb-4885-9f7a-5d1852de5f0d}: Current state: started Apr 22 11:23:25.700 INFO swap{id=c4f51a28-b2fb-4885-9f7a-5d1852de5f0d}: Waiting for 1 confirmation of Bitcoin transaction txid=537070d7a6f75e74caa65cebbbf0997b50914fd86b7a752f0d74eb0c5701291f Apr 22 11:23:33.732 DEBUG Transaction is in mempool txid=537070d7a6f75e74caa65cebbbf0997b50914fd86b7a752f0d74eb0c5701291f Apr 22 11:42:49.668 DEBUG Transaction is confirmed with 1 blocks txid=537070d7a6f75e74caa65cebbbf0997b50914fd86b7a752f0d74eb0c5701291f Apr 22 11:42:49.671 INFO swap{id=c4f51a28-b2fb-4885-9f7a-5d1852de5f0d}: Bitcoin tx has 1 out of 1 confirmation txid=537070d7a6f75e74caa65cebbbf0997b50914fd86b7a752f0d74eb0c5701291f Apr 22 11:42:49.703 INFO swap{id=c4f51a28-b2fb-4885-9f7a-5d1852de5f0d}: Current state: btc is locked Apr 22 11:43:02.670 DEBUG swap{id=c4f51a28-b2fb-4885-9f7a-5d1852de5f0d}: sent transfer of 0.695214974374 XMR to 05d77c136ad84eff1184a14971f8ec7f5884bb25b646a6c1eb95e0c26782f0a5 in c00f4543d9c9831fa892a2180b4dabbc33eff1fcd6f58ac24495dcf1450bbab3 Apr 22 11:43:02.740 INFO swap{id=c4f51a28-b2fb-4885-9f7a-5d1852de5f0d}: Current state: xmr lock transaction sent ... ``` Swap: ``` cargo run --bin swap buy-xmr --seller-peer-id 12D3KooWNqWpoLUp6YSoUYTinwJFh92wzggeanLgSutmZbZYG9cN --seller-addr /onion3/jugnrrdp7imu5tqphvlrctudguq3sapmjideu6d63i5y7qqtzzwvf4id:9939 --receive-address 5A3iBfDbhGfUUL5WKFcdY5JK7oLcMXYmD9VnUjxmBgFHXswtENMjFsHUDeeCWVvRYaNRCAJDRS7jY85iyNt7s3syVNJtwLd Finished dev [unoptimized + debuginfo] target(s) in 0.37s Running `target/debug/swap buy-xmr --seller-peer-id 12D3KooWNqWpoLUp6YSoUYTinwJFh92wzggeanLgSutmZbZYG9cN --seller-addr '/onion3/jugnrrdp7imu5tqphvlrctudguq3sapmjideu6d63i5y7qqtzzwvf4id:9939' --receive-address 5A3iBfDbhGfUUL5WKFcdY5JK7oLcMXYmD9VnUjxmBgFHXswtENMjFsHUDeeCWVvRYaNRCAJDRS7jY85iyNt7s3syVNJtwLd` Connecting to Tor proxy ... Connection established Connected to Alice at /onion3/jugnrrdp7imu5tqphvlrctudguq3sapmjideu6d63i5y7qqtzzwvf4id:9939/p2p/12D3KooWNqWpoLUp6YSoUYTinwJFh92wzggeanLgSutmZbZYG9cN Received quote: 1 XMR ~ 0.00719202 BTC Found 0.01559763 BTC in wallet Swapping 0.00500000 BTC with 0.00000610 BTC fees Spot price for 0.00500000 BTC is 0.695214974374 XMR Published Bitcoin lock transaction txid=537070d7a6f75e74caa65cebbbf0997b50914fd86b7a752f0d74eb0c5701291f Waiting for Alice to lock Monero Alice locked Monero txid=c00f4543d9c9831fa892a2180b4dabbc33eff1fcd6f58ac24495dcf1450bbab3 Waiting for 10 confirmations of Monero transaction txid=c00f4543d9c9831fa892a2180b4dabbc33eff1fcd6f58ac24495dcf1450bbab3 Monero lock tx has 1 out of 10 confirmations txid=c00f4543d9c9831fa892a2180b4dabbc33eff1fcd6f58ac24495dcf1450bbab3 Monero lock tx has 2 out of 10 confirmations txid=c00f4543d9c9831fa892a2180b4dabbc33eff1fcd6f58ac24495dcf1450bbab3 Monero lock tx has 3 out of 10 confirmations txid=c00f4543d9c9831fa892a2180b4dabbc33eff1fcd6f58ac24495dcf1450bbab3 ... ``` Co-authored-by: Philipp Hoenisch <philipp@hoenisch.at> Co-authored-by: Philipp Hoenisch <philipp@coblox.tech>
This commit is contained in:
commit
c0501627c9
@ -29,6 +29,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Websocket support for the ASB.
|
||||
The ASB is now capable to listen on both TCP and Websocket connections.
|
||||
Default websocket listening port is 9940.
|
||||
- Tor support as an optional feature.
|
||||
If ASB detects that Tor's control port is open, a hidden service is created for
|
||||
the network it is listening on (currently 2).
|
||||
The Tor control port as well as Tor socks5 proxy port is configurable.
|
||||
|
||||
## [0.4.0] - 2021-04-06
|
||||
|
||||
|
305
Cargo.lock
generated
305
Cargo.lock
generated
@ -68,6 +68,15 @@ version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
@ -139,9 +148,9 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -150,9 +159,9 @@ version = "0.1.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -220,6 +229,12 @@ version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b"
|
||||
|
||||
[[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.2.1"
|
||||
@ -290,9 +305,9 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b45570b78250774145859a8f85bfdb6e310663fc82640d7e159a44b1386074a2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -829,9 +844,23 @@ version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"regex",
|
||||
"rustc_version",
|
||||
"syn 0.15.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -997,9 +1026,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1139,9 +1168,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1656,8 +1685,8 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5f3d1e50fefe4252d2e44c805663e73a8c0b2002b73f834ea055c8ed7fc46a8"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1666,10 +1695,16 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97c11e429f0eaa41fe659013680b459d2368d8f0a3e69dccfb7a35800b0dc27b"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keccak"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7"
|
||||
|
||||
[[package]]
|
||||
name = "keccak-hash"
|
||||
version = "0.7.0"
|
||||
@ -1876,8 +1911,8 @@ version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "365b0a699fea5168676840567582a012ea297b1ca02eee467e58301b9c9c5eed"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2096,9 +2131,9 @@ version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19ce18b5423c573a13e80cb3046ea0af6379ef725dc3af4886bdb8f4e5093068"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2209,9 +2244,9 @@ checksum = "85ee3c48cb9d9b275ad967a0e96715badc13c6029adb92f34fa17b9ff28fd81f"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@ -2491,9 +2526,9 @@ version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2502,9 +2537,9 @@ version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2604,9 +2639,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
"version_check 0.9.3",
|
||||
]
|
||||
|
||||
@ -2616,8 +2651,8 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"version_check 0.9.3",
|
||||
]
|
||||
|
||||
@ -2633,13 +2668,22 @@ version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2678,9 +2722,9 @@ checksum = "169a15f3008ecb5160cba7d37bcd690a7601b6d30cfb87a117d45e59d52af5d4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.9.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2710,13 +2754,22 @@ dependencies = [
|
||||
"pin-project-lite 0.1.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2 1.0.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2970,6 +3023,8 @@ version = "1.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
@ -3026,6 +3081,7 @@ dependencies = [
|
||||
"serde_urlencoded",
|
||||
"tokio 1.5.0",
|
||||
"tokio-rustls",
|
||||
"tokio-socks",
|
||||
"url 2.2.1",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
@ -3272,9 +3328,9 @@ version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3317,9 +3373,9 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d08338d8024b227c62bd68a12c7c9883f5c66780abaef15c550dc56f46ee6515"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3366,6 +3422,19 @@ dependencies = [
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha3"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf"
|
||||
dependencies = [
|
||||
"block-buffer 0.7.3",
|
||||
"byte-tools",
|
||||
"digest 0.8.1",
|
||||
"keccak",
|
||||
"opaque-debug 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.1"
|
||||
@ -3548,11 +3617,11 @@ version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3562,13 +3631,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
|
||||
dependencies = [
|
||||
"base-x",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sha1",
|
||||
"syn",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3612,9 +3681,9 @@ checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3633,9 +3702,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3669,9 +3738,11 @@ dependencies = [
|
||||
"config",
|
||||
"conquer-once",
|
||||
"curve25519-dalek",
|
||||
"data-encoding",
|
||||
"dialoguer",
|
||||
"directories-next",
|
||||
"ecdsa_fun",
|
||||
"ed25519-dalek",
|
||||
"futures",
|
||||
"get-port",
|
||||
"hyper 0.14.7",
|
||||
@ -3703,10 +3774,12 @@ dependencies = [
|
||||
"thiserror",
|
||||
"time 0.2.26",
|
||||
"tokio 1.5.0",
|
||||
"tokio-socks",
|
||||
"tokio-tar",
|
||||
"tokio-tungstenite",
|
||||
"tokio-util",
|
||||
"toml",
|
||||
"torut",
|
||||
"tracing",
|
||||
"tracing-appender",
|
||||
"tracing-futures",
|
||||
@ -3717,15 +3790,26 @@ dependencies = [
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3734,10 +3818,10 @@ version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"unicode-xid",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3830,9 +3914,9 @@ version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3886,10 +3970,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"standback",
|
||||
"syn",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3954,9 +4038,9 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3970,6 +4054,18 @@ dependencies = [
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-socks"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0"
|
||||
dependencies = [
|
||||
"either",
|
||||
"futures-util",
|
||||
"thiserror",
|
||||
"tokio 1.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-stream"
|
||||
version = "0.1.4"
|
||||
@ -4035,6 +4131,23 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "torut"
|
||||
version = "0.1.8"
|
||||
source = "git+https://github.com/bonomat/torut/?branch=feature-flag-tor-secret-keys#d4f9858e3b4452c2056ff7ee4e50836cdcb62572"
|
||||
dependencies = [
|
||||
"base32",
|
||||
"base64 0.10.1",
|
||||
"derive_more",
|
||||
"ed25519-dalek",
|
||||
"hex 0.4.3",
|
||||
"hmac 0.7.1",
|
||||
"rand 0.7.3",
|
||||
"sha2 0.8.2",
|
||||
"sha3",
|
||||
"tokio 1.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.1"
|
||||
@ -4070,9 +4183,9 @@ version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4268,6 +4381,12 @@ version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.1"
|
||||
@ -4421,9 +4540,9 @@ dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log 0.4.14",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -4445,7 +4564,7 @@ version = "0.2.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"quote 1.0.9",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
@ -4455,9 +4574,9 @@ version = "0.2.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -4648,9 +4767,9 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
|
@ -1,2 +1,5 @@
|
||||
[workspace]
|
||||
members = ["monero-harness", "monero-rpc", "swap"]
|
||||
|
||||
[patch.crates-io]
|
||||
torut = { git = "https://github.com/bonomat/torut/", branch = "feature-flag-tor-secret-keys", default-features = false, features = ["v3", "control"] }
|
||||
|
@ -22,9 +22,11 @@ bmrng = "0.5"
|
||||
config = { version = "0.11", default-features = false, features = ["toml"] }
|
||||
conquer-once = "0.3"
|
||||
curve25519-dalek = "3"
|
||||
data-encoding = "2.3"
|
||||
dialoguer = "0.8"
|
||||
directories-next = "2"
|
||||
ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", features = ["libsecp_compat", "serde"] }
|
||||
ed25519-dalek = "1"
|
||||
futures = { version = "0.3", default-features = false }
|
||||
itertools = "0.10"
|
||||
libp2p = { version = "0.37", default-features = false, features = ["tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response", "websocket"] }
|
||||
@ -36,7 +38,7 @@ pem = "0.8"
|
||||
prettytable-rs = "0.8"
|
||||
rand = "0.7"
|
||||
rand_chacha = "0.2"
|
||||
reqwest = { version = "0.11", features = ["rustls-tls", "stream"], default-features = false }
|
||||
reqwest = { version = "0.11", features = ["rustls-tls", "stream", "socks"], default-features = false }
|
||||
rust_decimal = "1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_cbor = "0.11"
|
||||
@ -48,10 +50,12 @@ structopt = "0.3"
|
||||
strum = { version = "0.20", features = ["derive"] }
|
||||
thiserror = "1"
|
||||
time = "0.2"
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "time", "macros", "sync", "process", "fs"] }
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "time", "macros", "sync", "process", "fs", "net"] }
|
||||
tokio-socks = "0.5"
|
||||
tokio-tungstenite = { version = "0.14", features = [ "rustls-tls" ] }
|
||||
tokio-util = { version = "0.6", features = ["io"] }
|
||||
toml = "0.5"
|
||||
torut = { version = "0.1", default-features = false, features = ["v3", "control"] }
|
||||
tracing = { version = "0.1", features = ["attributes"] }
|
||||
tracing-appender = "0.1"
|
||||
tracing-futures = { version = "0.2", features = ["std-future", "futures-03"] }
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::fs::{default_data_dir, ensure_directory_exists};
|
||||
use crate::tor::{DEFAULT_CONTROL_PORT, DEFAULT_SOCKS5_PORT};
|
||||
use anyhow::{Context, Result};
|
||||
use config::ConfigError;
|
||||
use dialoguer::theme::ColorfulTheme;
|
||||
@ -22,6 +23,7 @@ pub struct Config {
|
||||
pub network: Network,
|
||||
pub bitcoin: Bitcoin,
|
||||
pub monero: Monero,
|
||||
pub tor: TorConf,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@ -61,6 +63,22 @@ pub struct Monero {
|
||||
pub wallet_rpc_url: Url,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct TorConf {
|
||||
pub control_port: u16,
|
||||
pub socks5_port: u16,
|
||||
}
|
||||
|
||||
impl Default for TorConf {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
control_port: DEFAULT_CONTROL_PORT,
|
||||
socks5_port: DEFAULT_SOCKS5_PORT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug, Clone, Copy)]
|
||||
#[error("config not initialized")]
|
||||
pub struct ConfigNotInitialized {}
|
||||
@ -133,6 +151,17 @@ pub fn query_user_for_initial_testnet_config() -> Result<Config> {
|
||||
.default(DEFAULT_MONERO_WALLET_RPC_TESTNET_URL.to_owned())
|
||||
.interact_text()?;
|
||||
let monero_wallet_rpc_url = monero_wallet_rpc_url.as_str().parse()?;
|
||||
|
||||
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()?;
|
||||
|
||||
println!();
|
||||
|
||||
Ok(Config {
|
||||
@ -144,6 +173,10 @@ pub fn query_user_for_initial_testnet_config() -> Result<Config> {
|
||||
monero: Monero {
|
||||
wallet_rpc_url: monero_wallet_rpc_url,
|
||||
},
|
||||
tor: TorConf {
|
||||
control_port: tor_control_port,
|
||||
socks5_port: tor_socks5_port,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@ -175,6 +208,7 @@ mod tests {
|
||||
monero: Monero {
|
||||
wallet_rpc_url: Url::from_str(DEFAULT_MONERO_WALLET_RPC_TESTNET_URL).unwrap(),
|
||||
},
|
||||
tor: Default::default(),
|
||||
};
|
||||
|
||||
initial_setup(config_path.clone(), || Ok(expected.clone())).unwrap();
|
||||
|
@ -13,8 +13,11 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use libp2p::core::multiaddr::Protocol;
|
||||
use libp2p::core::Multiaddr;
|
||||
use libp2p::Swarm;
|
||||
use prettytable::{row, Table};
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::sync::Arc;
|
||||
use structopt::StructOpt;
|
||||
use swap::asb::command::{Arguments, Command};
|
||||
@ -29,7 +32,8 @@ use swap::network::swarm;
|
||||
use swap::protocol::alice::event_loop::KrakenRate;
|
||||
use swap::protocol::alice::{run, EventLoop};
|
||||
use swap::seed::Seed;
|
||||
use swap::{asb, bitcoin, env, kraken, monero};
|
||||
use swap::tor::AuthenticatedClient;
|
||||
use swap::{asb, bitcoin, env, kraken, monero, tor};
|
||||
use tracing::{info, warn};
|
||||
use tracing_subscriber::filter::LevelFilter;
|
||||
|
||||
@ -97,6 +101,23 @@ async fn main() -> Result<()> {
|
||||
|
||||
let kraken_price_updates = kraken::connect()?;
|
||||
|
||||
// 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!("Tor found. Setting up 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 mut swarm = swarm::alice(&seed)?;
|
||||
|
||||
for listen in config.network.listen {
|
||||
@ -212,3 +233,45 @@ 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<Multiaddr>,
|
||||
tor_client: tor::Client,
|
||||
seed: &Seed,
|
||||
) -> Result<AuthenticatedClient> {
|
||||
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
|
||||
}
|
||||
})
|
||||
})
|
||||
.filter_map(|details| details)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
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, _)| {
|
||||
tracing::info!("/onion3/{}:{}", onion_address, port);
|
||||
});
|
||||
|
||||
Ok(ac)
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ async fn main() -> Result<()> {
|
||||
monero_daemon_host,
|
||||
},
|
||||
electrum_rpc_url,
|
||||
tor_socks5_port,
|
||||
} => {
|
||||
let swap_id = Uuid::new_v4();
|
||||
|
||||
@ -76,7 +77,7 @@ async fn main() -> Result<()> {
|
||||
init_monero_wallet(data_dir, monero_daemon_host, env_config).await?;
|
||||
let bitcoin_wallet = Arc::new(bitcoin_wallet);
|
||||
|
||||
let mut swarm = swarm::bob(&seed, alice_peer_id)?;
|
||||
let mut swarm = swarm::bob(&seed, alice_peer_id, tor_socks5_port).await?;
|
||||
swarm
|
||||
.behaviour_mut()
|
||||
.add_address(alice_peer_id, alice_multiaddr);
|
||||
@ -152,6 +153,7 @@ async fn main() -> Result<()> {
|
||||
monero_daemon_host,
|
||||
},
|
||||
electrum_rpc_url,
|
||||
tor_socks5_port,
|
||||
} => {
|
||||
let data_dir = data.0;
|
||||
cli::tracing::init(debug, data_dir.join("logs"), swap_id)?;
|
||||
@ -172,7 +174,8 @@ async fn main() -> Result<()> {
|
||||
let bitcoin_wallet = Arc::new(bitcoin_wallet);
|
||||
|
||||
let alice_peer_id = db.get_peer_id(swap_id)?;
|
||||
let mut swarm = swarm::bob(&seed, alice_peer_id)?;
|
||||
|
||||
let mut swarm = swarm::bob(&seed, alice_peer_id, tor_socks5_port).await?;
|
||||
let bob_peer_id = swarm.local_peer_id();
|
||||
tracing::debug!("Our peer-id: {}", bob_peer_id);
|
||||
swarm
|
||||
|
@ -13,6 +13,8 @@ pub const DEFAULT_STAGENET_MONERO_DAEMON_HOST: &str = "monero-stagenet.exan.tech
|
||||
pub const DEFAULT_ELECTRUM_HTTP_URL: &str = "https://blockstream.info/testnet/api/";
|
||||
const DEFAULT_ELECTRUM_RPC_URL: &str = "ssl://electrum.blockstream.info:60002";
|
||||
|
||||
const DEFAULT_TOR_SOCKS5_PORT: &str = "9050";
|
||||
|
||||
#[derive(structopt::StructOpt, Debug)]
|
||||
#[structopt(name = "swap", about = "CLI for swapping BTC for XMR", author)]
|
||||
pub struct Arguments {
|
||||
@ -48,6 +50,9 @@ pub enum Command {
|
||||
|
||||
#[structopt(flatten)]
|
||||
monero_params: MoneroParams,
|
||||
|
||||
#[structopt(long = "tor-socks5-port", help = "Your local Tor socks5 proxy port", default_value = DEFAULT_TOR_SOCKS5_PORT)]
|
||||
tor_socks5_port: u16,
|
||||
},
|
||||
/// Show a list of past ongoing and completed swaps
|
||||
History,
|
||||
@ -70,6 +75,9 @@ pub enum Command {
|
||||
|
||||
#[structopt(flatten)]
|
||||
monero_params: MoneroParams,
|
||||
|
||||
#[structopt(long = "tor-socks5-port", help = "Your local Tor socks5 proxy port", default_value = DEFAULT_TOR_SOCKS5_PORT)]
|
||||
tor_socks5_port: u16,
|
||||
},
|
||||
/// Try to cancel an ongoing swap (expert users only)
|
||||
Cancel {
|
||||
|
@ -27,5 +27,6 @@ pub mod monero;
|
||||
pub mod network;
|
||||
pub mod protocol;
|
||||
pub mod seed;
|
||||
pub mod tor;
|
||||
|
||||
mod monero_ext;
|
||||
|
@ -7,5 +7,6 @@ pub mod quote;
|
||||
pub mod redial;
|
||||
pub mod spot_price;
|
||||
pub mod swarm;
|
||||
pub mod tor_transport;
|
||||
pub mod transfer_proof;
|
||||
pub mod transport;
|
||||
|
@ -1,24 +1,53 @@
|
||||
use crate::network::transport;
|
||||
use crate::protocol::{alice, bob};
|
||||
use crate::seed::Seed;
|
||||
use crate::tor;
|
||||
use anyhow::Result;
|
||||
use libp2p::swarm::{NetworkBehaviour, SwarmBuilder};
|
||||
use libp2p::{PeerId, Swarm};
|
||||
|
||||
pub fn alice(seed: &Seed) -> Result<Swarm<alice::Behaviour>> {
|
||||
new(seed, alice::Behaviour::default())
|
||||
with_clear_net(seed, alice::Behaviour::default())
|
||||
}
|
||||
|
||||
pub fn bob(seed: &Seed, alice: PeerId) -> Result<Swarm<bob::Behaviour>> {
|
||||
new(seed, bob::Behaviour::new(alice))
|
||||
pub async fn bob(
|
||||
seed: &Seed,
|
||||
alice: PeerId,
|
||||
tor_socks5_port: u16,
|
||||
) -> Result<Swarm<bob::Behaviour>> {
|
||||
let client = tor::Client::new(tor_socks5_port);
|
||||
if client.assert_tor_running().await.is_ok() {
|
||||
return with_tor(seed, bob::Behaviour::new(alice), tor_socks5_port).await;
|
||||
}
|
||||
with_clear_net(seed, bob::Behaviour::new(alice))
|
||||
}
|
||||
|
||||
fn new<B>(seed: &Seed, behaviour: B) -> Result<Swarm<B>>
|
||||
fn with_clear_net<B>(seed: &Seed, behaviour: B) -> Result<Swarm<B>>
|
||||
where
|
||||
B: NetworkBehaviour,
|
||||
{
|
||||
tracing::info!("All connections will go through clear net.");
|
||||
let identity = seed.derive_libp2p_identity();
|
||||
let transport = transport::build(&identity)?;
|
||||
let transport = transport::build_clear_net(&identity)?;
|
||||
let peer_id = identity.public().into_peer_id();
|
||||
tracing::debug!("Our peer-id: {}", peer_id);
|
||||
|
||||
let swarm = SwarmBuilder::new(transport, behaviour, peer_id)
|
||||
.executor(Box::new(|f| {
|
||||
tokio::spawn(f);
|
||||
}))
|
||||
.build();
|
||||
|
||||
Ok(swarm)
|
||||
}
|
||||
|
||||
async fn with_tor<B>(seed: &Seed, behaviour: B, tor_socks5_port: u16) -> Result<Swarm<B>>
|
||||
where
|
||||
B: NetworkBehaviour,
|
||||
{
|
||||
tracing::info!("All connections will go through Tor socks5 proxy.");
|
||||
let identity = seed.derive_libp2p_identity();
|
||||
let transport = transport::build_tor(&identity, tor_socks5_port)?;
|
||||
let peer_id = identity.public().into_peer_id();
|
||||
tracing::debug!("Our peer-id: {}", peer_id);
|
||||
|
||||
|
199
swap/src/network/tor_transport.rs
Normal file
199
swap/src/network/tor_transport.rs
Normal file
@ -0,0 +1,199 @@
|
||||
use anyhow::anyhow;
|
||||
use data_encoding::BASE32;
|
||||
use futures::future::Ready;
|
||||
use futures::prelude::*;
|
||||
use libp2p::core::multiaddr::{Multiaddr, Protocol};
|
||||
use libp2p::core::transport::TransportError;
|
||||
use libp2p::core::Transport;
|
||||
use libp2p::tcp::tokio::{Tcp, TcpStream};
|
||||
use libp2p::tcp::{GenTcpConfig, TcpListenStream, TokioTcpConfig};
|
||||
use std::io;
|
||||
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||
use std::pin::Pin;
|
||||
use tokio_socks::tcp::Socks5Stream;
|
||||
use tokio_socks::IntoTargetAddr;
|
||||
|
||||
/// Represents the configuration for a Tor transport for libp2p.
|
||||
#[derive(Clone)]
|
||||
pub struct TorTcpConfig {
|
||||
inner: GenTcpConfig<Tcp>,
|
||||
/// Tor SOCKS5 proxy port number.
|
||||
socks_port: u16,
|
||||
}
|
||||
|
||||
impl TorTcpConfig {
|
||||
pub fn new(tcp: TokioTcpConfig, socks_port: u16) -> Self {
|
||||
Self {
|
||||
inner: tcp,
|
||||
socks_port,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Transport for TorTcpConfig {
|
||||
type Output = TcpStream;
|
||||
type Error = io::Error;
|
||||
type Listener = TcpListenStream<Tcp>;
|
||||
type ListenerUpgrade = Ready<Result<Self::Output, Self::Error>>;
|
||||
#[allow(clippy::type_complexity)]
|
||||
type Dial = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send>>;
|
||||
|
||||
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||
self.inner.listen_on(addr)
|
||||
}
|
||||
|
||||
// dials via Tor's socks5 proxy if configured and if the provided address is an
|
||||
// onion address. or it falls back to Tcp dialling
|
||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
async fn do_tor_dial(socks_port: u16, dest: String) -> Result<TcpStream, io::Error> {
|
||||
tracing::trace!("Connecting through Tor proxy to address: {}", dest);
|
||||
let stream = connect_to_socks_proxy(dest, socks_port)
|
||||
.await
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::ConnectionRefused, e))?;
|
||||
tracing::trace!("Connection through Tor established");
|
||||
Ok(stream)
|
||||
}
|
||||
|
||||
match to_address_string(addr.clone()) {
|
||||
Ok(tor_address_string) => {
|
||||
Ok(Box::pin(do_tor_dial(self.socks_port, tor_address_string)))
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::warn!(
|
||||
"Address {} could not be formatted. Dialling via clear net. Details: {}",
|
||||
addr,
|
||||
e
|
||||
);
|
||||
self.inner.dial(addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn address_translation(&self, listen: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
self.inner.address_translation(listen, observed)
|
||||
}
|
||||
}
|
||||
|
||||
/// Tor expects an address format of ADDR:PORT.
|
||||
/// This helper function tries to convert the provided multi-address into this
|
||||
/// format. None is returned if an unsupported protocol was provided.
|
||||
fn to_address_string(multi: Multiaddr) -> anyhow::Result<String> {
|
||||
let mut protocols = multi.iter();
|
||||
let address_string = match protocols.next() {
|
||||
// if it is an Onion address, we have all we need and can return
|
||||
Some(Protocol::Onion3(addr)) => {
|
||||
return Ok(format!(
|
||||
"{}.onion:{}",
|
||||
BASE32.encode(addr.hash()).to_lowercase(),
|
||||
addr.port()
|
||||
))
|
||||
}
|
||||
// Deal with non-onion addresses
|
||||
Some(Protocol::Ip4(addr)) => Some(format!("{}", addr)),
|
||||
Some(Protocol::Ip6(addr)) => Some(format!("{}", addr)),
|
||||
Some(Protocol::Dns(addr)) => Some(format!("{}", addr)),
|
||||
Some(Protocol::Dns4(addr)) => Some(format!("{}", addr)),
|
||||
_ => None,
|
||||
}
|
||||
.ok_or_else(|| {
|
||||
anyhow!(
|
||||
"Could not format address {}. Please consider reporting this issue. ",
|
||||
multi
|
||||
)
|
||||
})?;
|
||||
|
||||
let port_string = match protocols.next() {
|
||||
Some(Protocol::Tcp(port)) => Some(format!("{}", port)),
|
||||
Some(Protocol::Udp(port)) => Some(format!("{}", port)),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(port) = port_string {
|
||||
Ok(format!("{}:{}", address_string, port))
|
||||
} else {
|
||||
Ok(address_string)
|
||||
}
|
||||
}
|
||||
|
||||
/// Connect to the SOCKS5 proxy socket.
|
||||
async fn connect_to_socks_proxy<'a>(
|
||||
dest: impl IntoTargetAddr<'a>,
|
||||
port: u16,
|
||||
) -> Result<TcpStream, tokio_socks::Error> {
|
||||
let sock = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, port));
|
||||
let stream = Socks5Stream::connect(sock, dest).await?;
|
||||
Ok(TcpStream(stream.into_inner()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use crate::network::tor_transport::to_address_string;
|
||||
|
||||
#[test]
|
||||
fn test_tor_address_string() {
|
||||
let address =
|
||||
"/onion3/oarchy4tamydxcitaki6bc2v4leza6v35iezmu2chg2bap63sv6f2did:1024/p2p/12D3KooWPD4uHN74SHotLN7VCH7Fm8zZgaNVymYcpeF1fpD2guc9"
|
||||
;
|
||||
let address_string =
|
||||
to_address_string(address.parse().unwrap()).expect("To be a multi formatted address.");
|
||||
assert_eq!(
|
||||
address_string,
|
||||
"oarchy4tamydxcitaki6bc2v4leza6v35iezmu2chg2bap63sv6f2did.onion:1024"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tcp_to_address_string_should_be_some() {
|
||||
let address = "/ip4/127.0.0.1/tcp/7777";
|
||||
let address_string =
|
||||
to_address_string(address.parse().unwrap()).expect("To be a formatted multi address. ");
|
||||
assert_eq!(address_string, "127.0.0.1:7777");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ip6_to_address_string_should_be_some() {
|
||||
let address = "/ip6/2001:db8:85a3:8d3:1319:8a2e:370:7348/tcp/7777";
|
||||
let address_string =
|
||||
to_address_string(address.parse().unwrap()).expect("To be a formatted multi address. ");
|
||||
assert_eq!(address_string, "2001:db8:85a3:8d3:1319:8a2e:370:7348:7777");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn udp_to_address_string_should_be_some() {
|
||||
let address = "/ip4/127.0.0.1/udp/7777";
|
||||
let address_string =
|
||||
to_address_string(address.parse().unwrap()).expect("To be a formatted multi address. ");
|
||||
assert_eq!(address_string, "127.0.0.1:7777");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ws_to_address_string_should_be_some() {
|
||||
let address = "/ip4/127.0.0.1/tcp/7777/ws";
|
||||
let address_string =
|
||||
to_address_string(address.parse().unwrap()).expect("To be a formatted multi address. ");
|
||||
assert_eq!(address_string, "127.0.0.1:7777");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dns4_to_address_string_should_be_some() {
|
||||
let address = "/dns4/randomdomain.com/tcp/7777";
|
||||
let address_string =
|
||||
to_address_string(address.parse().unwrap()).expect("To be a formatted multi address. ");
|
||||
assert_eq!(address_string, "randomdomain.com:7777");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dns_to_address_string_should_be_some() {
|
||||
let address = "/dns/randomdomain.com/tcp/7777";
|
||||
let address_string =
|
||||
to_address_string(address.parse().unwrap()).expect("To be a formatted multi address. ");
|
||||
assert_eq!(address_string, "randomdomain.com:7777");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dnsaddr_to_address_string_should_be_none() {
|
||||
let address = "/dnsaddr/randomdomain.com";
|
||||
let address_string = to_address_string(address.parse().unwrap()).ok();
|
||||
assert_eq!(address_string, None);
|
||||
}
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
use crate::network::tor_transport::TorTcpConfig;
|
||||
use anyhow::Result;
|
||||
use libp2p::core::muxing::StreamMuxerBox;
|
||||
use libp2p::core::transport::Boxed;
|
||||
use libp2p::core::upgrade::{SelectUpgrade, Version};
|
||||
use libp2p::core::{identity, Transport};
|
||||
use libp2p::dns::TokioDnsConfig;
|
||||
use libp2p::mplex::MplexConfig;
|
||||
use libp2p::noise::{self, NoiseConfig, X25519Spec};
|
||||
use libp2p::tcp::TokioTcpConfig;
|
||||
use libp2p::websocket::WsConfig;
|
||||
use libp2p::{yamux, PeerId};
|
||||
use libp2p::{identity, yamux, PeerId, Transport};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Builds a libp2p transport with the following features:
|
||||
@ -16,9 +17,7 @@ use std::time::Duration;
|
||||
/// - DNS name resolution
|
||||
/// - authentication via noise
|
||||
/// - multiplexing via yamux or mplex
|
||||
pub fn build(id_keys: &identity::Keypair) -> Result<SwapTransport> {
|
||||
use libp2p::tcp::TokioTcpConfig;
|
||||
|
||||
pub fn build_clear_net(id_keys: &identity::Keypair) -> Result<SwapTransport> {
|
||||
let dh_keys = noise::Keypair::<X25519Spec>::new().into_authentic(id_keys)?;
|
||||
let noise = NoiseConfig::xx(dh_keys).into_authenticated();
|
||||
|
||||
@ -41,4 +40,34 @@ pub fn build(id_keys: &identity::Keypair) -> Result<SwapTransport> {
|
||||
Ok(transport)
|
||||
}
|
||||
|
||||
/// Builds a libp2p transport with the following features:
|
||||
/// - TorTcpConnection
|
||||
/// - WebSocketConnection
|
||||
/// - DNS name resolution
|
||||
/// - authentication via noise
|
||||
/// - multiplexing via yamux or mplex
|
||||
pub fn build_tor(id_keys: &identity::Keypair, tor_socks5_port: u16) -> Result<SwapTransport> {
|
||||
let dh_keys = noise::Keypair::<X25519Spec>::new().into_authentic(id_keys)?;
|
||||
let noise = NoiseConfig::xx(dh_keys).into_authenticated();
|
||||
|
||||
let tcp = TokioTcpConfig::new().nodelay(true);
|
||||
let tcp = TorTcpConfig::new(tcp, tor_socks5_port);
|
||||
let dns = TokioDnsConfig::system(tcp)?;
|
||||
let websocket = WsConfig::new(dns.clone());
|
||||
|
||||
let transport = websocket
|
||||
.or_transport(dns)
|
||||
.upgrade(Version::V1)
|
||||
.authenticate(noise)
|
||||
.multiplex(SelectUpgrade::new(
|
||||
yamux::YamuxConfig::default(),
|
||||
MplexConfig::new(),
|
||||
))
|
||||
.timeout(Duration::from_secs(20))
|
||||
.map(|(peer, muxer), _| (peer, StreamMuxerBox::new(muxer)))
|
||||
.boxed();
|
||||
|
||||
Ok(transport)
|
||||
}
|
||||
|
||||
pub type SwapTransport = Boxed<(PeerId, StreamMuxerBox)>;
|
||||
|
@ -12,6 +12,7 @@ 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,6 +48,14 @@ impl Seed {
|
||||
identity::Keypair::Ed25519(key.into())
|
||||
}
|
||||
|
||||
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<Self, Error> {
|
||||
let file_path_buf = data_dir.join("seed.pem");
|
||||
let file_path = Path::new(&file_path_buf);
|
||||
|
154
swap/src/tor.rs
Normal file
154
swap/src/tor.rs
Normal file
@ -0,0 +1,154 @@
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use std::future::Future;
|
||||
use std::net::{IpAddr, 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())
|
||||
.map_err(|_| anyhow!("tor proxy should be there"))?;
|
||||
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<UnauthenticatedConn<TcpStream>> {
|
||||
// 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<AuthenticatedClient> {
|
||||
self.assert_tor_running().await?;
|
||||
|
||||
let mut uc = self
|
||||
.init_unauthenticated_connection()
|
||||
.await
|
||||
.map_err(|_| anyhow!("Could not connect to Tor. Tor might not be running or the control port is incorrect."))?;
|
||||
|
||||
let tor_info = uc
|
||||
.load_protocol_info()
|
||||
.await
|
||||
.map_err(|_| anyhow!("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
|
||||
.map_err(|_| anyhow!("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<dyn Future<Output = Result<(), ConnError>> + Unpin>;
|
||||
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct AuthenticatedClient {
|
||||
inner: AuthenticatedConn<TcpStream, Handler>,
|
||||
}
|
||||
|
||||
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_service(
|
||||
&mut self,
|
||||
service_port: u16,
|
||||
onion_port: u16,
|
||||
tor_key: &TorSecretKeyV3,
|
||||
) -> Result<()> {
|
||||
self.inner
|
||||
.add_onion_v3(
|
||||
tor_key,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
&mut [(
|
||||
onion_port,
|
||||
SocketAddr::new(IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)), service_port),
|
||||
)]
|
||||
.iter(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| anyhow!("Could not add onion service.: {:#?}", e))
|
||||
}
|
||||
|
||||
/// 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
|
||||
.map_err(|e| anyhow!("Could not add onion service.: {:#?}", e))
|
||||
}
|
||||
}
|
@ -383,8 +383,8 @@ struct BobParams {
|
||||
}
|
||||
|
||||
impl BobParams {
|
||||
pub fn new_swap_from_db(&self, swap_id: Uuid) -> Result<(bob::Swap, bob::EventLoop)> {
|
||||
let (event_loop, handle) = self.new_eventloop(swap_id)?;
|
||||
pub async fn new_swap_from_db(&self, swap_id: Uuid) -> Result<(bob::Swap, bob::EventLoop)> {
|
||||
let (event_loop, handle) = self.new_eventloop(swap_id).await?;
|
||||
let db = Database::open(&self.db_path)?;
|
||||
|
||||
let swap = bob::Swap::from_db(
|
||||
@ -400,10 +400,13 @@ impl BobParams {
|
||||
Ok((swap, event_loop))
|
||||
}
|
||||
|
||||
pub fn new_swap(&self, btc_amount: bitcoin::Amount) -> Result<(bob::Swap, bob::EventLoop)> {
|
||||
pub async fn new_swap(
|
||||
&self,
|
||||
btc_amount: bitcoin::Amount,
|
||||
) -> Result<(bob::Swap, bob::EventLoop)> {
|
||||
let swap_id = Uuid::new_v4();
|
||||
|
||||
let (event_loop, handle) = self.new_eventloop(swap_id)?;
|
||||
let (event_loop, handle) = self.new_eventloop(swap_id).await?;
|
||||
let db = Database::open(&self.db_path)?;
|
||||
|
||||
let swap = bob::Swap::new(
|
||||
@ -420,8 +423,13 @@ impl BobParams {
|
||||
Ok((swap, event_loop))
|
||||
}
|
||||
|
||||
pub fn new_eventloop(&self, swap_id: Uuid) -> Result<(bob::EventLoop, bob::EventLoopHandle)> {
|
||||
let mut swarm = swarm::bob(&self.seed, self.alice_peer_id)?;
|
||||
pub async fn new_eventloop(
|
||||
&self,
|
||||
swap_id: Uuid,
|
||||
) -> Result<(bob::EventLoop, bob::EventLoopHandle)> {
|
||||
let tor_socks5_port = get_port()
|
||||
.expect("We don't care about Tor in the tests so we get a free port to disable it.");
|
||||
let mut swarm = swarm::bob(&self.seed, self.alice_peer_id, tor_socks5_port).await?;
|
||||
swarm
|
||||
.behaviour_mut()
|
||||
.add_address(self.alice_peer_id, self.alice_address.clone());
|
||||
@ -501,7 +509,7 @@ impl TestContext {
|
||||
}
|
||||
|
||||
pub async fn bob_swap(&mut self) -> (bob::Swap, BobApplicationHandle) {
|
||||
let (swap, event_loop) = self.bob_params.new_swap(self.btc_amount).unwrap();
|
||||
let (swap, event_loop) = self.bob_params.new_swap(self.btc_amount).await.unwrap();
|
||||
|
||||
// ensure the wallet is up to date for concurrent swap tests
|
||||
swap.bitcoin_wallet.sync().await.unwrap();
|
||||
@ -518,7 +526,7 @@ impl TestContext {
|
||||
) -> (bob::Swap, BobApplicationHandle) {
|
||||
join_handle.abort();
|
||||
|
||||
let (swap, event_loop) = self.bob_params.new_swap_from_db(swap_id).unwrap();
|
||||
let (swap, event_loop) = self.bob_params.new_swap_from_db(swap_id).await.unwrap();
|
||||
|
||||
let join_handle = tokio::spawn(event_loop.run());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user