diff --git a/swap/src/alice.rs b/swap/src/alice.rs index b419f5a9..52ae7cc4 100644 --- a/swap/src/alice.rs +++ b/swap/src/alice.rs @@ -75,7 +75,7 @@ pub async fn swap( // to `ConstantBackoff`. #[async_trait] impl ReceiveBitcoinRedeemEncsig for Network { - async fn receive_bitcoin_redeem_encsig(&mut self) -> xmr_btc::bitcoin::EncryptedSignature { + async fn receive_bitcoin_redeem_encsig(&mut self) -> bitcoin::EncryptedSignature { #[derive(Debug)] struct UnexpectedMessage; diff --git a/swap/src/bitcoin.rs b/swap/src/bitcoin.rs index 2d88ae2c..15c1e76b 100644 --- a/swap/src/bitcoin.rs +++ b/swap/src/bitcoin.rs @@ -8,13 +8,13 @@ use bitcoin_harness::bitcoind_rpc::PsbtBase64; use reqwest::Url; use tokio::time; use xmr_btc::bitcoin::{ - Amount, BlockHeight, BroadcastSignedTransaction, BuildTxLockPsbt, SignTxLock, - TransactionBlockHeight, TxLock, Txid, WatchForRawTransaction, + BlockHeight, BroadcastSignedTransaction, BuildTxLockPsbt, SignTxLock, TransactionBlockHeight, + WatchForRawTransaction, }; -pub const TX_LOCK_MINE_TIMEOUT: u64 = 3600; +pub use xmr_btc::bitcoin::*; -// This is cut'n'paste from xmr_btc/tests/harness/wallet/bitcoin.rs +pub const TX_LOCK_MINE_TIMEOUT: u64 = 3600; #[derive(Debug)] pub struct Wallet(pub bitcoin_harness::Wallet); diff --git a/swap/src/lib.rs b/swap/src/lib.rs index 9039aa74..cdc8673f 100644 --- a/swap/src/lib.rs +++ b/swap/src/lib.rs @@ -34,10 +34,10 @@ pub enum Rsp { pub struct SwapAmounts { /// Amount of BTC to swap. #[serde(with = "::bitcoin::util::amount::serde::as_sat")] - pub btc: ::bitcoin::Amount, + pub btc: bitcoin::Amount, /// Amount of XMR to swap. #[serde(with = "xmr_btc::serde::monero_amount")] - pub xmr: xmr_btc::monero::Amount, + pub xmr: monero::Amount, } // TODO: Display in XMR and BTC (not picos and sats). diff --git a/swap/src/monero.rs b/swap/src/monero.rs index eb9f9bbc..7d252b69 100644 --- a/swap/src/monero.rs +++ b/swap/src/monero.rs @@ -1,15 +1,11 @@ use anyhow::Result; use async_trait::async_trait; use backoff::{backoff::Constant as ConstantBackoff, future::FutureOperation as _}; -use monero::{Address, Network, PrivateKey}; use monero_harness::rpc::wallet; use std::{str::FromStr, time::Duration}; - use url::Url; -pub use xmr_btc::monero::{ - Amount, CreateWalletForOutput, InsufficientFunds, PrivateViewKey, PublicKey, PublicViewKey, - Transfer, TransferProof, TxHash, WatchForTransfer, *, -}; + +pub use xmr_btc::monero::*; pub struct Wallet(pub wallet::Client); diff --git a/swap/src/recover.rs b/swap/src/recover.rs index 4cbfe54c..b71b31fd 100644 --- a/swap/src/recover.rs +++ b/swap/src/recover.rs @@ -11,6 +11,7 @@ //! was deemed too complicated for the time being. use crate::{ + bitcoin, monero, monero::CreateWalletForOutput, state::{Alice, Bob, Swap}, }; @@ -23,13 +24,13 @@ use futures::{ use sha2::Sha256; use tracing::info; use xmr_btc::bitcoin::{ - poll_until_block_height_is_gte, BroadcastSignedTransaction, TransactionBlockHeight, TxCancel, - TxPunish, TxRedeem, TxRefund, WatchForRawTransaction, + poll_until_block_height_is_gte, BroadcastSignedTransaction, TransactionBlockHeight, + WatchForRawTransaction, }; pub async fn recover( - bitcoin_wallet: crate::bitcoin::Wallet, - monero_wallet: crate::monero::Wallet, + bitcoin_wallet: bitcoin::Wallet, + monero_wallet: monero::Wallet, state: Swap, ) -> Result<()> { match state { @@ -39,8 +40,8 @@ pub async fn recover( } pub async fn alice_recover( - bitcoin_wallet: crate::bitcoin::Wallet, - monero_wallet: crate::monero::Wallet, + bitcoin_wallet: bitcoin::Wallet, + monero_wallet: monero::Wallet, state: Alice, ) -> Result<()> { match state { @@ -50,7 +51,7 @@ pub async fn alice_recover( Alice::XmrLocked(state) => { info!("Monero still locked up"); - let tx_cancel = TxCancel::new( + let tx_cancel = bitcoin::TxCancel::new( &state.tx_lock, state.refund_timelock, state.a.public(), @@ -104,7 +105,7 @@ pub async fn alice_recover( ); pin_mut!(poll_until_bob_can_be_punished); - let tx_refund = TxRefund::new(&tx_cancel, &state.refund_address); + let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &state.refund_address); info!("Waiting for either Bitcoin refund or punish timelock"); match select( @@ -126,13 +127,9 @@ pub async fn alice_recover( .a .encsign(state.S_b_bitcoin.clone(), tx_refund.digest()); - let s_b = xmr_btc::bitcoin::recover( - state.S_b_bitcoin, - tx_refund_sig, - tx_refund_encsig, - )?; + let s_b = bitcoin::recover(state.S_b_bitcoin, tx_refund_sig, tx_refund_encsig)?; let s_b = monero::PrivateKey::from_scalar( - xmr_btc::monero::Scalar::from_bytes_mod_order(s_b.to_bytes()), + monero::Scalar::from_bytes_mod_order(s_b.to_bytes()), ); monero_wallet @@ -143,8 +140,11 @@ pub async fn alice_recover( Either::Right(_) => { info!("Punish timelock reached, attempting to punish Bob"); - let tx_punish = - TxPunish::new(&tx_cancel, &state.punish_address, state.punish_timelock); + let tx_punish = bitcoin::TxPunish::new( + &tx_cancel, + &state.punish_address, + state.punish_timelock, + ); let sig_a = state.a.sign(tx_punish.digest()); let sig_b = state.tx_punish_sig_bob.clone(); @@ -183,7 +183,7 @@ pub async fn alice_recover( } else { info!("Refund timelock reached"); - let tx_cancel = TxCancel::new( + let tx_cancel = bitcoin::TxCancel::new( &state.tx_lock, state.refund_timelock, state.a.public(), @@ -226,7 +226,7 @@ pub async fn alice_recover( ); pin_mut!(poll_until_bob_can_be_punished); - let tx_refund = TxRefund::new(&tx_cancel, &state.refund_address); + let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &state.refund_address); info!("Waiting for either Bitcoin refund or punish timelock"); match select( @@ -248,13 +248,10 @@ pub async fn alice_recover( .a .encsign(state.S_b_bitcoin.clone(), tx_refund.digest()); - let s_b = xmr_btc::bitcoin::recover( - state.S_b_bitcoin, - tx_refund_sig, - tx_refund_encsig, - )?; + let s_b = + bitcoin::recover(state.S_b_bitcoin, tx_refund_sig, tx_refund_encsig)?; let s_b = monero::PrivateKey::from_scalar( - xmr_btc::monero::Scalar::from_bytes_mod_order(s_b.to_bytes()), + monero::Scalar::from_bytes_mod_order(s_b.to_bytes()), ); monero_wallet @@ -265,8 +262,11 @@ pub async fn alice_recover( Either::Right(_) => { info!("Punish timelock reached, attempting to punish Bob"); - let tx_punish = - TxPunish::new(&tx_cancel, &state.punish_address, state.punish_timelock); + let tx_punish = bitcoin::TxPunish::new( + &tx_cancel, + &state.punish_address, + state.punish_timelock, + ); let sig_a = state.a.sign(tx_punish.digest()); let sig_b = state.tx_punish_sig_bob.clone(); @@ -288,13 +288,13 @@ pub async fn alice_recover( Alice::BtcPunishable(state) => { info!("Punish timelock reached, attempting to punish Bob"); - let tx_cancel = TxCancel::new( + let tx_cancel = bitcoin::TxCancel::new( &state.tx_lock, state.refund_timelock, state.a.public(), state.B.clone(), ); - let tx_refund = TxRefund::new(&tx_cancel, &state.refund_address); + let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &state.refund_address); info!("Checking if Bitcoin has already been refunded"); @@ -314,13 +314,9 @@ pub async fn alice_recover( .a .encsign(state.S_b_bitcoin.clone(), tx_refund.digest()); - let s_b = xmr_btc::bitcoin::recover( - state.S_b_bitcoin, - tx_refund_sig, - tx_refund_encsig, - )?; + let s_b = bitcoin::recover(state.S_b_bitcoin, tx_refund_sig, tx_refund_encsig)?; let s_b = monero::PrivateKey::from_scalar( - xmr_btc::monero::Scalar::from_bytes_mod_order(s_b.to_bytes()), + monero::Scalar::from_bytes_mod_order(s_b.to_bytes()), ); monero_wallet @@ -331,8 +327,11 @@ pub async fn alice_recover( Err(_) => { info!("Bitcoin not yet refunded"); - let tx_punish = - TxPunish::new(&tx_cancel, &state.punish_address, state.punish_timelock); + let tx_punish = bitcoin::TxPunish::new( + &tx_cancel, + &state.punish_address, + state.punish_timelock, + ); let sig_a = state.a.sign(tx_punish.digest()); let sig_b = state.tx_punish_sig_bob.clone(); @@ -379,7 +378,7 @@ pub async fn bob_recover( Bob::BtcLocked(state) | Bob::XmrLocked(state) | Bob::BtcRefundable(state) => { info!("Bitcoin may still be locked up, attempting to refund"); - let tx_cancel = TxCancel::new( + let tx_cancel = bitcoin::TxCancel::new( &state.tx_lock, state.refund_timelock, state.A.clone(), @@ -420,10 +419,11 @@ pub async fn bob_recover( bitcoin_wallet .broadcast_signed_transaction(tx_cancel) .await?; - info!("Successfully published Bitcoin cancel transaction"); } - let tx_refund = TxRefund::new(&tx_cancel, &state.refund_address); + info!("Confirmed that Bitcoin cancel transaction is on the blockchain"); + + let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &state.refund_address); let signed_tx_refund = { let adaptor = Adaptor::>::default(); let sig_a = adaptor @@ -449,7 +449,7 @@ pub async fn bob_recover( Bob::BtcRedeemed(state) => { info!("Bitcoin was redeemed, attempting to redeem monero"); - let tx_redeem = TxRedeem::new(&state.tx_lock, &state.redeem_address); + let tx_redeem = bitcoin::TxRedeem::new(&state.tx_lock, &state.redeem_address); let tx_redeem_published = bitcoin_wallet .0 .get_raw_transaction(tx_redeem.txid()) @@ -461,11 +461,10 @@ pub async fn bob_recover( let tx_redeem_sig = tx_redeem.extract_signature_by_key(tx_redeem_published, state.b.public())?; - let s_a = - xmr_btc::bitcoin::recover(state.S_a_bitcoin, tx_redeem_sig, tx_redeem_encsig)?; - let s_a = monero::PrivateKey::from_scalar( - xmr_btc::monero::Scalar::from_bytes_mod_order(s_a.to_bytes()), - ); + let s_a = bitcoin::recover(state.S_a_bitcoin, tx_redeem_sig, tx_redeem_encsig)?; + let s_a = monero::PrivateKey::from_scalar(monero::Scalar::from_bytes_mod_order( + s_a.to_bytes(), + )); let s_b = monero::PrivateKey { scalar: state.s_b.into_ed25519(), diff --git a/swap/tests/e2e.rs b/swap/tests/e2e.rs index d17ca0db..358657ca 100644 --- a/swap/tests/e2e.rs +++ b/swap/tests/e2e.rs @@ -6,6 +6,7 @@ use std::sync::Arc; use swap::{alice, bob, network::transport::build, storage::Database}; use tempfile::tempdir; use testcontainers::clients::Cli; +use xmr_btc::bitcoin; // NOTE: For some reason running these tests overflows the stack. In order to // mitigate this run them with: @@ -114,7 +115,7 @@ async fn swap() { assert_eq!( btc_alice_final, - btc_alice + btc - bitcoin::Amount::from_sat(xmr_btc::bitcoin::TX_FEE) + btc_alice + btc - bitcoin::Amount::from_sat(bitcoin::TX_FEE) ); assert!(btc_bob_final <= btc_bob - btc); diff --git a/xmr-btc/src/bitcoin.rs b/xmr-btc/src/bitcoin.rs index e5e6ca6b..a095d64f 100644 --- a/xmr-btc/src/bitcoin.rs +++ b/xmr-btc/src/bitcoin.rs @@ -2,12 +2,7 @@ pub mod transactions; use anyhow::{anyhow, bail, Result}; use async_trait::async_trait; -use bitcoin::{ - hashes::{hex::ToHex, Hash}, - secp256k1, - util::psbt::PartiallySignedTransaction, - SigHash, -}; +use bitcoin::hashes::{hex::ToHex, Hash}; use ecdsa_fun::{adaptor::Adaptor, fun::Point, nonce::Deterministic, ECDSA}; use miniscript::{Descriptor, Segwitv0}; use rand::{CryptoRng, RngCore}; @@ -15,9 +10,9 @@ use serde::{Deserialize, Serialize}; use sha2::Sha256; use std::str::FromStr; -pub use crate::bitcoin::transactions::{TxCancel, TxLock, TxPunish, TxRedeem, TxRefund}; -pub use bitcoin::{Address, Amount, OutPoint, Transaction, Txid}; +pub use bitcoin::{util::psbt::PartiallySignedTransaction, *}; pub use ecdsa_fun::{adaptor::EncryptedSignature, fun::Scalar, Signature}; +pub use transactions::{TxCancel, TxLock, TxPunish, TxRedeem, TxRefund}; pub const TX_FEE: u64 = 10_000; diff --git a/xmr-btc/src/monero.rs b/xmr-btc/src/monero.rs index ca55b904..643c4d32 100644 --- a/xmr-btc/src/monero.rs +++ b/xmr-btc/src/monero.rs @@ -1,12 +1,13 @@ use crate::serde::monero_private_key; use anyhow::Result; use async_trait::async_trait; -pub use curve25519_dalek::scalar::Scalar; -pub use monero::{Address, PrivateKey, PublicKey}; use rand::{CryptoRng, RngCore}; use serde::{Deserialize, Serialize}; use std::ops::{Add, Sub}; +pub use curve25519_dalek::scalar::Scalar; +pub use monero::*; + pub const MIN_CONFIRMATIONS: u32 = 10; pub fn random_private_key(rng: &mut R) -> PrivateKey { diff --git a/xmr-btc/tests/harness/wallet/monero.rs b/xmr-btc/tests/harness/wallet/monero.rs index 3cdc8a46..fbfd4270 100644 --- a/xmr-btc/tests/harness/wallet/monero.rs +++ b/xmr-btc/tests/harness/wallet/monero.rs @@ -1,12 +1,11 @@ use anyhow::Result; use async_trait::async_trait; use backoff::{backoff::Constant as ConstantBackoff, future::FutureOperation as _}; -use monero::{Address, Network, PrivateKey}; use monero_harness::rpc::wallet; use std::{str::FromStr, time::Duration}; use xmr_btc::monero::{ - Amount, CreateWalletForOutput, InsufficientFunds, PrivateViewKey, PublicKey, PublicViewKey, - Transfer, TransferProof, TxHash, WatchForTransfer, + Address, Amount, CreateWalletForOutput, InsufficientFunds, Network, PrivateKey, PrivateViewKey, + PublicKey, PublicViewKey, Transfer, TransferProof, TxHash, WatchForTransfer, }; pub struct Wallet(pub wallet::Client); diff --git a/xmr-btc/tests/on_chain.rs b/xmr-btc/tests/on_chain.rs index aa8adc61..459b368e 100644 --- a/xmr-btc/tests/on_chain.rs +++ b/xmr-btc/tests/on_chain.rs @@ -20,7 +20,7 @@ use tokio::sync::Mutex; use tracing::info; use xmr_btc::{ alice::{self, ReceiveBitcoinRedeemEncsig}, - bitcoin::{BroadcastSignedTransaction, EncryptedSignature, SignTxLock}, + bitcoin::{self, BroadcastSignedTransaction, EncryptedSignature, SignTxLock}, bob::{self, ReceiveTransferProof}, monero::{CreateWalletForOutput, Transfer, TransferProof}, }; @@ -309,8 +309,7 @@ async fn on_chain_happy_path() { assert_eq!( alice_final_btc_balance, - initial_balances.alice_btc + swap_amounts.btc - - bitcoin::Amount::from_sat(xmr_btc::bitcoin::TX_FEE) + initial_balances.alice_btc + swap_amounts.btc - bitcoin::Amount::from_sat(bitcoin::TX_FEE) ); assert_eq!( bob_final_btc_balance, @@ -411,7 +410,7 @@ async fn on_chain_both_refund_if_alice_never_redeems() { bob_final_btc_balance, // The 2 * TX_FEE corresponds to tx_refund and tx_cancel. initial_balances.bob_btc - - bitcoin::Amount::from_sat(2 * xmr_btc::bitcoin::TX_FEE) + - bitcoin::Amount::from_sat(2 * bitcoin::TX_FEE) - lock_tx_bitcoin_fee ); @@ -508,7 +507,7 @@ async fn on_chain_alice_punishes_if_bob_never_acts_after_fund() { assert_eq!( alice_final_btc_balance, initial_balances.alice_btc + swap_amounts.btc - - bitcoin::Amount::from_sat(2 * xmr_btc::bitcoin::TX_FEE) + - bitcoin::Amount::from_sat(2 * bitcoin::TX_FEE) ); assert_eq!( bob_final_btc_balance,