xmr-btc-swap/swap/tests/punish.rs
Franck Royer 1a4bd0e2b4
Bob refunds swap after restart that requires communication
As Bob is dialing Alice, we now ensure that we are connected to Alice
at each step that needs communication.
If we are not connected, we proceed with dialing.

In an attempt to improve libp2p usage, we also add known address of
Alice first and only use peer_id to dial.
This ensures that we use the expected peer id.
2020-12-21 08:31:21 +11:00

130 lines
3.7 KiB
Rust

use crate::testutils::{init_alice, init_bob};
use futures::future::try_join;
use get_port::get_port;
use libp2p::Multiaddr;
use rand::rngs::OsRng;
use swap::{alice, alice::swap::AliceState, bob, bob::swap::BobState};
use testcontainers::clients::Cli;
use testutils::init_tracing;
use uuid::Uuid;
use xmr_btc::{bitcoin, config::Config};
pub mod testutils;
/// Bob locks Btc and Alice locks Xmr. Bob does not act; he fails to send Alice
/// the encsig and fail to refund or redeem. Alice punishes.
#[tokio::test]
async fn alice_punishes_if_bob_never_acts_after_fund() {
let _guard = init_tracing();
let cli = Cli::default();
let (
monero,
testutils::Containers {
bitcoind,
monerods: _monerods,
},
) = testutils::init_containers(&cli).await;
let btc_to_swap = bitcoin::Amount::from_sat(1_000_000);
let xmr_to_swap = xmr_btc::monero::Amount::from_piconero(1_000_000_000_000);
let bob_btc_starting_balance = btc_to_swap * 10;
let alice_btc_starting_balance = bitcoin::Amount::ZERO;
let alice_xmr_starting_balance = xmr_to_swap * 10;
let port = get_port().expect("Failed to find a free port");
let alice_multiaddr: Multiaddr = format!("/ip4/127.0.0.1/tcp/{}", port)
.parse()
.expect("failed to parse Alice's address");
let config = Config::regtest();
let (
alice_state,
mut alice_event_loop,
alice_event_loop_handle,
alice_btc_wallet,
alice_xmr_wallet,
alice_db,
) = init_alice(
&bitcoind,
&monero,
btc_to_swap,
xmr_to_swap,
alice_xmr_starting_balance,
alice_multiaddr.clone(),
config,
)
.await;
let (bob_state, bob_event_loop, bob_event_loop_handle, bob_btc_wallet, bob_xmr_wallet, bob_db) =
init_bob(
alice_multiaddr,
alice_event_loop.peer_id(),
&bitcoind,
&monero,
btc_to_swap,
bob_btc_starting_balance,
xmr_to_swap,
config,
)
.await;
let bob_btc_locked_fut = bob::swap::run_until(
bob_state,
bob::swap::is_btc_locked,
bob_event_loop_handle,
bob_db,
bob_btc_wallet.clone(),
bob_xmr_wallet.clone(),
OsRng,
Uuid::new_v4(),
);
let _bob_swarm_fut = tokio::spawn(async move { bob_event_loop.run().await });
let alice_fut = alice::swap::swap(
alice_state,
alice_event_loop_handle,
alice_btc_wallet.clone(),
alice_xmr_wallet.clone(),
Config::regtest(),
Uuid::new_v4(),
alice_db,
);
let _alice_swarm_fut = tokio::spawn(async move { alice_event_loop.run().await });
// Wait until alice has locked xmr and bob has locked btc
let (alice_state, bob_state) = try_join(alice_fut, bob_btc_locked_fut).await.unwrap();
assert!(matches!(alice_state, AliceState::Punished));
let bob_state3 = if let BobState::BtcLocked(state3, ..) = bob_state {
state3
} else {
panic!("Bob in unexpected state");
};
let btc_alice_final = alice_btc_wallet.as_ref().balance().await.unwrap();
let btc_bob_final = bob_btc_wallet.as_ref().balance().await.unwrap();
// lock_tx_bitcoin_fee is determined by the wallet, it is not necessarily equal
// to TX_FEE
let lock_tx_bitcoin_fee = bob_btc_wallet
.transaction_fee(bob_state3.tx_lock_id())
.await
.unwrap();
assert_eq!(
btc_alice_final,
alice_btc_starting_balance + btc_to_swap - bitcoin::Amount::from_sat(2 * bitcoin::TX_FEE)
);
assert_eq!(
btc_bob_final,
bob_btc_starting_balance - btc_to_swap - lock_tx_bitcoin_fee
);
}