diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 8e842a00..3db89051 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -45,16 +45,16 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.2 - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.63 + toolchain: 1.67 targets: armv7-unknown-linux-gnueabihf - name: Build ${{ matrix.target }} ${{ matrix.bin }} release binary diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 055e61b5..af335076 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,14 +13,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 - uses: dtolnay/rust-toolchain@master with: toolchain: 1.67 components: clippy,rustfmt - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.2 - name: Check formatting uses: dprint/check@v2.2 @@ -37,9 +37,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.2 - name: Build swap run: cargo build --bin swap @@ -51,12 +51,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.2 - name: Install sqlx-cli - run: cargo install sqlx-cli + run: cargo install sqlx-cli --locked - name: Run sqlite_dev_setup.sh script run: | @@ -78,9 +78,9 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.2 - uses: dtolnay/rust-toolchain@master with: @@ -118,9 +118,9 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.2 - name: Build tests run: cargo build --tests --workspace --all-features @@ -155,9 +155,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.2 - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index f3bee225..c95f8d22 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v4.0.0 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index b25b6fdc..2e89fd6c 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v4.0.0 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index 37e04333..6e557033 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v4.0.0 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0768910b..160c34a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.12.3] - 2023-09-20 + +- Swap: If no Monero daemon is manually specified, we will automatically choose one from a list of public daemons by connecting to each and checking their availability. + ## [0.12.2] - 2023-08-08 ### Changed @@ -345,7 +349,8 @@ It is possible to migrate critical data from the old db to the sqlite but there - Fixed an issue where Alice would not verify if Bob's Bitcoin lock transaction is semantically correct, i.e. pays the agreed upon amount to an output owned by both of them. Fixing this required a **breaking change** on the network layer and hence old versions are not compatible with this version. -[Unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.2...HEAD +[Unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.3...HEAD +[0.12.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.2...0.12.3 [0.12.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.1...0.12.2 [0.12.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.0...0.12.1 [0.12.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.11.0...0.12.0 diff --git a/Cargo.lock b/Cargo.lock index 2421c1bf..78d6b5c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "adler32" version = "1.2.0" @@ -105,6 +120,16 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d6e24d2cce90c53b948c46271bfb053e4bdc2db9b5d3f65e20f8cf28a1b7fc3" +[[package]] +name = "assert-json-diff" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "async-compression" version = "0.3.15" @@ -114,7 +139,7 @@ dependencies = [ "bzip2", "futures-core", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tokio", ] @@ -148,7 +173,7 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", ] [[package]] @@ -195,11 +220,26 @@ dependencies = [ "futures-core", "getrandom 0.2.6", "instant", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "rand 0.8.3", "tokio", ] +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide 0.7.1", + "object", + "rustc-demangle", +] + [[package]] name = "base32" version = "0.4.0" @@ -377,6 +417,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + [[package]] name = "blake2" version = "0.9.2" @@ -644,7 +690,7 @@ checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ "ansi_term 0.11.0", "atty", - "bitflags", + "bitflags 1.3.2", "strsim 0.8.0", "textwrap", "unicode-width", @@ -657,6 +703,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colored" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +dependencies = [ + "is-terminal", + "lazy_static", + "windows-sys 0.48.0", +] + [[package]] name = "comfy-table" version = "6.1.4" @@ -832,7 +889,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crossterm_winapi", "libc", "mio", @@ -1253,7 +1310,7 @@ dependencies = [ "crc32fast", "libc", "libz-sys", - "miniz_oxide", + "miniz_oxide 0.3.7", ] [[package]] @@ -1412,7 +1469,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "pin-utils", "slab", ] @@ -1487,13 +1544,19 @@ dependencies = [ "polyval", ] +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + [[package]] name = "git2" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", "libgit2-sys", "log", @@ -1705,7 +1768,7 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "socket2 0.4.7", "tokio", "tower-service", @@ -1825,6 +1888,17 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.1", + "rustix 0.38.11", + "windows-sys 0.48.0", +] + [[package]] name = "itertools" version = "0.10.5" @@ -2015,9 +2089,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.141" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libgit2-sys" @@ -2355,6 +2429,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" +[[package]] +name = "linux-raw-sys" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" + [[package]] name = "lock_api" version = "0.4.6" @@ -2465,15 +2545,44 @@ dependencies = [ ] [[package]] -name = "mio" -version = "0.8.4" +name = "miniz_oxide" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.36.1", + "windows-sys 0.48.0", +] + +[[package]] +name = "mockito" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c762b6267c4593555bb38f1df19e9318985bc4de60b5e8462890856a9a5b4c" +dependencies = [ + "assert-json-diff", + "colored", + "futures", + "hyper", + "lazy_static", + "log", + "rand 0.8.3", + "regex", + "serde_json", + "serde_urlencoded", + "similar", + "tokio", ] [[package]] @@ -2734,6 +2843,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.13.0" @@ -2926,9 +3044,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -3045,7 +3163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" dependencies = [ "bit-set", - "bitflags", + "bitflags 1.3.2", "byteorder", "lazy_static", "num-traits", @@ -3300,7 +3418,7 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -3309,7 +3427,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -3324,9 +3442,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.5" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ "aho-corasick", "memchr", @@ -3345,9 +3463,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "rend" @@ -3380,7 +3498,7 @@ dependencies = [ "mime", "once_cell", "percent-encoding", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "rustls 0.21.1", "rustls-pemfile", "serde", @@ -3478,6 +3596,12 @@ dependencies = [ "rust_decimal", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -3511,11 +3635,24 @@ version = "0.37.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys", + "linux-raw-sys 0.3.1", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys 0.4.5", "windows-sys 0.48.0", ] @@ -3715,7 +3852,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -3988,6 +4125,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f0242b8e50dd9accdd56170e94ca1ebd223b098eb9c83539a6e367d0f36ae68" +[[package]] +name = "similar" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" + [[package]] name = "slab" version = "0.4.2" @@ -4055,6 +4198,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "soketto" version = "0.7.1" @@ -4125,7 +4278,7 @@ checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" dependencies = [ "ahash", "atoi", - "bitflags", + "bitflags 1.3.2", "byteorder", "bytes", "crc", @@ -4291,7 +4444,7 @@ checksum = "8049cf85f0e715d6af38dde439cb0ccb91f67fb9f5f63c80f8b43e48356e1a3f" [[package]] name = "swap" -version = "0.12.2" +version = "0.12.3" dependencies = [ "anyhow", "async-compression", @@ -4320,8 +4473,8 @@ dependencies = [ "itertools", "jsonrpsee", "jsonrpsee-core", - "jsonrpsee-types", "libp2p", + "mockito", "monero", "monero-harness", "monero-rpc", @@ -4412,7 +4565,7 @@ dependencies = [ "cfg-if 1.0.0", "fastrand", "redox_syscall 0.3.5", - "rustix", + "rustix 0.37.11", "windows-sys 0.48.0", ] @@ -4560,33 +4713,32 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.19.2" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ + "backtrace", "bytes", "libc", - "memchr", "mio", "num_cpus", - "once_cell", "parking_lot 0.12.0", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "signal-hook-registry", - "socket2 0.4.7", + "socket2 0.5.3", "tokio-macros", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "1.7.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] @@ -4640,7 +4792,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tokio", ] @@ -4686,7 +4838,7 @@ dependencies = [ "futures-core", "futures-io", "futures-sink", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tokio", "tracing", ] @@ -4748,7 +4900,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9cf6a813d3f40c88b0b6b6f29a5c95c6cdbf97c1f9cc53fb820200f5ad814d" dependencies = [ "log", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tracing-attributes", "tracing-core", ] @@ -5322,19 +5474,6 @@ dependencies = [ "windows_x86_64_msvc 0.32.0", ] -[[package]] -name = "windows-sys" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -5371,12 +5510,6 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" @@ -5389,12 +5522,6 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - [[package]] name = "windows_i686_gnu" version = "0.48.0" @@ -5407,12 +5534,6 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - [[package]] name = "windows_i686_msvc" version = "0.48.0" @@ -5425,12 +5546,6 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" @@ -5449,12 +5564,6 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 12886cdd..62505953 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swap" -version = "0.12.2" +version = "0.12.3" authors = [ "The COMIT guys " ] edition = "2021" description = "XMR/BTC trustless atomic swaps." @@ -80,7 +80,7 @@ bitcoin-harness = "0.2.2" get-port = "3" hyper = "0.14" jsonrpsee = { version = "0.16.2", features = [ "ws-client" ] } -jsonrpsee-types = { version = "0.16.2" } +mockito = "1.1.0" monero-harness = { path = "../monero-harness" } port_check = "0.1" proptest = "1" diff --git a/swap/src/api.rs b/swap/src/api.rs index 36bc9faa..365d8354 100644 --- a/swap/src/api.rs +++ b/swap/src/api.rs @@ -268,7 +268,7 @@ async fn init_monero_wallet( let monero_wallet_rpc = monero::WalletRpc::new(data_dir.join("monero")).await?; let monero_wallet_rpc_process = monero_wallet_rpc - .run(network, monero_daemon_address.as_str()) + .run(network, Some(monero_daemon_address)) .await?; let monero_wallet = monero::Wallet::open_or_create( diff --git a/swap/src/api/request.rs b/swap/src/api/request.rs index 53a6090f..aa727b26 100644 --- a/swap/src/api/request.rs +++ b/swap/src/api/request.rs @@ -177,11 +177,11 @@ impl Request { Method::SuspendCurrentSwap => { let swap_id = context.swap_lock.get_current_swap_id().await; - if swap_id.is_some() { + if let Some(id_value) = swap_id { context.swap_lock.send_suspend_signal().await?; Ok(json!({ - "swapId": swap_id.unwrap() + "swapId": id_value })) } else { bail!("No swap is currently running") @@ -624,7 +624,7 @@ impl Request { } Method::StartDaemon { server_address } => { // Default to 127.0.0.1:1234 - let server_address = server_address.unwrap_or("127.0.0.1:1234".parse().unwrap()); + let server_address = server_address.unwrap_or("127.0.0.1:1234".parse()?); let (addr, server_handle) = rpc::run_server(server_address, Arc::clone(&context)).await?; diff --git a/swap/src/bitcoin/wallet.rs b/swap/src/bitcoin/wallet.rs index 5617d381..468d607d 100644 --- a/swap/src/bitcoin/wallet.rs +++ b/swap/src/bitcoin/wallet.rs @@ -785,6 +785,10 @@ impl Client { if !self.script_history.contains_key(&script) { self.script_history.insert(script.clone(), vec![]); + + // When we first subscribe to a script we want to immediately fetch its status + // Otherwise we would have to wait for the next sync interval, which can take a minute + // This would result in potentially inaccurate status updates until that next sync interval is hit self.update_state(true)?; } else { self.update_state(false)?; diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index 3f548c41..56fd8e60 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -174,11 +174,6 @@ impl Wallet { pub async fn transfer(&self, request: TransferRequest) -> Result { let inner = self.inner.lock().await; - inner - .open_wallet(self.name.clone()) - .await - .with_context(|| format!("Failed to open wallet {}", self.name))?; - let TransferRequest { public_spend_key, public_view_key, diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index 819eeccb..e44d800e 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -1,19 +1,45 @@ use ::monero::Network; -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Error, Result}; use big_bytes::BigByte; use futures::{StreamExt, TryStreamExt}; use monero_rpc::wallet::{Client, MoneroWalletRpc as _}; use reqwest::header::CONTENT_LENGTH; use reqwest::Url; +use serde::Deserialize; +use std::fmt; +use std::fmt::{Debug, Display, Formatter}; use std::io::ErrorKind; use std::path::{Path, PathBuf}; use std::process::Stdio; +use std::time::Duration; use tokio::fs::{remove_file, OpenOptions}; use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; use tokio::process::{Child, Command}; use tokio_util::codec::{BytesCodec, FramedRead}; use tokio_util::io::StreamReader; +// See: https://www.moneroworld.com/#nodes, https://monero.fail +// We don't need any testnet nodes because we don't support testnet at all +const MONERO_DAEMONS: [MoneroDaemon; 17] = [ + MoneroDaemon::new("xmr-node.cakewallet.com", 18081, Network::Mainnet), + MoneroDaemon::new("nodex.monerujo.io", 18081, Network::Mainnet), + MoneroDaemon::new("node.moneroworld.com", 18089, Network::Mainnet), + MoneroDaemon::new("nodes.hashvault.pro", 18081, Network::Mainnet), + MoneroDaemon::new("p2pmd.xmrvsbeast.com", 18081, Network::Mainnet), + MoneroDaemon::new("node.monerodevs.org", 18089, Network::Mainnet), + MoneroDaemon::new("xmr-node-usa-east.cakewallet.com", 18081, Network::Mainnet), + MoneroDaemon::new("xmr-node-uk.cakewallet.com", 18081, Network::Mainnet), + MoneroDaemon::new("node.community.rino.io", 18081, Network::Mainnet), + MoneroDaemon::new("testingjohnross.com", 20031, Network::Mainnet), + MoneroDaemon::new("xmr.litepay.ch", 18081, Network::Mainnet), + MoneroDaemon::new("node.trocador.app", 18089, Network::Mainnet), + MoneroDaemon::new("stagenet.xmr-tw.org", 38081, Network::Stagenet), + MoneroDaemon::new("node.monerodevs.org", 38089, Network::Stagenet), + MoneroDaemon::new("singapore.node.xmr.pm", 38081, Network::Stagenet), + MoneroDaemon::new("xmr-lux.boldsuck.org", 38081, Network::Stagenet), + MoneroDaemon::new("stagenet.community.rino.io", 38081, Network::Stagenet), +]; + #[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))] compile_error!("unsupported operating system"); @@ -50,6 +76,91 @@ pub struct WalletRpcProcess { port: u16, } +struct MoneroDaemon { + address: &'static str, + port: u16, + network: Network, +} + +impl MoneroDaemon { + const fn new(address: &'static str, port: u16, network: Network) -> Self { + Self { + address, + port, + network, + } + } + + /// Checks if the Monero daemon is available by sending a request to its `get_info` endpoint. + async fn is_available(&self, client: &reqwest::Client) -> Result { + let url = format!("http://{}:{}/get_info", self.address, self.port); + let res = client + .get(url) + .send() + .await + .context("Failed to send request to get_info endpoint")?; + + let json: MoneroDaemonGetInfoResponse = res + .json() + .await + .context("Failed to deserialize daemon get_info response")?; + + let is_status_ok = json.status == "OK"; + let is_synchronized = json.synchronized; + let is_correct_network = match self.network { + Network::Mainnet => json.mainnet, + Network::Stagenet => json.stagenet, + Network::Testnet => json.testnet, + }; + + Ok(is_status_ok && is_synchronized && is_correct_network) + } +} + +impl Display for MoneroDaemon { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}:{}", self.address, self.port) + } +} + +#[derive(Deserialize)] +struct MoneroDaemonGetInfoResponse { + status: String, + synchronized: bool, + mainnet: bool, + stagenet: bool, + testnet: bool, +} + +/// Chooses an available Monero daemon based on the specified network. +async fn choose_monero_daemon(network: Network) -> Result<&'static MoneroDaemon, Error> { + let client = reqwest::Client::builder() + .timeout(Duration::from_secs(30)) + .https_only(false) + .build()?; + + // We only want to check for daemons that match the specified network + let network_matching_daemons = MONERO_DAEMONS + .iter() + .filter(|daemon| daemon.network == network); + + for daemon in network_matching_daemons { + match daemon.is_available(&client).await { + Ok(true) => { + tracing::debug!(%daemon, "Found available Monero daemon"); + return Ok(daemon); + } + Err(err) => { + tracing::debug!(%err, %daemon, "Failed to connect to Monero daemon"); + continue; + } + Ok(false) => continue, + } + } + + bail!("No Monero daemon could be found. Please specify one manually or try again later.") +} + impl WalletRpcProcess { pub fn endpoint(&self) -> Url { Url::parse(&format!("http://127.0.0.1:{}/json_rpc", self.port)) @@ -153,13 +264,23 @@ impl WalletRpc { Ok(monero_wallet_rpc) } - pub async fn run(&self, network: Network, daemon_address: &str) -> Result { + pub async fn run( + &self, + network: Network, + daemon_address: Option, + ) -> Result { let port = tokio::net::TcpListener::bind("127.0.0.1:0") .await? .local_addr()? .port(); + let daemon_address = match daemon_address { + Some(daemon_address) => daemon_address, + None => choose_monero_daemon(network).await?.to_string(), + }; + tracing::debug!( + %daemon_address, %port, "Starting monero-wallet-rpc" ); @@ -232,7 +353,6 @@ impl WalletRpc { #[cfg(not(target_os = "windows"))] async fn extract_archive(monero_wallet_rpc: &Self) -> Result<()> { - use anyhow::bail; use tokio_tar::Archive; let mut options = OpenOptions::new(); @@ -297,3 +417,123 @@ impl WalletRpc { Ok(()) } } + +#[cfg(test)] +mod tests { + use super::*; + + fn extract_host_and_port(address: String) -> (&'static str, u16) { + let parts: Vec<&str> = address.split(':').collect(); + + if parts.len() == 2 { + let host = parts[0].to_string(); + let port = parts[1].parse::().unwrap(); + let static_str_host: &'static str = Box::leak(host.into_boxed_str()); + return (static_str_host, port); + } + panic!("Could not extract host and port from address: {}", address) + } + + #[tokio::test] + async fn test_is_daemon_available_success() { + let mut server = mockito::Server::new(); + + let _ = server + .mock("GET", "/get_info") + .with_status(200) + .with_body( + r#" + { + "status": "OK", + "synchronized": true, + "mainnet": true, + "stagenet": false, + "testnet": false + } + "#, + ) + .create(); + + let (host, port) = extract_host_and_port(server.host_with_port()); + + let client = reqwest::Client::new(); + let result = MoneroDaemon::new(host, port, Network::Mainnet) + .is_available(&client) + .await; + + assert!(result.is_ok()); + assert!(result.unwrap()); + } + + #[tokio::test] + async fn test_is_daemon_available_wrong_network_failure() { + let mut server = mockito::Server::new(); + + let _ = server + .mock("GET", "/get_info") + .with_status(200) + .with_body( + r#" + { + "status": "OK", + "synchronized": true, + "mainnet": true, + "stagenet": false, + "testnet": false + } + "#, + ) + .create(); + + let (host, port) = extract_host_and_port(server.host_with_port()); + + let client = reqwest::Client::new(); + let result = MoneroDaemon::new(host, port, Network::Stagenet) + .is_available(&client) + .await; + + assert!(result.is_ok()); + assert!(!result.unwrap()); + } + + #[tokio::test] + async fn test_is_daemon_available_not_synced_failure() { + let mut server = mockito::Server::new(); + + let _ = server + .mock("GET", "/get_info") + .with_status(200) + .with_body( + r#" + { + "status": "OK", + "synchronized": false, + "mainnet": true, + "stagenet": false, + "testnet": false + } + "#, + ) + .create(); + + let (host, port) = extract_host_and_port(server.host_with_port()); + + let client = reqwest::Client::new(); + let result = MoneroDaemon::new(host, port, Network::Mainnet) + .is_available(&client) + .await; + + assert!(result.is_ok()); + assert!(!result.unwrap()); + } + + #[tokio::test] + async fn test_is_daemon_available_network_error_failure() { + let client = reqwest::Client::new(); + let result = MoneroDaemon::new("does.not.exist.com", 18081, Network::Mainnet) + .is_available(&client) + .await; + + assert!(result.is_err()); + } +}