mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Merge pull request #68 from comit-network/ci-time
Improve CI execution time
This commit is contained in:
commit
8f5eac8201
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@ -77,6 +77,7 @@ jobs:
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
profile: minimal
|
||||
override: true
|
||||
|
||||
@ -94,14 +95,14 @@ jobs:
|
||||
key: rust-${{ matrix.target }}-${{ matrix.rust_toolchain }}-cargo-registry-directory-${{ hashFiles('Cargo.lock') }}-v1
|
||||
|
||||
- name: Cargo check release code with default features
|
||||
run: cargo check --workspace
|
||||
run: cargo +nightly check --workspace
|
||||
|
||||
- name: Cargo check all features
|
||||
run: cargo check --workspace --all-targets --all-features
|
||||
run: cargo +nightly check --workspace --all-targets --all-features
|
||||
|
||||
- name: Cargo test
|
||||
if: (!matrix.skip_tests)
|
||||
run: cargo test --workspace --all-features
|
||||
run: cargo +nightly test --workspace --all-features -- -Z unstable-options --report-time
|
||||
env:
|
||||
MONERO_ADDITIONAL_SLEEP_PERIOD: 60000
|
||||
RUST_MIN_STACK: 10000000
|
||||
|
@ -118,8 +118,8 @@ impl<'c> Monero {
|
||||
|
||||
// generate the first 70 as bulk
|
||||
let monerod = &self.monerod;
|
||||
let block = monerod.client().generate_blocks(70, &miner_address).await?;
|
||||
tracing::info!("Generated {:?} blocks", block);
|
||||
let res = monerod.client().generate_blocks(70, &miner_address).await?;
|
||||
tracing::info!("Generated {:?} blocks", res.blocks.len());
|
||||
miner_wallet.refresh().await?;
|
||||
|
||||
for (wallet, amount) in wallet_amount.iter() {
|
||||
|
@ -14,86 +14,11 @@ mod tests {
|
||||
use std::convert::TryInto;
|
||||
use testcontainers::clients::Cli;
|
||||
use xmr_btc::{
|
||||
alice, bitcoin,
|
||||
alice,
|
||||
bitcoin::{Amount, TX_FEE},
|
||||
bob,
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn happy_path() {
|
||||
let cli = Cli::default();
|
||||
let (monero, _container) = Monero::new(&cli, Some("hp".to_string()), vec![
|
||||
"alice".to_string(),
|
||||
"bob".to_string(),
|
||||
])
|
||||
.await
|
||||
.unwrap();
|
||||
let bitcoind = init_bitcoind(&cli).await;
|
||||
|
||||
let (
|
||||
alice_state0,
|
||||
bob_state0,
|
||||
mut alice_node,
|
||||
mut bob_node,
|
||||
initial_balances,
|
||||
swap_amounts,
|
||||
) = init_test(&monero, &bitcoind, None, None).await;
|
||||
|
||||
let (alice_state, bob_state) = future::try_join(
|
||||
run_alice_until(
|
||||
&mut alice_node,
|
||||
alice_state0.into(),
|
||||
harness::alice::is_state6,
|
||||
&mut OsRng,
|
||||
),
|
||||
run_bob_until(
|
||||
&mut bob_node,
|
||||
bob_state0.into(),
|
||||
harness::bob::is_state5,
|
||||
&mut OsRng,
|
||||
),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let alice_state6: alice::State6 = alice_state.try_into().unwrap();
|
||||
let bob_state5: bob::State5 = bob_state.try_into().unwrap();
|
||||
|
||||
let alice_final_btc_balance = alice_node.bitcoin_wallet.balance().await.unwrap();
|
||||
let bob_final_btc_balance = bob_node.bitcoin_wallet.balance().await.unwrap();
|
||||
|
||||
let lock_tx_bitcoin_fee = bob_node
|
||||
.bitcoin_wallet
|
||||
.transaction_fee(bob_state5.tx_lock_id())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let alice_final_xmr_balance = alice_node.monero_wallet.get_balance().await.unwrap();
|
||||
|
||||
monero.wallet("bob").unwrap().refresh().await.unwrap();
|
||||
|
||||
let bob_final_xmr_balance = bob_node.monero_wallet.get_balance().await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
alice_final_btc_balance,
|
||||
initial_balances.alice_btc + swap_amounts.btc
|
||||
- bitcoin::Amount::from_sat(bitcoin::TX_FEE)
|
||||
);
|
||||
assert_eq!(
|
||||
bob_final_btc_balance,
|
||||
initial_balances.bob_btc - swap_amounts.btc - lock_tx_bitcoin_fee
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
alice_final_xmr_balance,
|
||||
initial_balances.alice_xmr - swap_amounts.xmr - alice_state6.lock_xmr_fee()
|
||||
);
|
||||
assert_eq!(
|
||||
bob_final_xmr_balance,
|
||||
initial_balances.bob_xmr + swap_amounts.xmr
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn both_refund() {
|
||||
let cli = Cli::default();
|
||||
@ -170,71 +95,4 @@ mod tests {
|
||||
assert_eq!(alice_final_xmr_balance, swap_amounts.xmr);
|
||||
assert_eq!(bob_final_xmr_balance, initial_balances.bob_xmr);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn alice_punishes() {
|
||||
let cli = Cli::default();
|
||||
let (monero, _containers) = Monero::new(&cli, Some("ap".to_string()), vec![
|
||||
"alice".to_string(),
|
||||
"bob".to_string(),
|
||||
])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let bitcoind = init_bitcoind(&cli).await;
|
||||
|
||||
let (
|
||||
alice_state0,
|
||||
bob_state0,
|
||||
mut alice_node,
|
||||
mut bob_node,
|
||||
initial_balances,
|
||||
swap_amounts,
|
||||
) = init_test(&monero, &bitcoind, None, None).await;
|
||||
|
||||
let (alice_state, bob_state) = future::try_join(
|
||||
run_alice_until(
|
||||
&mut alice_node,
|
||||
alice_state0.into(),
|
||||
harness::alice::is_state4,
|
||||
&mut OsRng,
|
||||
),
|
||||
run_bob_until(
|
||||
&mut bob_node,
|
||||
bob_state0.into(),
|
||||
harness::bob::is_state3,
|
||||
&mut OsRng,
|
||||
),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let alice_state4: alice::State4 = alice_state.try_into().unwrap();
|
||||
let bob_state3: bob::State3 = bob_state.try_into().unwrap();
|
||||
|
||||
alice_state4
|
||||
.punish(&alice_node.bitcoin_wallet)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let alice_final_btc_balance = alice_node.bitcoin_wallet.balance().await.unwrap();
|
||||
let bob_final_btc_balance = bob_node.bitcoin_wallet.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_node
|
||||
.bitcoin_wallet
|
||||
.transaction_fee(bob_state3.tx_lock_id())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
alice_final_btc_balance,
|
||||
initial_balances.alice_btc + swap_amounts.btc - Amount::from_sat(2 * TX_FEE)
|
||||
);
|
||||
assert_eq!(
|
||||
bob_final_btc_balance,
|
||||
initial_balances.bob_btc - swap_amounts.btc - lock_tx_bitcoin_fee
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,521 +0,0 @@
|
||||
pub mod harness;
|
||||
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use futures::{
|
||||
channel::mpsc::{channel, Receiver, Sender},
|
||||
future::{select, try_join},
|
||||
pin_mut, SinkExt, StreamExt,
|
||||
};
|
||||
use genawaiter::GeneratorState;
|
||||
use harness::{
|
||||
init_bitcoind, init_test,
|
||||
node::{run_alice_until, run_bob_until},
|
||||
};
|
||||
use monero_harness::Monero;
|
||||
use rand::rngs::OsRng;
|
||||
use std::{convert::TryInto, sync::Arc};
|
||||
use testcontainers::clients::Cli;
|
||||
use tokio::sync::Mutex;
|
||||
use tracing::info;
|
||||
use xmr_btc::{
|
||||
alice::{self, ReceiveBitcoinRedeemEncsig},
|
||||
bitcoin::{self, BroadcastSignedTransaction, EncryptedSignature, SignTxLock},
|
||||
bob::{self, ReceiveTransferProof},
|
||||
monero::{CreateWalletForOutput, Transfer, TransferProof},
|
||||
};
|
||||
|
||||
/// Time given to Bob to get the Bitcoin lock transaction included in a block.
|
||||
const BITCOIN_TX_LOCK_TIMEOUT: u64 = 5;
|
||||
|
||||
type AliceNetwork = Network<EncryptedSignature>;
|
||||
type BobNetwork = Network<TransferProof>;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Network<M> {
|
||||
// TODO: It is weird to use mpsc's in a situation where only one message is expected, but the
|
||||
// ownership rules of Rust are making this painful
|
||||
pub receiver: Receiver<M>,
|
||||
}
|
||||
|
||||
impl<M> Network<M> {
|
||||
pub fn new() -> (Network<M>, Sender<M>) {
|
||||
let (sender, receiver) = channel(1);
|
||||
|
||||
(Self { receiver }, sender)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ReceiveTransferProof for BobNetwork {
|
||||
async fn receive_transfer_proof(&mut self) -> TransferProof {
|
||||
self.receiver.next().await.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ReceiveBitcoinRedeemEncsig for AliceNetwork {
|
||||
async fn receive_bitcoin_redeem_encsig(&mut self) -> EncryptedSignature {
|
||||
self.receiver.next().await.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
struct AliceBehaviour {
|
||||
lock_xmr: bool,
|
||||
redeem_btc: bool,
|
||||
cancel_btc: bool,
|
||||
punish_btc: bool,
|
||||
create_monero_wallet_for_output: bool,
|
||||
}
|
||||
|
||||
impl Default for AliceBehaviour {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
lock_xmr: true,
|
||||
redeem_btc: true,
|
||||
cancel_btc: true,
|
||||
punish_btc: true,
|
||||
create_monero_wallet_for_output: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct BobBehaviour {
|
||||
lock_btc: bool,
|
||||
send_btc_redeem_encsig: bool,
|
||||
create_monero_wallet_for_output: bool,
|
||||
cancel_btc: bool,
|
||||
refund_btc: bool,
|
||||
}
|
||||
|
||||
impl Default for BobBehaviour {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
lock_btc: true,
|
||||
send_btc_redeem_encsig: true,
|
||||
create_monero_wallet_for_output: true,
|
||||
cancel_btc: true,
|
||||
refund_btc: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn swap_as_alice(
|
||||
network: Arc<Mutex<AliceNetwork>>,
|
||||
// FIXME: It would be more intuitive to have a single network/transport struct instead of
|
||||
// splitting into two, but Rust ownership rules make this tedious
|
||||
mut sender: Sender<TransferProof>,
|
||||
monero_wallet: Arc<harness::wallet::monero::Wallet>,
|
||||
bitcoin_wallet: Arc<harness::wallet::bitcoin::Wallet>,
|
||||
behaviour: AliceBehaviour,
|
||||
state: alice::State3,
|
||||
) -> Result<()> {
|
||||
let mut action_generator = alice::action_generator(
|
||||
network,
|
||||
bitcoin_wallet.clone(),
|
||||
state,
|
||||
BITCOIN_TX_LOCK_TIMEOUT,
|
||||
);
|
||||
|
||||
loop {
|
||||
let state = action_generator.async_resume().await;
|
||||
|
||||
info!("resumed execution of alice generator, got: {:?}", state);
|
||||
|
||||
match state {
|
||||
GeneratorState::Yielded(alice::Action::LockXmr {
|
||||
amount,
|
||||
public_spend_key,
|
||||
public_view_key,
|
||||
}) => {
|
||||
if behaviour.lock_xmr {
|
||||
let (transfer_proof, _) = monero_wallet
|
||||
.transfer(public_spend_key, public_view_key, amount)
|
||||
.await?;
|
||||
|
||||
sender.send(transfer_proof).await?;
|
||||
}
|
||||
}
|
||||
GeneratorState::Yielded(alice::Action::RedeemBtc(tx)) => {
|
||||
if behaviour.redeem_btc {
|
||||
let _ = bitcoin_wallet.broadcast_signed_transaction(tx).await?;
|
||||
}
|
||||
}
|
||||
GeneratorState::Yielded(alice::Action::CancelBtc(tx)) => {
|
||||
if behaviour.cancel_btc {
|
||||
let _ = bitcoin_wallet.broadcast_signed_transaction(tx).await?;
|
||||
}
|
||||
}
|
||||
GeneratorState::Yielded(alice::Action::PunishBtc(tx)) => {
|
||||
if behaviour.punish_btc {
|
||||
let _ = bitcoin_wallet.broadcast_signed_transaction(tx).await?;
|
||||
}
|
||||
}
|
||||
GeneratorState::Yielded(alice::Action::CreateMoneroWalletForOutput {
|
||||
spend_key,
|
||||
view_key,
|
||||
}) => {
|
||||
if behaviour.create_monero_wallet_for_output {
|
||||
monero_wallet
|
||||
.create_and_load_wallet_for_output(spend_key, view_key)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
GeneratorState::Complete(()) => return Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn swap_as_bob(
|
||||
network: Arc<Mutex<BobNetwork>>,
|
||||
mut sender: Sender<EncryptedSignature>,
|
||||
monero_wallet: Arc<harness::wallet::monero::Wallet>,
|
||||
bitcoin_wallet: Arc<harness::wallet::bitcoin::Wallet>,
|
||||
behaviour: BobBehaviour,
|
||||
state: bob::State2,
|
||||
) -> Result<()> {
|
||||
let mut action_generator = bob::action_generator(
|
||||
network,
|
||||
monero_wallet.clone(),
|
||||
bitcoin_wallet.clone(),
|
||||
state,
|
||||
BITCOIN_TX_LOCK_TIMEOUT,
|
||||
);
|
||||
|
||||
loop {
|
||||
let state = action_generator.async_resume().await;
|
||||
|
||||
info!("resumed execution of bob generator, got: {:?}", state);
|
||||
|
||||
match state {
|
||||
GeneratorState::Yielded(bob::Action::LockBtc(tx_lock)) => {
|
||||
if behaviour.lock_btc {
|
||||
let signed_tx_lock = bitcoin_wallet.sign_tx_lock(tx_lock).await?;
|
||||
let _ = bitcoin_wallet
|
||||
.broadcast_signed_transaction(signed_tx_lock)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
GeneratorState::Yielded(bob::Action::SendBtcRedeemEncsig(tx_redeem_encsig)) => {
|
||||
if behaviour.send_btc_redeem_encsig {
|
||||
sender.send(tx_redeem_encsig).await.unwrap();
|
||||
}
|
||||
}
|
||||
GeneratorState::Yielded(bob::Action::CreateXmrWalletForOutput {
|
||||
spend_key,
|
||||
view_key,
|
||||
}) => {
|
||||
if behaviour.create_monero_wallet_for_output {
|
||||
monero_wallet
|
||||
.create_and_load_wallet_for_output(spend_key, view_key)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
GeneratorState::Yielded(bob::Action::CancelBtc(tx_cancel)) => {
|
||||
if behaviour.cancel_btc {
|
||||
let _ = bitcoin_wallet
|
||||
.broadcast_signed_transaction(tx_cancel)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
GeneratorState::Yielded(bob::Action::RefundBtc(tx_refund)) => {
|
||||
if behaviour.refund_btc {
|
||||
let _ = bitcoin_wallet
|
||||
.broadcast_signed_transaction(tx_refund)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
GeneratorState::Complete(()) => return Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn on_chain_happy_path() {
|
||||
let cli = Cli::default();
|
||||
let (monero, _container) = Monero::new(&cli, Some("ochp".to_string()), vec![
|
||||
"alice".to_string(),
|
||||
"bob".to_string(),
|
||||
])
|
||||
.await
|
||||
.unwrap();
|
||||
let bitcoind = init_bitcoind(&cli).await;
|
||||
|
||||
let (alice_state0, bob_state0, mut alice_node, mut bob_node, initial_balances, swap_amounts) =
|
||||
init_test(&monero, &bitcoind, Some(100), Some(100)).await;
|
||||
|
||||
// run the handshake as part of the setup
|
||||
let (alice_state, bob_state) = try_join(
|
||||
run_alice_until(
|
||||
&mut alice_node,
|
||||
alice_state0.into(),
|
||||
harness::alice::is_state3,
|
||||
&mut OsRng,
|
||||
),
|
||||
run_bob_until(
|
||||
&mut bob_node,
|
||||
bob_state0.into(),
|
||||
harness::bob::is_state2,
|
||||
&mut OsRng,
|
||||
),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let alice: alice::State3 = alice_state.try_into().unwrap();
|
||||
let bob: bob::State2 = bob_state.try_into().unwrap();
|
||||
let tx_lock_txid = bob.tx_lock.txid();
|
||||
|
||||
let alice_bitcoin_wallet = Arc::new(alice_node.bitcoin_wallet);
|
||||
let bob_bitcoin_wallet = Arc::new(bob_node.bitcoin_wallet);
|
||||
let alice_monero_wallet = Arc::new(alice_node.monero_wallet);
|
||||
let bob_monero_wallet = Arc::new(bob_node.monero_wallet);
|
||||
|
||||
let (alice_network, bob_sender) = Network::<EncryptedSignature>::new();
|
||||
let (bob_network, alice_sender) = Network::<TransferProof>::new();
|
||||
|
||||
try_join(
|
||||
swap_as_alice(
|
||||
Arc::new(Mutex::new(alice_network)),
|
||||
alice_sender,
|
||||
alice_monero_wallet.clone(),
|
||||
alice_bitcoin_wallet.clone(),
|
||||
AliceBehaviour::default(),
|
||||
alice,
|
||||
),
|
||||
swap_as_bob(
|
||||
Arc::new(Mutex::new(bob_network)),
|
||||
bob_sender,
|
||||
bob_monero_wallet.clone(),
|
||||
bob_bitcoin_wallet.clone(),
|
||||
BobBehaviour::default(),
|
||||
bob,
|
||||
),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let alice_final_btc_balance = alice_bitcoin_wallet.balance().await.unwrap();
|
||||
let bob_final_btc_balance = bob_bitcoin_wallet.balance().await.unwrap();
|
||||
|
||||
let lock_tx_bitcoin_fee = bob_bitcoin_wallet
|
||||
.transaction_fee(tx_lock_txid)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let alice_final_xmr_balance = alice_monero_wallet.get_balance().await.unwrap();
|
||||
|
||||
monero.wallet("bob").unwrap().refresh().await.unwrap();
|
||||
let bob_final_xmr_balance = bob_monero_wallet.get_balance().await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
alice_final_btc_balance,
|
||||
initial_balances.alice_btc + swap_amounts.btc - bitcoin::Amount::from_sat(bitcoin::TX_FEE)
|
||||
);
|
||||
assert_eq!(
|
||||
bob_final_btc_balance,
|
||||
initial_balances.bob_btc - swap_amounts.btc - lock_tx_bitcoin_fee
|
||||
);
|
||||
|
||||
// Getting the Monero LockTx fee is tricky in a clean way, I think checking this
|
||||
// condition is sufficient
|
||||
assert!(alice_final_xmr_balance <= initial_balances.alice_xmr - swap_amounts.xmr);
|
||||
assert_eq!(
|
||||
bob_final_xmr_balance,
|
||||
initial_balances.bob_xmr + swap_amounts.xmr
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn on_chain_both_refund_if_alice_never_redeems() {
|
||||
let cli = Cli::default();
|
||||
let (monero, _container) = Monero::new(&cli, Some("ocbr".to_string()), vec![
|
||||
"alice".to_string(),
|
||||
"bob".to_string(),
|
||||
])
|
||||
.await
|
||||
.unwrap();
|
||||
let bitcoind = init_bitcoind(&cli).await;
|
||||
|
||||
let (alice_state0, bob_state0, mut alice_node, mut bob_node, initial_balances, swap_amounts) =
|
||||
init_test(&monero, &bitcoind, Some(10), Some(10)).await;
|
||||
|
||||
// run the handshake as part of the setup
|
||||
let (alice_state, bob_state) = try_join(
|
||||
run_alice_until(
|
||||
&mut alice_node,
|
||||
alice_state0.into(),
|
||||
harness::alice::is_state3,
|
||||
&mut OsRng,
|
||||
),
|
||||
run_bob_until(
|
||||
&mut bob_node,
|
||||
bob_state0.into(),
|
||||
harness::bob::is_state2,
|
||||
&mut OsRng,
|
||||
),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let alice: alice::State3 = alice_state.try_into().unwrap();
|
||||
let bob: bob::State2 = bob_state.try_into().unwrap();
|
||||
let tx_lock_txid = bob.tx_lock.txid();
|
||||
|
||||
let alice_bitcoin_wallet = Arc::new(alice_node.bitcoin_wallet);
|
||||
let bob_bitcoin_wallet = Arc::new(bob_node.bitcoin_wallet);
|
||||
let alice_monero_wallet = Arc::new(alice_node.monero_wallet);
|
||||
let bob_monero_wallet = Arc::new(bob_node.monero_wallet);
|
||||
|
||||
let (alice_network, bob_sender) = Network::<EncryptedSignature>::new();
|
||||
let (bob_network, alice_sender) = Network::<TransferProof>::new();
|
||||
|
||||
try_join(
|
||||
swap_as_alice(
|
||||
Arc::new(Mutex::new(alice_network)),
|
||||
alice_sender,
|
||||
alice_monero_wallet.clone(),
|
||||
alice_bitcoin_wallet.clone(),
|
||||
AliceBehaviour {
|
||||
redeem_btc: false,
|
||||
..Default::default()
|
||||
},
|
||||
alice,
|
||||
),
|
||||
swap_as_bob(
|
||||
Arc::new(Mutex::new(bob_network)),
|
||||
bob_sender,
|
||||
bob_monero_wallet.clone(),
|
||||
bob_bitcoin_wallet.clone(),
|
||||
BobBehaviour::default(),
|
||||
bob,
|
||||
),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let alice_final_btc_balance = alice_bitcoin_wallet.balance().await.unwrap();
|
||||
let bob_final_btc_balance = bob_bitcoin_wallet.balance().await.unwrap();
|
||||
|
||||
let lock_tx_bitcoin_fee = bob_bitcoin_wallet
|
||||
.transaction_fee(tx_lock_txid)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
monero.wallet("alice").unwrap().refresh().await.unwrap();
|
||||
let alice_final_xmr_balance = alice_monero_wallet.get_balance().await.unwrap();
|
||||
|
||||
let bob_final_xmr_balance = bob_monero_wallet.get_balance().await.unwrap();
|
||||
|
||||
assert_eq!(alice_final_btc_balance, initial_balances.alice_btc);
|
||||
assert_eq!(
|
||||
bob_final_btc_balance,
|
||||
// The 2 * TX_FEE corresponds to tx_refund and tx_cancel.
|
||||
initial_balances.bob_btc
|
||||
- bitcoin::Amount::from_sat(2 * bitcoin::TX_FEE)
|
||||
- lock_tx_bitcoin_fee
|
||||
);
|
||||
|
||||
// Because we create a new wallet when claiming Monero, we can only assert on
|
||||
// this new wallet owning all of `xmr_amount` after refund
|
||||
assert_eq!(alice_final_xmr_balance, swap_amounts.xmr);
|
||||
assert_eq!(bob_final_xmr_balance, initial_balances.bob_xmr);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn on_chain_alice_punishes_if_bob_never_acts_after_fund() {
|
||||
let cli = Cli::default();
|
||||
let (monero, _container) = Monero::new(&cli, Some("ocap".to_string()), vec![
|
||||
"alice".to_string(),
|
||||
"bob".to_string(),
|
||||
])
|
||||
.await
|
||||
.unwrap();
|
||||
let bitcoind = init_bitcoind(&cli).await;
|
||||
|
||||
let (alice_state0, bob_state0, mut alice_node, mut bob_node, initial_balances, swap_amounts) =
|
||||
init_test(&monero, &bitcoind, Some(10), Some(10)).await;
|
||||
|
||||
// run the handshake as part of the setup
|
||||
let (alice_state, bob_state) = try_join(
|
||||
run_alice_until(
|
||||
&mut alice_node,
|
||||
alice_state0.into(),
|
||||
harness::alice::is_state3,
|
||||
&mut OsRng,
|
||||
),
|
||||
run_bob_until(
|
||||
&mut bob_node,
|
||||
bob_state0.into(),
|
||||
harness::bob::is_state2,
|
||||
&mut OsRng,
|
||||
),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let alice: alice::State3 = alice_state.try_into().unwrap();
|
||||
let bob: bob::State2 = bob_state.try_into().unwrap();
|
||||
let tx_lock_txid = bob.tx_lock.txid();
|
||||
|
||||
let alice_bitcoin_wallet = Arc::new(alice_node.bitcoin_wallet);
|
||||
let bob_bitcoin_wallet = Arc::new(bob_node.bitcoin_wallet);
|
||||
let alice_monero_wallet = Arc::new(alice_node.monero_wallet);
|
||||
let bob_monero_wallet = Arc::new(bob_node.monero_wallet);
|
||||
|
||||
let (alice_network, bob_sender) = Network::<EncryptedSignature>::new();
|
||||
let (bob_network, alice_sender) = Network::<TransferProof>::new();
|
||||
|
||||
let alice_swap = swap_as_alice(
|
||||
Arc::new(Mutex::new(alice_network)),
|
||||
alice_sender,
|
||||
alice_monero_wallet.clone(),
|
||||
alice_bitcoin_wallet.clone(),
|
||||
AliceBehaviour::default(),
|
||||
alice,
|
||||
);
|
||||
let bob_swap = swap_as_bob(
|
||||
Arc::new(Mutex::new(bob_network)),
|
||||
bob_sender,
|
||||
bob_monero_wallet.clone(),
|
||||
bob_bitcoin_wallet.clone(),
|
||||
BobBehaviour {
|
||||
send_btc_redeem_encsig: false,
|
||||
create_monero_wallet_for_output: false,
|
||||
cancel_btc: false,
|
||||
refund_btc: false,
|
||||
..Default::default()
|
||||
},
|
||||
bob,
|
||||
);
|
||||
|
||||
pin_mut!(alice_swap);
|
||||
pin_mut!(bob_swap);
|
||||
|
||||
// since we model Bob as inactive after locking bitcoin, his future does not
|
||||
// resolve, so we wait for one of the two (Alice's) to resolve via select
|
||||
select(alice_swap, bob_swap).await;
|
||||
|
||||
let alice_final_btc_balance = alice_bitcoin_wallet.balance().await.unwrap();
|
||||
let bob_final_btc_balance = bob_bitcoin_wallet.balance().await.unwrap();
|
||||
|
||||
let lock_tx_bitcoin_fee = bob_bitcoin_wallet
|
||||
.transaction_fee(tx_lock_txid)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let alice_final_xmr_balance = alice_monero_wallet.get_balance().await.unwrap();
|
||||
let bob_final_xmr_balance = bob_monero_wallet.get_balance().await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
alice_final_btc_balance,
|
||||
initial_balances.alice_btc + swap_amounts.btc
|
||||
- bitcoin::Amount::from_sat(2 * bitcoin::TX_FEE)
|
||||
);
|
||||
assert_eq!(
|
||||
bob_final_btc_balance,
|
||||
initial_balances.bob_btc - swap_amounts.btc - lock_tx_bitcoin_fee
|
||||
);
|
||||
|
||||
// Getting the Monero LockTx fee is tricky in a clean way, I think checking this
|
||||
// condition is sufficient
|
||||
assert!(alice_final_xmr_balance <= initial_balances.alice_xmr - swap_amounts.xmr,);
|
||||
assert_eq!(bob_final_xmr_balance, initial_balances.bob_xmr);
|
||||
}
|
Loading…
Reference in New Issue
Block a user