diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 955a24ee..08aed6ee 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -45,7 +45,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v2.4.0 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} @@ -67,7 +67,7 @@ jobs: run: target/${{ matrix.target }}/release/${{ matrix.bin }} --help # Remove once python 3 is the default - - uses: actions/setup-python@v2.2.2 + - uses: actions/setup-python@v2.3.1 with: python-version: '3.x' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1d4d341..46246c84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v2.4.0 - uses: Swatinem/rust-cache@v1.3.0 @@ -42,7 +42,7 @@ jobs: steps: - name: Checkout sources - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v2.4.0 - uses: Swatinem/rust-cache@v1.3.0 @@ -75,7 +75,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v2.4.0 - uses: Swatinem/rust-cache@v1.3.0 @@ -111,7 +111,7 @@ jobs: steps: - name: Checkout sources - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v2.4.0 - uses: Swatinem/rust-cache@v1.3.0 diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index ebe32ecb..ee95935f 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@v2.3.4 + - uses: actions/checkout@v2.4.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 c9a23801..bab5c85a 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@v2.3.4 + - uses: actions/checkout@v2.4.0 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index 65ecc775..a8207201 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@v2.3.4 + - uses: actions/checkout@v2.4.0 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 diff --git a/CHANGELOG.md b/CHANGELOG.md index 94fe4037..22df77e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- `monero-recovery` command that can be used to print the monero address, private spend and view key so one can manually recover instances where the `monero-wallet-rpc` does not pick up the Monero funds locked up by the ASB. + Related issue: https://github.com/comit-network/xmr-btc-swap/issues/537 + The command takes the swap-id as parameter. + The swap has to be in a `BtcRedeemed` state. + Use `--help` for more details. + ## [0.10.0] - 2021-10-15 ### Removed diff --git a/Cargo.lock b/Cargo.lock index a43d46ab..12b0f2eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -567,8 +567,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11e95a3e867422fd8d04049041f5671f94d53c32a9dcd82e2be268714942f3f3" dependencies = [ "crossterm", - "strum", - "strum_macros", + "strum 0.21.0", + "strum_macros 0.21.0", "unicode-width", ] @@ -1335,9 +1335,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "825343c4eef0b63f541f8903f395dc5beb362a979b5799a84062527ef1e37726" +checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd" dependencies = [ "bytes", "fnv", @@ -1493,9 +1493,9 @@ checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9" [[package]] name = "hyper" -version = "0.14.13" +version = "0.14.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593" +checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" dependencies = [ "bytes", "futures-channel", @@ -2551,9 +2551,9 @@ dependencies = [ [[package]] name = "pem" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2373df5233932a893d3bc2c78a0bf3f6d12590a1edd546b4fbefcac32c5c0f" +checksum = "06673860db84d02a63942fa69cd9543f2624a5df3aea7f33173048fa7ad5cf1a" dependencies = [ "base64 0.13.0", "once_cell", @@ -3907,8 +3907,14 @@ name = "strum" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2" + +[[package]] +name = "strum" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" dependencies = [ - "strum_macros", + "strum_macros 0.23.0", ] [[package]] @@ -3923,6 +3929,19 @@ dependencies = [ "syn", ] +[[package]] +name = "strum_macros" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00ad150e9d51e33e8142984f577662c1324d49f3be45ed37bac8645fdcbe0fe5" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "subtle" version = "2.4.0" @@ -3986,7 +4005,7 @@ dependencies = [ "spectral", "sqlx", "structopt", - "strum", + "strum 0.23.0", "tempfile", "testcontainers 0.12.0", "thiserror", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 3c7c9f31..4ccb0954 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -50,7 +50,7 @@ sha2 = "0.9" sigma_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = false, features = [ "ed25519", "serde" ] } sqlx = { version = "0.5", features = [ "sqlite", "runtime-tokio-rustls", "offline" ] } structopt = "0.3" -strum = { version = "0.21", features = [ "derive" ] } +strum = { version = "0.23", features = [ "derive" ] } thiserror = "1" time = "0.3" tokio = { version = "1", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs", "net" ] } diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index 5bbe4ba2..efb8ad8b 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -12,7 +12,7 @@ #![forbid(unsafe_code)] #![allow(non_snake_case)] -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Result}; use comfy_table::Table; use qrcode::render::unicode; use qrcode::QrCode; @@ -438,6 +438,43 @@ async fn main() -> Result<()> { let wallet_export = bitcoin_wallet.wallet_export("cli").await?; tracing::info!(descriptor=%wallet_export.to_string(), "Exported bitcoin wallet"); } + Command::MoneroRecovery { swap_id } => { + let db = open_db(data_dir.join("sqlite")).await?; + + let swap_state: BobState = db.get_state(swap_id).await?.try_into()?; + + match swap_state { + BobState::Started { .. } + | BobState::SwapSetupCompleted(_) + | BobState::BtcLocked(_) + | BobState::XmrLockProofReceived { .. } + | BobState::XmrLocked(_) + | BobState::EncSigSent(_) + | BobState::CancelTimelockExpired(_) + | BobState::BtcCancelled(_) + | BobState::BtcRefunded(_) + | BobState::BtcPunished { .. } + | BobState::SafelyAborted + | BobState::XmrRedeemed { .. } => { + bail!("Cannot print monero recovery information in state {}, only possible for BtcRedeemed", swap_state) + } + BobState::BtcRedeemed(state5) => { + let (spend_key, view_key) = state5.xmr_keys(); + + let address = monero::Address::standard( + env_config.monero_network, + monero::PublicKey::from_private_key(&spend_key), + monero::PublicKey::from(view_key.public()), + ); + tracing::info!("Wallet address: {}", address.to_string()); + + let view_key = serde_json::to_string(&view_key)?; + println!("View key: {}", view_key); + + println!("Spend key: {}", spend_key); + } + } + } }; Ok(()) } diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index ccb46fa2..f2d57ceb 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -249,6 +249,15 @@ where }, } } + RawCommand::MoneroRecovery { swap_id } => Arguments { + env_config: env_config_from(is_testnet), + debug, + json, + data_dir: data::data_dir_from(data, is_testnet)?, + cmd: Command::MoneroRecovery { + swap_id: swap_id.swap_id, + }, + }, }; Ok(ParseResult::Arguments(arguments)) @@ -303,6 +312,9 @@ pub enum Command { bitcoin_electrum_rpc_url: Url, bitcoin_target_block: usize, }, + MoneroRecovery { + swap_id: Uuid, + }, } #[derive(structopt::StructOpt, Debug)] @@ -439,6 +451,13 @@ enum RawCommand { #[structopt(flatten)] bitcoin: Bitcoin, }, + /// Prints Monero information related to the swap in case the generated + /// wallet fails to detect the funds. This can only be used for swaps + /// that are in a `btc is redeemed` state. + MoneroRecovery { + #[structopt(flatten)] + swap_id: SwapId, + }, } #[derive(structopt::StructOpt, Debug)]