From bede1c13dd6e68d79c8ee64645467bd31b9c848a Mon Sep 17 00:00:00 2001 From: Daniel Karzel Date: Fri, 15 Jan 2021 19:29:26 +1100 Subject: [PATCH] Refactor Bob's side (happy path + alice restart) Refactor Bob's test setup in the same way as Alice's. Introduce BobHarness that allows creating and restarting as well as asserting redeemed for Bob. --- swap/tests/happy_path.rs | 16 +-- swap/tests/happy_path_restart_alice.rs | 12 +- swap/tests/testutils/mod.rs | 186 ++++++++++++++++++------- 3 files changed, 148 insertions(+), 66 deletions(-) diff --git a/swap/tests/happy_path.rs b/swap/tests/happy_path.rs index c2a251b1..4f40db1c 100644 --- a/swap/tests/happy_path.rs +++ b/swap/tests/happy_path.rs @@ -1,5 +1,5 @@ use rand::rngs::OsRng; -use swap::protocol::{alice, bob, bob::BobState}; +use swap::protocol::{alice, bob}; use tokio::join; pub mod testutils; @@ -8,7 +8,7 @@ pub mod testutils; #[tokio::test] async fn happy_path() { - testutils::test(|alice_harness, bob, swap_amounts| async move { + testutils::test(|alice_harness, bob_harness| async move { let alice = alice_harness.new_alice().await; let alice_swap_fut = alice::swap( alice.state, @@ -19,6 +19,8 @@ async fn happy_path() { alice.swap_id, alice.db, ); + + let bob = bob_harness.new_bob().await; let bob_swap_fut = bob::swap( bob.state, bob.event_loop_handle, @@ -31,15 +33,7 @@ async fn happy_path() { let (alice_state, bob_state) = join!(alice_swap_fut, bob_swap_fut); alice_harness.assert_redeemed(alice_state.unwrap()).await; - - let btc_bob_final = bob.bitcoin_wallet.as_ref().balance().await.unwrap(); - - bob.monero_wallet.as_ref().inner.refresh().await.unwrap(); - - let xmr_bob_final = bob.monero_wallet.as_ref().get_balance().await.unwrap(); - assert!(matches!(bob_state.unwrap(), BobState::XmrRedeemed)); - assert!(btc_bob_final <= bob.btc_starting_balance - swap_amounts.btc); - assert_eq!(xmr_bob_final, bob.xmr_starting_balance + swap_amounts.xmr); + bob_harness.assert_redeemed(bob_state.unwrap()).await; }) .await; } diff --git a/swap/tests/happy_path_restart_alice.rs b/swap/tests/happy_path_restart_alice.rs index 136dcd84..48612540 100644 --- a/swap/tests/happy_path_restart_alice.rs +++ b/swap/tests/happy_path_restart_alice.rs @@ -1,12 +1,13 @@ use rand::rngs::OsRng; -use swap::protocol::{alice, alice::AliceState, bob, bob::BobState}; +use swap::protocol::{alice, alice::AliceState, bob}; pub mod testutils; #[tokio::test] async fn given_alice_restarts_after_encsig_is_learned_resume_swap() { - testutils::test(|alice_harness, bob, swap_amounts| async move { + testutils::test(|alice_harness, bob_harness| async move { let alice = alice_harness.new_alice().await; + let bob = bob_harness.new_bob().await; let bob_swap_fut = bob::swap( bob.state, @@ -51,12 +52,7 @@ async fn given_alice_restarts_after_encsig_is_learned_resume_swap() { alice_harness.assert_redeemed(alice_state).await; let bob_state = bob_swap_handle.await.unwrap(); - let btc_bob_final = bob.bitcoin_wallet.as_ref().balance().await.unwrap(); - bob.monero_wallet.as_ref().inner.refresh().await.unwrap(); - let xmr_bob_final = bob.monero_wallet.as_ref().get_balance().await.unwrap(); - assert!(matches!(bob_state.unwrap(), BobState::XmrRedeemed)); - assert!(btc_bob_final <= bob.btc_starting_balance - swap_amounts.btc); - assert_eq!(xmr_bob_final, bob.xmr_starting_balance + swap_amounts.xmr); + bob_harness.assert_redeemed(bob_state.unwrap()).await }) .await; } diff --git a/swap/tests/testutils/mod.rs b/swap/tests/testutils/mod.rs index eef2654f..27d39111 100644 --- a/swap/tests/testutils/mod.rs +++ b/swap/tests/testutils/mod.rs @@ -38,17 +38,6 @@ pub struct Alice { pub db: Database, } -pub struct Bob { - pub state: BobState, - pub event_loop_handle: bob::EventLoopHandle, - pub db: Database, - pub bitcoin_wallet: Arc, - pub monero_wallet: Arc, - pub swap_id: Uuid, - pub btc_starting_balance: bitcoin::Amount, - pub xmr_starting_balance: monero::Amount, -} - pub struct AliceHarness { listen_address: Multiaddr, peer_id: PeerId, @@ -57,7 +46,6 @@ pub struct AliceHarness { db_path: PathBuf, swap_id: Uuid, - // Stuff that should probably not be in here... swap_amounts: SwapAmounts, btc_wallet: Arc, xmr_wallet: Arc, @@ -189,9 +177,137 @@ impl AliceHarness { } } +pub struct Bob { + pub state: BobState, + pub event_loop_handle: bob::EventLoopHandle, + pub db: Database, + pub bitcoin_wallet: Arc, + pub monero_wallet: Arc, + pub swap_id: Uuid, +} + +pub struct BobHarness { + db_path: PathBuf, + swap_id: Uuid, + + swap_amounts: SwapAmounts, + btc_wallet: Arc, + xmr_wallet: Arc, + config: Config, + starting_balances: StartingBalances, + + alice_connect_address: Multiaddr, + alice_connect_peer_id: PeerId, +} + +impl BobHarness { + #[allow(clippy::too_many_arguments)] + pub async fn new( + config: Config, + swap_amounts: SwapAmounts, + swap_id: Uuid, + monero: &Monero, + bitcoind: &Bitcoind<'_>, + starting_balances: StartingBalances, + alice_connect_address: Multiaddr, + alice_connect_peer_id: PeerId, + ) -> Self { + let db_path = tempdir().unwrap().path().to_path_buf(); + + let (btc_wallet, xmr_wallet) = + init_wallets("bob", bitcoind, monero, starting_balances.clone(), config).await; + + Self { + db_path, + swap_id, + swap_amounts, + btc_wallet, + xmr_wallet, + config, + starting_balances, + alice_connect_address, + alice_connect_peer_id, + } + } + + pub async fn new_bob(&self) -> Bob { + let initial_state = init_bob_state( + self.swap_amounts.btc, + self.swap_amounts.xmr, + self.btc_wallet.clone(), + self.config, + ) + .await; + + let (event_loop, event_loop_handle) = init_bob_event_loop( + self.alice_connect_peer_id.clone(), + self.alice_connect_address.clone(), + ); + + tokio::spawn(async move { event_loop.run().await }); + + let db = Database::open(self.db_path.as_path()).unwrap(); + + Bob { + state: initial_state, + event_loop_handle, + db, + bitcoin_wallet: self.btc_wallet.clone(), + monero_wallet: self.xmr_wallet.clone(), + swap_id: self.swap_id, + } + } + + pub async fn recover_bob_from_db(&self) -> Bob { + // TODO: "simulated restart" issues: + // - create new wallets instead of reusing (hard because of container + // lifetimes) + // - consider aborting the old event loop (currently just keeps running) + + // reopen the existing database + let db = Database::open(self.db_path.clone().as_path()).unwrap(); + + let resume_state = + if let swap::database::Swap::Bob(state) = db.get_state(self.swap_id).unwrap() { + state.into() + } else { + unreachable!() + }; + + let (event_loop, event_loop_handle) = init_bob_event_loop( + self.alice_connect_peer_id.clone(), + self.alice_connect_address.clone(), + ); + + tokio::spawn(async move { event_loop.run().await }); + + Bob { + state: resume_state, + event_loop_handle, + db, + bitcoin_wallet: self.btc_wallet.clone(), + monero_wallet: self.xmr_wallet.clone(), + swap_id: self.swap_id, + } + } + + pub async fn assert_redeemed(&self, state: BobState) { + assert!(matches!(state, BobState::XmrRedeemed)); + + let btc_bob_final = self.btc_wallet.as_ref().balance().await.unwrap(); + self.xmr_wallet.as_ref().inner.refresh().await.unwrap(); + let xmr_bob_final = self.xmr_wallet.as_ref().get_balance().await.unwrap(); + assert!(btc_bob_final <= self.starting_balances.btc - self.swap_amounts.btc); + assert_eq!( + xmr_bob_final, + self.starting_balances.xmr + self.swap_amounts.xmr + ); + } +} + pub async fn test(testfn: T) where - T: Fn(AliceHarness, Bob, SwapAmounts) -> F, + T: Fn(AliceHarness, BobHarness) -> F, F: Future, { let cli = Cli::default(); @@ -211,7 +327,7 @@ where xmr: swap_amounts.xmr * 10, btc: bitcoin::Amount::ZERO, }; - let alice_factory = AliceHarness::new( + let alice_harness = AliceHarness::new( config, swap_amounts, Uuid::new_v4(), @@ -226,43 +342,19 @@ where btc: swap_amounts.btc * 10, }; - let (bob_btc_wallet, bob_xmr_wallet) = init_wallets( - "bob", - &containers.bitcoind, + let bob_harness = BobHarness::new( + config, + swap_amounts, + Uuid::new_v4(), &monero, - bob_starting_balances.clone(), - config, + &containers.bitcoind, + bob_starting_balances, + alice_harness.listen_address(), + alice_harness.peer_id(), ) .await; - let bob_state = init_bob_state( - swap_amounts.btc, - swap_amounts.xmr, - bob_btc_wallet.clone(), - config, - ) - .await; - - let (bob_event_loop, bob_event_loop_handle) = - init_bob_event_loop(alice_factory.peer_id(), alice_factory.listen_address()); - - let bob_db_dir = tempdir().unwrap(); - let bob_db = Database::open(bob_db_dir.path()).unwrap(); - - tokio::spawn(async move { bob_event_loop.run().await }); - - let bob = Bob { - state: bob_state, - event_loop_handle: bob_event_loop_handle, - db: bob_db, - bitcoin_wallet: bob_btc_wallet, - monero_wallet: bob_xmr_wallet, - swap_id: Uuid::new_v4(), - xmr_starting_balance: bob_starting_balances.xmr, - btc_starting_balance: bob_starting_balances.btc, - }; - - testfn(alice_factory, bob, swap_amounts).await + testfn(alice_harness, bob_harness).await } pub async fn init_containers(cli: &Cli) -> (Monero, Containers<'_>) {