Merge branch 'comit-network:master' into rpc-server

This commit is contained in:
Lorenzo Tucci 2023-01-08 09:07:38 +01:00 committed by GitHub
commit d416095146
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 386 additions and 166 deletions

View File

@ -45,19 +45,16 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout tagged commit - name: Checkout tagged commit
uses: actions/checkout@v3.1.0 uses: actions/checkout@v3.3.0
with: with:
ref: ${{ github.event.release.target_commitish }} ref: ${{ github.event.release.target_commitish }}
token: ${{ secrets.BOTTY_GITHUB_TOKEN }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }}
- uses: Swatinem/rust-cache@v2.2.0 - uses: Swatinem/rust-cache@v2.2.0
- uses: actions-rs/toolchain@v1 - uses: dtolnay/rust-toolchain@stable
with: with:
toolchain: stable targets: armv7-unknown-linux-gnueabihf
profile: minimal
target: armv7-unknown-linux-gnueabihf
override: true
- name: Build ${{ matrix.target }} ${{ matrix.bin }} release binary - name: Build ${{ matrix.target }} ${{ matrix.bin }} release binary
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1

View File

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3.1.0 uses: actions/checkout@v3.3.0
- uses: Swatinem/rust-cache@v2.2.0 - uses: Swatinem/rust-cache@v2.2.0
@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3.1.0 uses: actions/checkout@v3.3.0
- uses: Swatinem/rust-cache@v2.0.2 - uses: Swatinem/rust-cache@v2.0.2
@ -44,7 +44,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3.1.0 uses: actions/checkout@v3.3.0
- uses: Swatinem/rust-cache@v2.0.2 - uses: Swatinem/rust-cache@v2.0.2
@ -71,31 +71,25 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3.1.0 uses: actions/checkout@v3.3.0
- uses: Swatinem/rust-cache@v2.2.0 - uses: Swatinem/rust-cache@v2.2.0
- uses: actions-rs/toolchain@v1 - uses: dtolnay/rust-toolchain@stable
with: with:
toolchain: stable targets: armv7-unknown-linux-gnueabihf
profile: minimal
target: armv7-unknown-linux-gnueabihf
override: true
- name: Build binary - name: Build binary
if: matrix.target != 'armv7-unknown-linux-gnueabihf' if: matrix.target != 'armv7-unknown-linux-gnueabihf'
uses: actions-rs/cargo@v1 run: cargo build -p swap --target ${{ matrix.target }}
with:
command: build - name: Install cross (armv7)
args: -p swap --target ${{ matrix.target }} if: matrix.target == 'armv7-unknown-linux-gnueabihf'
run: cargo install cross --locked
- name: Build binary (armv7) - name: Build binary (armv7)
if: matrix.target == 'armv7-unknown-linux-gnueabihf' if: matrix.target == 'armv7-unknown-linux-gnueabihf'
uses: actions-rs/cargo@v1 run: cross build -p swap --target ${{ matrix.target }}
with:
command: build
args: -p swap --target ${{ matrix.target }}
use-cross: true
- name: Upload swap binary - name: Upload swap binary
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
@ -116,7 +110,7 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3.1.0 uses: actions/checkout@v3.3.0
- uses: Swatinem/rust-cache@v2.2.0 - uses: Swatinem/rust-cache@v2.2.0
@ -152,7 +146,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3.1.0 uses: actions/checkout@v3.3.0
- uses: Swatinem/rust-cache@v2.2.0 - uses: Swatinem/rust-cache@v2.2.0

View File

@ -11,7 +11,7 @@ jobs:
if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/')
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3.1.0 - uses: actions/checkout@v3.3.0
- name: Extract version from branch name - name: Extract version from branch name
id: extract-version id: extract-version

View File

@ -12,7 +12,7 @@ jobs:
name: "Draft a new release" name: "Draft a new release"
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3.1.0 - uses: actions/checkout@v3.3.0
with: with:
token: ${{ secrets.BOTTY_GITHUB_TOKEN }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }}
@ -54,7 +54,7 @@ jobs:
run: git push origin release/${{ github.event.inputs.version }} --force run: git push origin release/${{ github.event.inputs.version }} --force
- name: Create pull request - name: Create pull request
uses: thomaseizinger/create-pull-request@1.2.2 uses: thomaseizinger/create-pull-request@1.3.0
with: with:
GITHUB_TOKEN: ${{ secrets.BOTTY_GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.BOTTY_GITHUB_TOKEN }}
head: release/${{ github.event.inputs.version }} head: release/${{ github.event.inputs.version }}

View File

@ -10,7 +10,7 @@ jobs:
name: Create preview release name: Create preview release
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3.1.0 - uses: actions/checkout@v3.3.0
- name: Delete 'preview' release - name: Delete 'preview' release
uses: larryjoelane/delete-release-action@v1.0.24 uses: larryjoelane/delete-release-action@v1.0.24

View File

@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [0.12.0] - 2022-12-31
### Changed
- Update `bdk` library to latest version. This introduces an incompatability with previous versions due to different formats being used to exchange Bitcoin transactions
- Changed ASB to quote on Monero unlocked balance instead of total balance
- Allow `asb` to set a bitcoin address that is controlled by the asb itself to redeem/punish bitcoin to
### Added
- Allow asb config overrides using environment variables. See [1231](https://github.com/comit-network/xmr-btc-swap/pull/1231)
## [0.11.0] - 2022-08-11 ## [0.11.0] - 2022-08-11
### Changed ### Changed
@ -320,7 +332,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. - 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. 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.11.0...HEAD [Unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.0...HEAD
[0.12.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.11.0...0.12.0
[0.11.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.10.2...0.11.0 [0.11.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.10.2...0.11.0
[0.10.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.10.1...0.10.2 [0.10.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.10.1...0.10.2
[0.10.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.10.0...0.10.1 [0.10.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.10.0...0.10.1

166
Cargo.lock generated
View File

@ -83,9 +83,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.66" version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
[[package]] [[package]]
name = "arrayref" name = "arrayref"
@ -93,12 +93,6 @@ version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
name = "arrayvec"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]] [[package]]
name = "arrayvec" name = "arrayvec"
version = "0.7.2" version = "0.7.2"
@ -136,9 +130,9 @@ dependencies = [
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.59" version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364" checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -235,10 +229,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]] [[package]]
name = "bdk" name = "base64"
version = "0.24.0" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c50e3f08fbcd7eb34f11e066a1353986d583f1f87af70f7cd50bff9fce97c817" checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5"
[[package]]
name = "bdk"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1e7eb54c6288eca1b698e6e33dd82ebe6c08a93ec1a96bb6926ddceed22c703"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"bdk-macros", "bdk-macros",
@ -659,9 +659,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]] [[package]]
name = "comfy-table" name = "comfy-table"
version = "6.1.3" version = "6.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e621e7e86c46fd8a14c32c6ae3cb95656621b4743a27d0cffedb831d46e7ad21" checksum = "6e7b787b0dc42e8111badfdbe4c3059158ccb2db8780352fa1b01e8ccf45cc4d"
dependencies = [ dependencies = [
"crossterm", "crossterm",
"strum", "strum",
@ -671,12 +671,14 @@ dependencies = [
[[package]] [[package]]
name = "config" name = "config"
version = "0.11.0" version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1b9d958c2b1368a663f05538fc1b5975adce1e19f435acceae987aceeeb369" checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7"
dependencies = [ dependencies = [
"async-trait",
"lazy_static", "lazy_static",
"nom 5.1.2", "nom",
"pathdiff",
"serde", "serde",
"toml", "toml",
] ]
@ -967,10 +969,21 @@ dependencies = [
] ]
[[package]] [[package]]
name = "data-encoding" name = "dashmap"
version = "2.3.2" version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" checksum = "4c8858831f7781322e539ea39e72449c46b059638250c14344fec8d0aa6e539c"
dependencies = [
"cfg-if 1.0.0",
"num_cpus",
"parking_lot 0.12.0",
]
[[package]]
name = "data-encoding"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb"
[[package]] [[package]]
name = "derive_more" name = "derive_more"
@ -1052,7 +1065,7 @@ checksum = "5caaa75cbd2b960ff1e5392d2cfb1f44717fffe12fc1f32b7b5d1267f99732a6"
[[package]] [[package]]
name = "ecdsa_fun" name = "ecdsa_fun"
version = "0.7.1" version = "0.7.1"
source = "git+https://github.com/LLFourn/secp256kfun#da6ffd2ef4d58c84d508428356c92d92d5f11ac4" source = "git+https://github.com/LLFourn/secp256kfun#9657d8c12fd26df5e57254a0063eaf41082a38ca"
dependencies = [ dependencies = [
"bincode", "bincode",
"rand_chacha 0.3.1", "rand_chacha 0.3.1",
@ -1463,9 +1476,9 @@ dependencies = [
[[package]] [[package]]
name = "git2" name = "git2"
version = "0.14.4" version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0155506aab710a86160ddb504a480d2964d7ab5b9e62419be69e0032bc5931c" checksum = "2994bee4a3a6a51eb90c218523be382fd7ea09b16380b9312e9dbe955ff7c7d1"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"libc", "libc",
@ -1964,19 +1977,6 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lexical-core"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374"
dependencies = [
"arrayvec 0.5.2",
"bitflags",
"cfg-if 1.0.0",
"ryu",
"static_assertions",
]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.137" version = "0.2.137"
@ -1985,9 +1985,9 @@ checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
[[package]] [[package]]
name = "libgit2-sys" name = "libgit2-sys"
version = "0.13.4+1.4.2" version = "0.14.0+1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0fa6563431ede25f5cc7f6d803c6afbc1c5d3ad3d4925d12c882bf2b526f5d1" checksum = "47a00859c70c8a4f7218e6d1cc32875c4b55f6799445b842b0d8ed5e4c3d959b"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
@ -2485,6 +2485,7 @@ dependencies = [
"monero-epee-bin-serde", "monero-epee-bin-serde",
"rand 0.7.3", "rand 0.7.3",
"reqwest", "reqwest",
"rust_decimal",
"serde", "serde",
"serde_json", "serde_json",
"tokio", "tokio",
@ -2577,17 +2578,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
[[package]]
name = "nom"
version = "5.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
dependencies = [
"lexical-core",
"memchr",
"version_check",
]
[[package]] [[package]]
name = "nom" name = "nom"
version = "7.0.0" version = "7.0.0"
@ -2690,9 +2680,9 @@ dependencies = [
[[package]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.13.0" version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi",
"libc", "libc",
@ -2808,6 +2798,12 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
[[package]]
name = "pathdiff"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
[[package]] [[package]]
name = "pem" name = "pem"
version = "1.1.0" version = "1.1.0"
@ -3425,7 +3421,7 @@ version = "1.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c321ee4e17d2b7abe12b5d20c1231db708dd36185c8a21e9de5fed6da4dbe9" checksum = "33c321ee4e17d2b7abe12b5d20c1231db708dd36185c8a21e9de5fed6da4dbe9"
dependencies = [ dependencies = [
"arrayvec 0.7.2", "arrayvec",
"borsh", "borsh",
"bytecheck", "bytecheck",
"byteorder", "byteorder",
@ -3633,7 +3629,7 @@ dependencies = [
[[package]] [[package]]
name = "secp256kfun" name = "secp256kfun"
version = "0.7.1" version = "0.7.1"
source = "git+https://github.com/LLFourn/secp256kfun#da6ffd2ef4d58c84d508428356c92d92d5f11ac4" source = "git+https://github.com/LLFourn/secp256kfun#9657d8c12fd26df5e57254a0063eaf41082a38ca"
dependencies = [ dependencies = [
"digest 0.10.5", "digest 0.10.5",
"rand_core 0.6.2", "rand_core 0.6.2",
@ -3700,9 +3696,9 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.148" version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc" checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
@ -3729,9 +3725,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.148" version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c" checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -3740,9 +3736,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.89" version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -3783,6 +3779,31 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "serial_test"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c789ec87f4687d022a2405cf46e0cd6284889f1839de292cadeb6c6019506f2"
dependencies = [
"dashmap",
"futures",
"lazy_static",
"log",
"parking_lot 0.12.0",
"serial_test_derive",
]
[[package]]
name = "serial_test_derive"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b64f9e531ce97c88b4778aad0ceee079216071cffec6ac9b904277f8f92e7fe3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "sha-1" name = "sha-1"
version = "0.9.4" version = "0.9.4"
@ -3844,7 +3865,7 @@ dependencies = [
[[package]] [[package]]
name = "sigma_fun" name = "sigma_fun"
version = "0.4.1" version = "0.4.1"
source = "git+https://github.com/LLFourn/secp256kfun#da6ffd2ef4d58c84d508428356c92d92d5f11ac4" source = "git+https://github.com/LLFourn/secp256kfun#9657d8c12fd26df5e57254a0063eaf41082a38ca"
dependencies = [ dependencies = [
"curve25519-dalek-ng", "curve25519-dalek-ng",
"digest 0.10.5", "digest 0.10.5",
@ -4005,7 +4026,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f87e292b4291f154971a43c3774364e2cbcaec599d3f5bf6fa9d122885dbc38a" checksum = "f87e292b4291f154971a43c3774364e2cbcaec599d3f5bf6fa9d122885dbc38a"
dependencies = [ dependencies = [
"itertools", "itertools",
"nom 7.0.0", "nom",
"unicode_categories", "unicode_categories",
] ]
@ -4193,14 +4214,14 @@ checksum = "8049cf85f0e715d6af38dde439cb0ccb91f67fb9f5f63c80f8b43e48356e1a3f"
[[package]] [[package]]
name = "swap" name = "swap"
version = "0.11.0" version = "0.12.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-compression", "async-compression",
"async-trait", "async-trait",
"atty", "atty",
"backoff", "backoff",
"base64 0.13.1", "base64 0.20.0",
"bdk", "bdk",
"big-bytes", "big-bytes",
"bitcoin", "bitcoin",
@ -4241,6 +4262,7 @@ dependencies = [
"serde_cbor", "serde_cbor",
"serde_json", "serde_json",
"serde_with", "serde_with",
"serial_test",
"sha2 0.10.6", "sha2 0.10.6",
"sigma_fun", "sigma_fun",
"spectral", "spectral",
@ -4359,18 +4381,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.37" version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.37" version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -4586,9 +4608,9 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.9" version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -4972,9 +4994,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]] [[package]]
name = "vergen" name = "vergen"
version = "7.4.3" version = "7.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "447f9238a4553957277b3ee09d80babeae0811f1b3baefb093de1c0448437a37" checksum = "efadd36bc6fde40c6048443897d69511a19161c0756cb704ed403f8dfd2b7d1c"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cfg-if 1.0.0", "cfg-if 1.0.0",

View File

@ -25,7 +25,7 @@ impl Image for Monerod {
type EntryPoint = str; type EntryPoint = str;
fn descriptor(&self) -> String { fn descriptor(&self) -> String {
"rinocommunity/monero:v0.18.0.0".to_owned() "rinocommunity/monero:v0.18.1.2".to_owned()
} }
fn wait_until_ready<D: Docker>(&self, container: &Container<'_, D, Self>) { fn wait_until_ready<D: Docker>(&self, container: &Container<'_, D, Self>) {
@ -70,7 +70,7 @@ impl Image for MoneroWalletRpc {
type EntryPoint = str; type EntryPoint = str;
fn descriptor(&self) -> String { fn descriptor(&self) -> String {
"rinocommunity/monero:v0.18.0.0".to_owned() "rinocommunity/monero:v0.18.1.2".to_owned()
} }
fn wait_until_ready<D: Docker>(&self, container: &Container<'_, D, Self>) { fn wait_until_ready<D: Docker>(&self, container: &Container<'_, D, Self>) {
@ -229,6 +229,7 @@ impl IntoIterator for MoneroWalletRpcArgs {
format!("--daemon-address={}", self.daemon_address), format!("--daemon-address={}", self.daemon_address),
format!("--rpc-bind-port={}", RPC_PORT), format!("--rpc-bind-port={}", RPC_PORT),
"--log-level=4".to_string(), "--log-level=4".to_string(),
"--allow-mismatched-daemon-version".to_string(), /* https://github.com/monero-project/monero/issues/8600 */
]; ];
if self.disable_rpc_login { if self.disable_rpc_login {

View File

@ -138,15 +138,30 @@ impl<'c> Monero {
let wallet = self.wallet(name)?; let wallet = self.wallet(name)?;
let address = wallet.address().await?.address; let address = wallet.address().await?.address;
let mut expected_total = 0;
let mut expected_unlocked = 0;
let mut unlocked = 0;
for amount in amount_in_outputs { for amount in amount_in_outputs {
if amount > 0 { if amount > 0 {
miner_wallet.transfer(&address, amount).await?; miner_wallet.transfer(&address, amount).await?;
expected_total += amount;
tracing::info!("Funded {} wallet with {}", wallet.name, amount); tracing::info!("Funded {} wallet with {}", wallet.name, amount);
// sanity checks for total/unlocked balance
let total = wallet.balance().await?;
assert_eq!(total, expected_total);
assert_eq!(unlocked, expected_unlocked);
monerod monerod
.client() .client()
.generateblocks(10, miner_address.clone()) .generateblocks(10, miner_address.clone())
.await?; .await?;
wallet.refresh().await?; wallet.refresh().await?;
expected_unlocked += amount;
unlocked = wallet.unlocked_balance().await?;
assert_eq!(unlocked, expected_unlocked);
assert_eq!(total, expected_total);
} }
} }
@ -310,10 +325,18 @@ impl<'c> MoneroWalletRpc {
Ok(balance) Ok(balance)
} }
pub async fn unlocked_balance(&self) -> Result<u64> {
self.client().refresh().await?;
let balance = self.client().get_balance(0).await?.unlocked_balance;
Ok(balance)
}
pub async fn refresh(&self) -> Result<Refreshed> { pub async fn refresh(&self) -> Result<Refreshed> {
Ok(self.client().refresh().await?) Ok(self.client().refresh().await?)
} }
} }
/// Mine a block ever BLOCK_TIME_SECS seconds. /// Mine a block ever BLOCK_TIME_SECS seconds.
async fn mine(monerod: monerod::Client, reward_address: String) -> Result<()> { async fn mine(monerod: monerod::Client, reward_address: String) -> Result<()> {
loop { loop {

View File

@ -13,6 +13,7 @@ monero = "0.12"
monero-epee-bin-serde = "1" monero-epee-bin-serde = "1"
rand = "0.7" rand = "0.7"
reqwest = { version = "0.11", default-features = false, features = [ "json" ] } reqwest = { version = "0.11", default-features = false, features = [ "json" ] }
rust_decimal = { version = "1", features = [ "serde-float" ] }
serde = { version = "1.0", features = [ "derive" ] } serde = { version = "1.0", features = [ "derive" ] }
serde_json = "1.0" serde_json = "1.0"
tracing = "0.1" tracing = "0.1"

View File

@ -1,4 +1,7 @@
use std::fmt;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use rust_decimal::Decimal;
use serde::de::Error; use serde::de::Error;
use serde::{Deserialize, Deserializer, Serialize}; use serde::{Deserialize, Deserializer, Serialize};
@ -86,10 +89,30 @@ pub struct GetAddress {
#[derive(Deserialize, Debug, Clone, Copy)] #[derive(Deserialize, Debug, Clone, Copy)]
pub struct GetBalance { pub struct GetBalance {
pub balance: u64, pub balance: u64,
pub blocks_to_unlock: u32,
pub multisig_import_needed: bool,
pub time_to_unlock: u32,
pub unlocked_balance: u64, pub unlocked_balance: u64,
pub multisig_import_needed: bool,
pub blocks_to_unlock: u32,
pub time_to_unlock: u32,
}
impl fmt::Display for GetBalance {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut total = Decimal::from(self.balance);
total
.set_scale(12)
.expect("12 is smaller than max precision of 28");
let mut unlocked = Decimal::from(self.unlocked_balance);
unlocked
.set_scale(12)
.expect("12 is smaller than max precision of 28");
write!(
f,
"total balance: {}, unlocked balance: {}",
total, unlocked
)
}
} }
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "swap" name = "swap"
version = "0.11.0" version = "0.12.0"
authors = [ "The COMIT guys <hello@comit.network>" ] authors = [ "The COMIT guys <hello@comit.network>" ]
edition = "2021" edition = "2021"
description = "XMR/BTC trustless atomic swaps." description = "XMR/BTC trustless atomic swaps."
@ -14,13 +14,13 @@ async-compression = { version = "0.3", features = [ "bzip2", "tokio" ] }
async-trait = "0.1" async-trait = "0.1"
atty = "0.2" atty = "0.2"
backoff = { version = "0.4", features = [ "tokio" ] } backoff = { version = "0.4", features = [ "tokio" ] }
base64 = "0.13" base64 = "0.20"
bdk = "0.24" bdk = "0.25"
big-bytes = "1" big-bytes = "1"
bitcoin = { version = "0.29", features = [ "rand", "serde" ] } bitcoin = { version = "0.29", features = [ "rand", "serde" ] }
bmrng = "0.5" bmrng = "0.5"
comfy-table = "6.1" comfy-table = "6.1"
config = { version = "0.11", default-features = false, features = [ "toml" ] } config = { version = "0.13", default-features = false, features = [ "toml" ] }
conquer-once = "0.3" conquer-once = "0.3"
curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" } curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" }
data-encoding = "2.3" data-encoding = "2.3"
@ -85,11 +85,12 @@ jsonrpsee-types = { version = "0.16.2" }
port_check = "0.1" port_check = "0.1"
proptest = "1" proptest = "1"
serde_cbor = "0.11" serde_cbor = "0.11"
serial_test = "0.10"
spectral = "0.6" spectral = "0.6"
tempfile = "3" tempfile = "3"
testcontainers = "0.12" testcontainers = "0.12"
sequential-test = "0.2.4" sequential-test = "0.2.4"
[build-dependencies] [build-dependencies]
vergen = { version = "7", default-features = false, features = [ "git", "build" ] }
anyhow = "1" anyhow = "1"
vergen = { version = "7", default-features = false, features = [ "git", "build" ] }

View File

@ -102,12 +102,27 @@ impl Config {
{ {
let config_file = Path::new(&config_file); let config_file = Path::new(&config_file);
let mut config = config::Config::new(); let config = config::Config::builder()
config.merge(config::File::from(config_file))?; .add_source(config::File::from(config_file))
.add_source(
config::Environment::with_prefix("ASB")
.separator("__")
.list_separator(","),
)
.build()?;
config.try_into() config.try_into()
} }
} }
impl TryFrom<config::Config> for Config {
type Error = config::ConfigError;
fn try_from(value: config::Config) -> Result<Self, Self::Error> {
value.try_deserialize()
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct Data { pub struct Data {
@ -117,13 +132,55 @@ pub struct Data {
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct Network { pub struct Network {
#[serde(deserialize_with = "addr_list::deserialize")]
pub listen: Vec<Multiaddr>, pub listen: Vec<Multiaddr>,
#[serde(default)] #[serde(default)]
pub rendezvous_point: Option<Multiaddr>, pub rendezvous_point: Option<Multiaddr>,
#[serde(default)] #[serde(default, deserialize_with = "addr_list::deserialize")]
pub external_addresses: Vec<Multiaddr>, pub external_addresses: Vec<Multiaddr>,
} }
mod addr_list {
use libp2p::Multiaddr;
use serde::de::Unexpected;
use serde::{de, Deserialize, Deserializer};
use serde_json::Value;
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Multiaddr>, D::Error>
where
D: Deserializer<'de>,
{
let s = Value::deserialize(deserializer)?;
return match s {
Value::String(s) => {
let list: Result<Vec<_>, _> = s
.split(',')
.filter(|s| !s.is_empty())
.map(|s| s.parse().map_err(de::Error::custom))
.collect();
Ok(list?)
}
Value::Array(a) => {
let list: Result<Vec<_>, _> = a
.iter()
.map(|v| {
if let Value::String(s) = v {
s.parse().map_err(de::Error::custom)
} else {
Err(de::Error::custom("expected a string"))
}
})
.collect();
Ok(list?)
}
value => Err(de::Error::invalid_type(
Unexpected::Other(&value.to_string()),
&"a string or array",
)),
};
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct Bitcoin { pub struct Bitcoin {
@ -159,6 +216,7 @@ pub struct Maker {
pub max_buy_btc: bitcoin::Amount, pub max_buy_btc: bitcoin::Amount,
pub ask_spread: Decimal, pub ask_spread: Decimal,
pub price_ticker_ws_url: Url, pub price_ticker_ws_url: Url,
pub external_bitcoin_redeem_address: Option<bitcoin::Address>,
} }
impl Default for TorConf { impl Default for TorConf {
@ -172,7 +230,7 @@ impl Default for TorConf {
#[derive(thiserror::Error, Debug, Clone, Copy)] #[derive(thiserror::Error, Debug, Clone, Copy)]
#[error("config not initialized")] #[error("config not initialized")]
pub struct ConfigNotInitialized {} pub struct ConfigNotInitialized;
pub fn read_config(config_path: PathBuf) -> Result<Result<Config, ConfigNotInitialized>> { pub fn read_config(config_path: PathBuf) -> Result<Result<Config, ConfigNotInitialized>> {
if config_path.exists() { if config_path.exists() {
@ -327,6 +385,7 @@ pub fn query_user_for_initial_config(testnet: bool) -> Result<Config> {
max_buy_btc: max_buy, max_buy_btc: max_buy,
ask_spread, ask_spread,
price_ticker_ws_url: defaults.price_ticker_ws_url, price_ticker_ws_url: defaults.price_ticker_ws_url,
external_bitcoin_redeem_address: None,
}, },
}) })
} }
@ -334,9 +393,12 @@ pub fn query_user_for_initial_config(testnet: bool) -> Result<Config> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use serial_test::serial;
use tempfile::tempdir; use tempfile::tempdir;
// these tests are run serially since env vars affect the whole process
#[test] #[test]
#[serial]
fn config_roundtrip_testnet() { fn config_roundtrip_testnet() {
let temp_dir = tempdir().unwrap().path().to_path_buf(); let temp_dir = tempdir().unwrap().path().to_path_buf();
let config_path = Path::join(&temp_dir, "config.toml"); let config_path = Path::join(&temp_dir, "config.toml");
@ -358,7 +420,6 @@ mod tests {
rendezvous_point: None, rendezvous_point: None,
external_addresses: vec![], external_addresses: vec![],
}, },
monero: Monero { monero: Monero {
wallet_rpc_url: defaults.monero_wallet_rpc_url, wallet_rpc_url: defaults.monero_wallet_rpc_url,
finality_confirmations: None, finality_confirmations: None,
@ -370,6 +431,7 @@ mod tests {
max_buy_btc: bitcoin::Amount::from_btc(DEFAULT_MAX_BUY_AMOUNT).unwrap(), max_buy_btc: bitcoin::Amount::from_btc(DEFAULT_MAX_BUY_AMOUNT).unwrap(),
ask_spread: Decimal::from_f64(DEFAULT_SPREAD).unwrap(), ask_spread: Decimal::from_f64(DEFAULT_SPREAD).unwrap(),
price_ticker_ws_url: defaults.price_ticker_ws_url, price_ticker_ws_url: defaults.price_ticker_ws_url,
external_bitcoin_redeem_address: None,
}, },
}; };
@ -380,6 +442,7 @@ mod tests {
} }
#[test] #[test]
#[serial]
fn config_roundtrip_mainnet() { fn config_roundtrip_mainnet() {
let temp_dir = tempdir().unwrap().path().to_path_buf(); let temp_dir = tempdir().unwrap().path().to_path_buf();
let config_path = Path::join(&temp_dir, "config.toml"); let config_path = Path::join(&temp_dir, "config.toml");
@ -401,7 +464,6 @@ mod tests {
rendezvous_point: None, rendezvous_point: None,
external_addresses: vec![], external_addresses: vec![],
}, },
monero: Monero { monero: Monero {
wallet_rpc_url: defaults.monero_wallet_rpc_url, wallet_rpc_url: defaults.monero_wallet_rpc_url,
finality_confirmations: None, finality_confirmations: None,
@ -413,6 +475,7 @@ mod tests {
max_buy_btc: bitcoin::Amount::from_btc(DEFAULT_MAX_BUY_AMOUNT).unwrap(), max_buy_btc: bitcoin::Amount::from_btc(DEFAULT_MAX_BUY_AMOUNT).unwrap(),
ask_spread: Decimal::from_f64(DEFAULT_SPREAD).unwrap(), ask_spread: Decimal::from_f64(DEFAULT_SPREAD).unwrap(),
price_ticker_ws_url: defaults.price_ticker_ws_url, price_ticker_ws_url: defaults.price_ticker_ws_url,
external_bitcoin_redeem_address: None,
}, },
}; };
@ -421,4 +484,61 @@ mod tests {
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test]
#[serial]
fn env_override() {
let temp_dir = tempfile::tempdir().unwrap().path().to_path_buf();
let config_path = Path::join(&temp_dir, "config.toml");
let defaults = Mainnet::getConfigFileDefaults().unwrap();
let dir = PathBuf::from("/tmp/dir");
std::env::set_var("ASB__DATA__DIR", dir.clone());
let addr1 = "/dns4/example.com/tcp/9939";
let addr2 = "/ip4/1.2.3.4/tcp/9940";
let external_addresses = vec![addr1.parse().unwrap(), addr2.parse().unwrap()];
let listen = external_addresses.clone();
std::env::set_var(
"ASB__NETWORK__EXTERNAL_ADDRESSES",
format!("{},{}", addr1, addr2),
);
std::env::set_var("ASB__NETWORK__LISTEN", format!("{},{}", addr1, addr2));
let expected = Config {
data: Data { dir },
bitcoin: Bitcoin {
electrum_rpc_url: defaults.electrum_rpc_url,
target_block: defaults.bitcoin_confirmation_target,
finality_confirmations: None,
network: bitcoin::Network::Bitcoin,
},
network: Network {
listen,
rendezvous_point: None,
external_addresses,
},
monero: Monero {
wallet_rpc_url: defaults.monero_wallet_rpc_url,
finality_confirmations: None,
network: monero::Network::Mainnet,
},
tor: Default::default(),
maker: Maker {
min_buy_btc: bitcoin::Amount::from_btc(DEFAULT_MIN_BUY_AMOUNT).unwrap(),
max_buy_btc: bitcoin::Amount::from_btc(DEFAULT_MAX_BUY_AMOUNT).unwrap(),
ask_spread: Decimal::from_f64(DEFAULT_SPREAD).unwrap(),
price_ticker_ws_url: defaults.price_ticker_ws_url,
external_bitcoin_redeem_address: None,
},
};
initial_setup(config_path.clone(), expected.clone()).unwrap();
let actual = read_config(config_path).unwrap().unwrap();
assert_eq!(expected, actual);
std::env::remove_var("ASB__DATA__DIR");
std::env::remove_var("ASB__NETWORK__EXTERNAL_ADDRESSES");
std::env::remove_var("ASB__NETWORK__LISTEN");
}
} }

View File

@ -1,4 +1,5 @@
use crate::asb::{Behaviour, OutEvent, Rate}; use crate::asb::{Behaviour, OutEvent, Rate};
use crate::monero::Amount;
use crate::network::quote::BidQuote; use crate::network::quote::BidQuote;
use crate::network::swap_setup::alice::WalletSnapshot; use crate::network::swap_setup::alice::WalletSnapshot;
use crate::network::transfer_proof; use crate::network::transfer_proof;
@ -43,6 +44,7 @@ where
latest_rate: LR, latest_rate: LR,
min_buy: bitcoin::Amount, min_buy: bitcoin::Amount,
max_buy: bitcoin::Amount, max_buy: bitcoin::Amount,
external_redeem_address: Option<bitcoin::Address>,
swap_sender: mpsc::Sender<Swap>, swap_sender: mpsc::Sender<Swap>,
@ -75,6 +77,7 @@ where
latest_rate: LR, latest_rate: LR,
min_buy: bitcoin::Amount, min_buy: bitcoin::Amount,
max_buy: bitcoin::Amount, max_buy: bitcoin::Amount,
external_redeem_address: Option<bitcoin::Address>,
) -> Result<(Self, mpsc::Receiver<Swap>)> { ) -> Result<(Self, mpsc::Receiver<Swap>)> {
let swap_channel = MpscChannels::default(); let swap_channel = MpscChannels::default();
@ -88,6 +91,7 @@ where
swap_sender: swap_channel.sender, swap_sender: swap_channel.sender,
min_buy, min_buy,
max_buy, max_buy,
external_redeem_address,
recv_encrypted_signature: Default::default(), recv_encrypted_signature: Default::default(),
inflight_encrypted_signatures: Default::default(), inflight_encrypted_signatures: Default::default(),
send_transfer_proof: Default::default(), send_transfer_proof: Default::default(),
@ -164,7 +168,7 @@ where
} }
}; };
let wallet_snapshot = match WalletSnapshot::capture(&self.bitcoin_wallet, &self.monero_wallet, btc).await { let wallet_snapshot = match WalletSnapshot::capture(&self.bitcoin_wallet, &self.monero_wallet, &self.external_redeem_address, btc).await {
Ok(wallet_snapshot) => wallet_snapshot, Ok(wallet_snapshot) => wallet_snapshot,
Err(error) => { Err(error) => {
tracing::error!("Swap request will be ignored because we were unable to create wallet snapshot for swap: {:#}", error); tracing::error!("Swap request will be ignored because we were unable to create wallet snapshot for swap: {:#}", error);
@ -326,7 +330,10 @@ where
.ask() .ask()
.context("Failed to compute asking price")?; .context("Failed to compute asking price")?;
let xmr = self.monero_wallet.get_balance().await?; let balance = self.monero_wallet.get_balance().await?;
// use unlocked monero balance for quote
let xmr = Amount::from_piconero(balance.unlocked_balance);
let max_bitcoin_for_monero = xmr.max_bitcoin_for_price(ask_price).ok_or_else(|| { let max_bitcoin_for_monero = xmr.max_bitcoin_for_price(ask_price).ok_or_else(|| {
anyhow::anyhow!("Bitcoin price ({}) x Monero ({}) overflow", ask_price, xmr) anyhow::anyhow!("Bitcoin price ({}) x Monero ({}) overflow", ask_price, xmr)

View File

@ -31,7 +31,6 @@ use swap::asb::config::{
use swap::asb::{cancel, punish, redeem, refund, safely_abort, EventLoop, Finality, KrakenRate}; use swap::asb::{cancel, punish, redeem, refund, safely_abort, EventLoop, Finality, KrakenRate};
use swap::common::check_latest_version; use swap::common::check_latest_version;
use swap::database::open_db; use swap::database::open_db;
use swap::monero::Amount;
use swap::network::rendezvous::XmrBtcNamespace; use swap::network::rendezvous::XmrBtcNamespace;
use swap::network::swarm; use swap::network::swarm;
use swap::protocol::alice::{run, AliceState}; use swap::protocol::alice::{run, AliceState};
@ -103,24 +102,35 @@ async fn main() -> Result<()> {
match cmd { match cmd {
Command::Start { resume_only } => { Command::Start { resume_only } => {
let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?;
let monero_wallet = init_monero_wallet(&config, env_config).await?; let monero_wallet = init_monero_wallet(&config, env_config).await?;
let monero_address = monero_wallet.get_main_address();
let bitcoin_balance = bitcoin_wallet.balance().await?; tracing::info!(%monero_address, "Monero wallet address");
tracing::info!(%bitcoin_balance, "Initialized Bitcoin wallet"); let monero = monero_wallet.get_balance().await?;
match (monero.balance, monero.unlocked_balance) {
let monero_balance = monero_wallet.get_balance().await?; (0, _) => {
if monero_balance == Amount::ZERO { tracing::warn!(
let monero_address = monero_wallet.get_main_address(); %monero_address,
tracing::warn!( "The Monero balance is 0, make sure to deposit funds at",
%monero_address, )
"The Monero balance is 0, make sure to deposit funds at", }
) (total, 0) => {
} else { let total = monero::Amount::from_piconero(total);
tracing::info!(%monero_balance, "Initialized Monero wallet"); tracing::warn!(
%total,
"Unlocked Monero balance is 0, total balance is",
)
}
(total, unlocked) => {
let total = monero::Amount::from_piconero(total);
let unlocked = monero::Amount::from_piconero(unlocked);
tracing::info!(%total, %unlocked, "Monero wallet balance");
}
} }
let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?;
let bitcoin_balance = bitcoin_wallet.balance().await?;
tracing::info!(%bitcoin_balance, "Bitcoin wallet balance");
let kraken_price_updates = kraken::connect(config.maker.price_ticker_ws_url.clone())?; let kraken_price_updates = kraken::connect(config.maker.price_ticker_ws_url.clone())?;
// setup Tor hidden services // setup Tor hidden services
@ -178,6 +188,7 @@ async fn main() -> Result<()> {
kraken_rate.clone(), kraken_rate.clone(),
config.maker.min_buy_btc, config.maker.min_buy_btc,
config.maker.max_buy_btc, config.maker.max_buy_btc,
config.maker.external_bitcoin_redeem_address,
) )
.unwrap(); .unwrap();
@ -236,16 +247,14 @@ async fn main() -> Result<()> {
bitcoin_wallet.broadcast(signed_tx, "withdraw").await?; bitcoin_wallet.broadcast(signed_tx, "withdraw").await?;
} }
Command::Balance => { Command::Balance => {
let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?;
let monero_wallet = init_monero_wallet(&config, env_config).await?; let monero_wallet = init_monero_wallet(&config, env_config).await?;
let bitcoin_balance = bitcoin_wallet.balance().await?;
let monero_balance = monero_wallet.get_balance().await?; let monero_balance = monero_wallet.get_balance().await?;
tracing::info!(%monero_balance);
tracing::info!( let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?;
%bitcoin_balance, let bitcoin_balance = bitcoin_wallet.balance().await?;
%monero_balance, tracing::info!(%bitcoin_balance);
"Current balance"); tracing::info!(%bitcoin_balance, %monero_balance, "Current balance");
} }
Command::Cancel { swap_id } => { Command::Cancel { swap_id } => {
let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?;

View File

@ -169,8 +169,6 @@ impl Wallet {
let mut last_status = None; let mut last_status = None;
loop { loop {
tokio::time::sleep(Duration::from_secs(5)).await;
let new_status = match client.lock().await.status_of_script(&tx) { let new_status = match client.lock().await.status_of_script(&tx) {
Ok(new_status) => new_status, Ok(new_status) => new_status,
Err(error) => { Err(error) => {
@ -191,6 +189,8 @@ impl Wallet {
return; return;
} }
} }
tokio::time::sleep(Duration::from_secs(5)).await;
} }
}); });
@ -743,7 +743,7 @@ impl Client {
electrum, electrum,
blockchain, blockchain,
latest_block_height: BlockHeight::try_from(latest_block)?, latest_block_height: BlockHeight::try_from(latest_block)?,
last_sync: Instant::now(), last_sync: Instant::now() - interval,
sync_interval: interval, sync_interval: interval,
script_history: Default::default(), script_history: Default::default(),
subscriptions: Default::default(), subscriptions: Default::default(),

View File

@ -47,10 +47,10 @@ mod test {
#[tokio::test] #[tokio::test]
#[ignore = "For local testing, makes http requests to github."] #[ignore = "For local testing, makes http requests to github."]
async fn it_compares_with_github() { async fn it_compares_with_github() {
let result = check_latest_version("0.10.1").await.unwrap(); let result = check_latest_version("0.11.0").await.unwrap();
assert_eq!(result, Version::Available); assert_eq!(result, Version::Available);
let result = check_latest_version("0.10.2").await.unwrap(); let result = check_latest_version("0.11.1").await.unwrap();
assert_eq!(result, Version::Current); assert_eq!(result, Version::Current);
} }
} }

View File

@ -253,10 +253,8 @@ impl Wallet {
} }
/// Get the balance of the primary account. /// Get the balance of the primary account.
pub async fn get_balance(&self) -> Result<Amount> { pub async fn get_balance(&self) -> Result<wallet::GetBalance> {
let amount = self.inner.lock().await.get_balance(0).await?.balance; Ok(self.inner.lock().await.get_balance(0).await?)
Ok(Amount::from_piconero(amount))
} }
pub async fn block_height(&self) -> Result<BlockHeight> { pub async fn block_height(&self) -> Result<BlockHeight> {

View File

@ -18,20 +18,20 @@ use tokio_util::io::StreamReader;
compile_error!("unsupported operating system"); compile_error!("unsupported operating system");
#[cfg(all(target_os = "macos", target_arch = "x86_64"))] #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.0.0.tar.bz2"; const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.1.2.tar.bz2";
#[cfg(all(target_os = "macos", target_arch = "aarch64"))] #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.0.0.tar.bz2"; const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.0.0.tar.bz2";
#[cfg(all(target_os = "linux", target_arch = "x86_64"))] #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.0.0.tar.bz2"; const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.1.2.tar.bz2";
#[cfg(all(target_os = "linux", target_arch = "arm"))] #[cfg(all(target_os = "linux", target_arch = "arm"))]
const DOWNLOAD_URL: &str = const DOWNLOAD_URL: &str =
"https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.0.0.tar.bz2"; "https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.1.2.tar.bz2";
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.0.0.zip"; const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.1.2.zip";
#[cfg(any(target_os = "macos", target_os = "linux"))] #[cfg(any(target_os = "macos", target_os = "linux"))]
const PACKED_FILE: &str = "monero-wallet-rpc"; const PACKED_FILE: &str = "monero-wallet-rpc";
@ -39,7 +39,7 @@ const PACKED_FILE: &str = "monero-wallet-rpc";
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
const PACKED_FILE: &str = "monero-wallet-rpc.exe"; const PACKED_FILE: &str = "monero-wallet-rpc.exe";
const CODENAME: &str = "Fluorine Fermi"; const WALLET_RPC_VERSION: &str = "v0.18.1.2";
#[derive(Debug, Clone, Copy, thiserror::Error)] #[derive(Debug, Clone, Copy, thiserror::Error)]
#[error("monero wallet rpc executable not found in downloaded archive")] #[error("monero wallet rpc executable not found in downloaded archive")]
@ -86,7 +86,7 @@ impl WalletRpc {
let version = String::from_utf8_lossy(&output.stdout); let version = String::from_utf8_lossy(&output.stdout);
tracing::debug!("RPC version output: {}", version); tracing::debug!("RPC version output: {}", version);
if !version.contains(CODENAME) { if !version.contains(WALLET_RPC_VERSION) {
tracing::info!("Removing old version of monero-wallet-rpc"); tracing::info!("Removing old version of monero-wallet-rpc");
tokio::fs::remove_file(exec_path).await?; tokio::fs::remove_file(exec_path).await?;
} }

View File

@ -1,4 +1,5 @@
use crate::asb::LatestRate; use crate::asb::LatestRate;
use crate::monero::Amount;
use crate::network::swap_setup; use crate::network::swap_setup;
use crate::network::swap_setup::{ use crate::network::swap_setup::{
protocol, BlockchainNetwork, SpotPriceError, SpotPriceRequest, SpotPriceResponse, protocol, BlockchainNetwork, SpotPriceError, SpotPriceRequest, SpotPriceResponse,
@ -42,7 +43,7 @@ pub enum OutEvent {
#[derive(Debug)] #[derive(Debug)]
pub struct WalletSnapshot { pub struct WalletSnapshot {
balance: monero::Amount, balance: monero_rpc::wallet::GetBalance,
lock_fee: monero::Amount, lock_fee: monero::Amount,
// TODO: Consider using the same address for punish and redeem (they are mutually exclusive, so // TODO: Consider using the same address for punish and redeem (they are mutually exclusive, so
@ -58,11 +59,17 @@ impl WalletSnapshot {
pub async fn capture( pub async fn capture(
bitcoin_wallet: &bitcoin::Wallet, bitcoin_wallet: &bitcoin::Wallet,
monero_wallet: &monero::Wallet, monero_wallet: &monero::Wallet,
external_redeem_address: &Option<bitcoin::Address>,
transfer_amount: bitcoin::Amount, transfer_amount: bitcoin::Amount,
) -> Result<Self> { ) -> Result<Self> {
let balance = monero_wallet.get_balance().await?; let balance = monero_wallet.get_balance().await?;
let redeem_address = bitcoin_wallet.new_address().await?; let redeem_address = external_redeem_address
let punish_address = bitcoin_wallet.new_address().await?; .clone()
.unwrap_or(bitcoin_wallet.new_address().await?);
let punish_address = external_redeem_address
.clone()
.unwrap_or(bitcoin_wallet.new_address().await?);
let redeem_fee = bitcoin_wallet let redeem_fee = bitcoin_wallet
.estimate_fee(bitcoin::TxRedeem::weight(), transfer_amount) .estimate_fee(bitcoin::TxRedeem::weight(), transfer_amount)
.await?; .await?;
@ -323,7 +330,8 @@ where
.sell_quote(btc) .sell_quote(btc)
.map_err(Error::SellQuoteCalculationFailed)?; .map_err(Error::SellQuoteCalculationFailed)?;
if wallet_snapshot.balance < xmr + wallet_snapshot.lock_fee { let unlocked = Amount::from_piconero(wallet_snapshot.balance.unlocked_balance);
if unlocked < xmr + wallet_snapshot.lock_fee {
return Err(Error::BalanceTooLow { return Err(Error::BalanceTooLow {
balance: wallet_snapshot.balance, balance: wallet_snapshot.balance,
buy: btc, buy: btc,
@ -479,9 +487,9 @@ pub enum Error {
max: bitcoin::Amount, max: bitcoin::Amount,
buy: bitcoin::Amount, buy: bitcoin::Amount,
}, },
#[error("Balance {balance} too low to fulfill swapping {buy}")] #[error("Unlocked balance ({balance}) too low to fulfill swapping {buy}")]
BalanceTooLow { BalanceTooLow {
balance: monero::Amount, balance: monero_rpc::wallet::GetBalance,
buy: bitcoin::Amount, buy: bitcoin::Amount,
}, },
#[error("Failed to fetch latest rate")] #[error("Failed to fetch latest rate")]

View File

@ -259,6 +259,7 @@ async fn start_alice(
FixedRate::default(), FixedRate::default(),
min_buy, min_buy,
max_buy, max_buy,
None,
) )
.unwrap(); .unwrap();
@ -867,7 +868,9 @@ impl Wallet for monero::Wallet {
} }
async fn get_balance(&self) -> Result<Self::Amount> { async fn get_balance(&self) -> Result<Self::Amount> {
self.get_balance().await let total = self.get_balance().await?;
let balance = Self::Amount::from_piconero(total.balance);
Ok(balance)
} }
} }