150: Few improvements r=D4nte a=D4nte



Co-authored-by: Franck Royer <franck@coblox.tech>
This commit is contained in:
bors[bot] 2021-01-20 11:30:35 +00:00 committed by GitHub
commit d6bf66c1f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 397 additions and 426 deletions

View File

@ -23,7 +23,7 @@ use swap::{
config::Config,
database::Database,
monero,
protocol::{alice, bob, bob::SwapFactory, StartingBalances},
protocol::{alice, bob, bob::Builder},
trace::init_tracing,
SwapAmounts,
};
@ -67,7 +67,7 @@ async fn main() -> Result<()> {
btc: receive_bitcoin,
};
let (bitcoin_wallet, monero_wallet, starting_balances) = setup_wallets(
let (bitcoin_wallet, monero_wallet) = setup_wallets(
bitcoind_url,
bitcoin_wallet_name.as_str(),
monero_wallet_rpc_url,
@ -82,18 +82,18 @@ async fn main() -> Result<()> {
send_monero, receive_bitcoin, swap_id
);
let alice_factory = alice::SwapFactory::new(
let alice_factory = alice::Builder::new(
seed,
config,
swap_id,
bitcoin_wallet,
monero_wallet,
starting_balances,
Arc::new(bitcoin_wallet),
Arc::new(monero_wallet),
db_path,
listen_addr,
)
.await;
let (swap, mut event_loop) = alice_factory.new_swap_as_alice(swap_amounts).await?;
let (swap, mut event_loop) =
alice_factory.with_init_params(swap_amounts).build().await?;
tokio::spawn(async move { event_loop.run().await });
alice::run(swap).await?;
@ -112,7 +112,7 @@ async fn main() -> Result<()> {
xmr: receive_monero,
};
let (bitcoin_wallet, monero_wallet, starting_balances) = setup_wallets(
let (bitcoin_wallet, monero_wallet) = setup_wallets(
bitcoind_url,
bitcoin_wallet_name.as_str(),
monero_wallet_rpc_url,
@ -127,18 +127,19 @@ async fn main() -> Result<()> {
send_bitcoin, receive_monero, swap_id
);
let bob_factory = SwapFactory::new(
let bob_factory = Builder::new(
seed,
db_path,
swap_id,
bitcoin_wallet,
monero_wallet,
config,
starting_balances,
Arc::new(bitcoin_wallet),
Arc::new(monero_wallet),
alice_addr,
alice_peer_id,
);
let (swap, event_loop) = bob_factory.new_swap_as_bob(swap_amounts).await?;
let (swap, event_loop) = bob_factory
.with_init_params(swap_amounts, config)
.build()
.await?;
tokio::spawn(async move { event_loop.run().await });
bob::run(swap).await?;
@ -164,7 +165,7 @@ async fn main() -> Result<()> {
monero_wallet_rpc_url,
listen_addr,
}) => {
let (bitcoin_wallet, monero_wallet, starting_balances) = setup_wallets(
let (bitcoin_wallet, monero_wallet) = setup_wallets(
bitcoind_url,
bitcoin_wallet_name.as_str(),
monero_wallet_rpc_url,
@ -172,18 +173,17 @@ async fn main() -> Result<()> {
)
.await?;
let alice_factory = alice::SwapFactory::new(
let alice_factory = alice::Builder::new(
seed,
config,
swap_id,
bitcoin_wallet,
monero_wallet,
starting_balances,
Arc::new(bitcoin_wallet),
Arc::new(monero_wallet),
db_path,
listen_addr,
)
.await;
let (swap, mut event_loop) = alice_factory.recover_alice_from_db().await?;
let (swap, mut event_loop) = alice_factory.build().await?;
tokio::spawn(async move { event_loop.run().await });
alice::run(swap).await?;
@ -196,7 +196,7 @@ async fn main() -> Result<()> {
alice_peer_id,
alice_addr,
}) => {
let (bitcoin_wallet, monero_wallet, starting_balances) = setup_wallets(
let (bitcoin_wallet, monero_wallet) = setup_wallets(
bitcoind_url,
bitcoin_wallet_name.as_str(),
monero_wallet_rpc_url,
@ -204,18 +204,16 @@ async fn main() -> Result<()> {
)
.await?;
let bob_factory = SwapFactory::new(
let bob_factory = Builder::new(
seed,
db_path,
swap_id,
bitcoin_wallet,
monero_wallet,
config,
starting_balances,
Arc::new(bitcoin_wallet),
Arc::new(monero_wallet),
alice_addr,
alice_peer_id,
);
let (swap, event_loop) = bob_factory.recover_bob_from_db().await?;
let (swap, event_loop) = bob_factory.build().await?;
tokio::spawn(async move { event_loop.run().await });
bob::run(swap).await?;
@ -230,11 +228,7 @@ async fn setup_wallets(
bitcoin_wallet_name: &str,
monero_wallet_rpc_url: url::Url,
config: Config,
) -> Result<(
Arc<swap::bitcoin::Wallet>,
Arc<swap::monero::Wallet>,
StartingBalances,
)> {
) -> Result<(swap::bitcoin::Wallet, swap::monero::Wallet)> {
let bitcoin_wallet =
swap::bitcoin::Wallet::new(bitcoin_wallet_name, bitcoind_url, config.bitcoin_network)
.await?;
@ -243,7 +237,6 @@ async fn setup_wallets(
"Connection to Bitcoin wallet succeeded, balance: {}",
bitcoin_balance
);
let bitcoin_wallet = Arc::new(bitcoin_wallet);
let monero_wallet = monero::Wallet::new(monero_wallet_rpc_url, config.monero_network);
let monero_balance = monero_wallet.get_balance().await?;
@ -251,12 +244,6 @@ async fn setup_wallets(
"Connection to Monero wallet succeeded, balance: {}",
monero_balance
);
let monero_wallet = Arc::new(monero_wallet);
let starting_balances = StartingBalances {
btc: bitcoin_balance,
xmr: monero_balance,
};
Ok((bitcoin_wallet, monero_wallet, starting_balances))
Ok((bitcoin_wallet, monero_wallet))
}

View File

@ -24,10 +24,7 @@ pub use self::{
state::*,
swap::{run, run_until},
};
use crate::{
config::Config, database::Database, network::transport::build, protocol::StartingBalances,
seed::Seed,
};
use crate::{config::Config, database::Database, network::transport::build, seed::Seed};
use libp2p::{core::Multiaddr, identity::Keypair};
use rand::rngs::OsRng;
use std::{path::PathBuf, sync::Arc};
@ -53,7 +50,7 @@ pub struct Swap {
pub db: Database,
}
pub struct SwapFactory {
pub struct Builder {
swap_id: Uuid,
identity: Keypair,
peer_id: PeerId,
@ -62,20 +59,24 @@ pub struct SwapFactory {
listen_address: Multiaddr,
pub bitcoin_wallet: Arc<bitcoin::Wallet>,
pub monero_wallet: Arc<monero::Wallet>,
pub starting_balances: StartingBalances,
bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>,
init_params: InitParams,
}
impl SwapFactory {
#[allow(clippy::too_many_arguments)]
enum InitParams {
None,
New { swap_amounts: SwapAmounts },
}
impl Builder {
pub async fn new(
seed: Seed,
config: Config,
swap_id: Uuid,
bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>,
starting_balances: StartingBalances,
db_path: PathBuf,
listen_address: Multiaddr,
) -> Self {
@ -92,72 +93,71 @@ impl SwapFactory {
listen_address,
bitcoin_wallet,
monero_wallet,
starting_balances,
init_params: InitParams::None,
}
}
pub async fn new_swap_as_alice(&self, swap_amounts: SwapAmounts) -> Result<(Swap, EventLoop)> {
let initial_state = init_alice_state(
swap_amounts.btc,
swap_amounts.xmr,
self.bitcoin_wallet.clone(),
self.config,
)
.await?;
let (event_loop, event_loop_handle) = init_alice_event_loop(
self.listen_address.clone(),
self.identity.clone(),
self.peer_id.clone(),
)?;
let db = Database::open(self.db_path.as_path())?;
Ok((
Swap {
event_loop_handle,
bitcoin_wallet: self.bitcoin_wallet.clone(),
monero_wallet: self.monero_wallet.clone(),
config: self.config,
db,
state: initial_state,
swap_id: self.swap_id,
},
event_loop,
))
pub fn with_init_params(self, swap_amounts: SwapAmounts) -> Self {
Self {
init_params: InitParams::New { swap_amounts },
..self
}
}
pub async fn recover_alice_from_db(&self) -> Result<(Swap, EventLoop)> {
// reopen the existing database
let db = Database::open(self.db_path.clone().as_path())?;
pub async fn build(self) -> Result<(Swap, EventLoop)> {
match self.init_params {
InitParams::New { swap_amounts } => {
let initial_state = self
.make_initial_state(swap_amounts.btc, swap_amounts.xmr)
.await?;
let resume_state = if let database::Swap::Alice(state) = db.get_state(self.swap_id)? {
state.into()
} else {
bail!(
"Trying to load swap with id {} for the wrong direction.",
self.swap_id
)
};
let (event_loop, event_loop_handle) = self.init_event_loop()?;
let (event_loop, event_loop_handle) = init_alice_event_loop(
self.listen_address.clone(),
self.identity.clone(),
self.peer_id.clone(),
)?;
let db = Database::open(self.db_path.as_path())?;
Ok((
Swap {
state: resume_state,
event_loop_handle,
bitcoin_wallet: self.bitcoin_wallet.clone(),
monero_wallet: self.monero_wallet.clone(),
config: self.config,
swap_id: self.swap_id,
db,
},
event_loop,
))
Ok((
Swap {
event_loop_handle,
bitcoin_wallet: self.bitcoin_wallet,
monero_wallet: self.monero_wallet,
config: self.config,
db,
state: initial_state,
swap_id: self.swap_id,
},
event_loop,
))
}
InitParams::None => {
// reopen the existing database
let db = Database::open(self.db_path.as_path())?;
let resume_state =
if let database::Swap::Alice(state) = db.get_state(self.swap_id)? {
state.into()
} else {
bail!(
"Trying to load swap with id {} for the wrong direction.",
self.swap_id
)
};
let (event_loop, event_loop_handle) = self.init_event_loop()?;
Ok((
Swap {
state: resume_state,
event_loop_handle,
bitcoin_wallet: self.bitcoin_wallet,
monero_wallet: self.monero_wallet,
config: self.config,
swap_id: self.swap_id,
db,
},
event_loop,
))
}
}
}
pub fn peer_id(&self) -> PeerId {
@ -167,49 +167,49 @@ impl SwapFactory {
pub fn listen_address(&self) -> Multiaddr {
self.listen_address.clone()
}
}
async fn init_alice_state(
btc_to_swap: bitcoin::Amount,
xmr_to_swap: monero::Amount,
alice_btc_wallet: Arc<bitcoin::Wallet>,
config: Config,
) -> Result<AliceState> {
let rng = &mut OsRng;
async fn make_initial_state(
&self,
btc_to_swap: bitcoin::Amount,
xmr_to_swap: monero::Amount,
) -> Result<AliceState> {
let rng = &mut OsRng;
let amounts = SwapAmounts {
btc: btc_to_swap,
xmr: xmr_to_swap,
};
let amounts = SwapAmounts {
btc: btc_to_swap,
xmr: xmr_to_swap,
};
let a = bitcoin::SecretKey::new_random(rng);
let s_a = cross_curve_dleq::Scalar::random(rng);
let v_a = monero::PrivateViewKey::new_random(rng);
let redeem_address = alice_btc_wallet.as_ref().new_address().await?;
let punish_address = redeem_address.clone();
let state0 = State0::new(
a,
s_a,
v_a,
amounts.btc,
amounts.xmr,
config.bitcoin_cancel_timelock,
config.bitcoin_punish_timelock,
redeem_address,
punish_address,
);
let a = bitcoin::SecretKey::new_random(rng);
let s_a = cross_curve_dleq::Scalar::random(rng);
let v_a = monero::PrivateViewKey::new_random(rng);
let redeem_address = self.bitcoin_wallet.new_address().await?;
let punish_address = redeem_address.clone();
let state0 = State0::new(
a,
s_a,
v_a,
amounts.btc,
amounts.xmr,
self.config.bitcoin_cancel_timelock,
self.config.bitcoin_punish_timelock,
redeem_address,
punish_address,
);
Ok(AliceState::Started { amounts, state0 })
}
Ok(AliceState::Started { amounts, state0 })
}
fn init_alice_event_loop(
listen: Multiaddr,
identity: Keypair,
peer_id: PeerId,
) -> Result<(EventLoop, EventLoopHandle)> {
let alice_behaviour = Behaviour::default();
let alice_transport = build(identity)?;
EventLoop::new(alice_transport, alice_behaviour, listen, peer_id)
fn init_event_loop(&self) -> Result<(EventLoop, EventLoopHandle)> {
let alice_behaviour = Behaviour::default();
let alice_transport = build(self.identity.clone())?;
EventLoop::new(
alice_transport,
alice_behaviour,
self.listen_address.clone(),
self.peer_id.clone(),
)
}
}
#[derive(Debug)]

View File

@ -23,10 +23,7 @@ pub use self::{
state::*,
swap::{run, run_until},
};
use crate::{
config::Config, database::Database, network::transport::build, protocol::StartingBalances,
seed::Seed,
};
use crate::{config::Config, database::Database, network::transport::build, seed::Seed};
use libp2p::identity::Keypair;
use rand::rngs::OsRng;
use std::{path::PathBuf, sync::Arc};
@ -50,33 +47,38 @@ pub struct Swap {
pub swap_id: Uuid,
}
pub struct SwapFactory {
pub struct Builder {
swap_id: Uuid,
identity: Keypair,
peer_id: PeerId,
db_path: PathBuf,
config: Config,
alice_connect_address: Multiaddr,
alice_connect_peer_id: PeerId,
alice_address: Multiaddr,
alice_peer_id: PeerId,
pub bitcoin_wallet: Arc<bitcoin::Wallet>,
pub monero_wallet: Arc<monero::Wallet>,
pub starting_balances: StartingBalances,
bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>,
init_params: InitParams,
}
impl SwapFactory {
#[allow(clippy::too_many_arguments)]
enum InitParams {
None,
New {
swap_amounts: SwapAmounts,
config: Config,
},
}
impl Builder {
pub fn new(
seed: Seed,
db_path: PathBuf,
swap_id: Uuid,
bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>,
config: Config,
starting_balances: StartingBalances,
alice_connect_address: Multiaddr,
alice_connect_peer_id: PeerId,
alice_address: Multiaddr,
alice_peer_id: PeerId,
) -> Self {
let identity = network::Seed::new(seed).derive_libp2p_identity();
let peer_id = identity.public().into_peer_id();
@ -86,126 +88,120 @@ impl SwapFactory {
identity,
peer_id,
db_path,
config,
alice_connect_address,
alice_connect_peer_id,
alice_address,
alice_peer_id,
bitcoin_wallet,
monero_wallet,
starting_balances,
init_params: InitParams::None,
}
}
pub async fn new_swap_as_bob(
&self,
swap_amounts: SwapAmounts,
) -> Result<(bob::Swap, bob::EventLoop)> {
let initial_state = init_bob_state(
swap_amounts.btc,
swap_amounts.xmr,
self.bitcoin_wallet.clone(),
self.config,
)
.await?;
let (event_loop, event_loop_handle) = init_bob_event_loop(
self.identity.clone(),
self.peer_id.clone(),
self.alice_connect_peer_id.clone(),
self.alice_connect_address.clone(),
)?;
let db = Database::open(self.db_path.as_path())?;
Ok((
Swap {
state: initial_state,
event_loop_handle,
db,
bitcoin_wallet: self.bitcoin_wallet.clone(),
monero_wallet: self.monero_wallet.clone(),
swap_id: self.swap_id,
pub fn with_init_params(self, swap_amounts: SwapAmounts, config: Config) -> Self {
Self {
init_params: InitParams::New {
swap_amounts,
config,
},
event_loop,
))
..self
}
}
pub async fn recover_bob_from_db(&self) -> Result<(bob::Swap, bob::EventLoop)> {
// reopen the existing database
let db = Database::open(self.db_path.clone().as_path())?;
pub async fn build(self) -> Result<(bob::Swap, bob::EventLoop)> {
match self.init_params {
InitParams::New {
swap_amounts,
config,
} => {
let initial_state = self
.make_initial_state(swap_amounts.btc, swap_amounts.xmr, config)
.await?;
let resume_state = if let database::Swap::Bob(state) = db.get_state(self.swap_id)? {
state.into()
} else {
bail!(
"Trying to load swap with id {} for the wrong direction.",
self.swap_id
)
let (event_loop, event_loop_handle) = self.init_event_loop()?;
let db = Database::open(self.db_path.as_path())?;
Ok((
Swap {
state: initial_state,
event_loop_handle,
db,
bitcoin_wallet: self.bitcoin_wallet.clone(),
monero_wallet: self.monero_wallet.clone(),
swap_id: self.swap_id,
},
event_loop,
))
}
InitParams::None => {
// reopen the existing database
let db = Database::open(self.db_path.as_path())?;
let resume_state = if let database::Swap::Bob(state) = db.get_state(self.swap_id)? {
state.into()
} else {
bail!(
"Trying to load swap with id {} for the wrong direction.",
self.swap_id
)
};
let (event_loop, event_loop_handle) = self.init_event_loop()?;
Ok((
Swap {
state: resume_state,
event_loop_handle,
db,
bitcoin_wallet: self.bitcoin_wallet.clone(),
monero_wallet: self.monero_wallet.clone(),
swap_id: self.swap_id,
},
event_loop,
))
}
}
}
fn init_event_loop(
&self,
) -> Result<(bob::event_loop::EventLoop, bob::event_loop::EventLoopHandle)> {
let bob_behaviour = bob::Behaviour::default();
let bob_transport = build(self.identity.clone())?;
bob::event_loop::EventLoop::new(
bob_transport,
bob_behaviour,
self.peer_id.clone(),
self.alice_peer_id.clone(),
self.alice_address.clone(),
)
}
async fn make_initial_state(
&self,
btc_to_swap: bitcoin::Amount,
xmr_to_swap: monero::Amount,
config: Config,
) -> Result<BobState> {
let amounts = SwapAmounts {
btc: btc_to_swap,
xmr: xmr_to_swap,
};
let (event_loop, event_loop_handle) = init_bob_event_loop(
self.identity.clone(),
self.peer_id.clone(),
self.alice_connect_peer_id.clone(),
self.alice_connect_address.clone(),
)?;
let refund_address = self.bitcoin_wallet.new_address().await?;
let state0 = bob::State0::new(
&mut OsRng,
btc_to_swap,
xmr_to_swap,
config.bitcoin_cancel_timelock,
config.bitcoin_punish_timelock,
refund_address,
config.monero_finality_confirmations,
);
Ok((
Swap {
state: resume_state,
event_loop_handle,
db,
bitcoin_wallet: self.bitcoin_wallet.clone(),
monero_wallet: self.monero_wallet.clone(),
swap_id: self.swap_id,
},
event_loop,
))
Ok(BobState::Started { state0, amounts })
}
}
async fn init_bob_state(
btc_to_swap: bitcoin::Amount,
xmr_to_swap: monero::Amount,
bob_btc_wallet: Arc<bitcoin::Wallet>,
config: Config,
) -> Result<BobState> {
let amounts = SwapAmounts {
btc: btc_to_swap,
xmr: xmr_to_swap,
};
let refund_address = bob_btc_wallet.new_address().await?;
let state0 = bob::State0::new(
&mut OsRng,
btc_to_swap,
xmr_to_swap,
config.bitcoin_cancel_timelock,
config.bitcoin_punish_timelock,
refund_address,
config.monero_finality_confirmations,
);
Ok(BobState::Started { state0, amounts })
}
fn init_bob_event_loop(
identity: Keypair,
peer_id: PeerId,
alice_peer_id: PeerId,
alice_addr: Multiaddr,
) -> Result<(bob::event_loop::EventLoop, bob::event_loop::EventLoopHandle)> {
let bob_behaviour = bob::Behaviour::default();
let bob_transport = build(identity)?;
bob::event_loop::EventLoop::new(
bob_transport,
bob_behaviour,
peer_id,
alice_peer_id,
alice_addr,
)
}
#[derive(Debug, Clone)]
pub enum OutEvent {
ConnectionEstablished(PeerId),

View File

@ -7,7 +7,7 @@ pub mod testutils;
#[tokio::test]
async fn happy_path() {
testutils::setup_test(|ctx| async move {
testutils::setup_test(|mut ctx| async move {
let alice_swap = ctx.new_swap_as_alice().await;
let bob_swap = ctx.new_swap_as_bob().await;

View File

@ -4,7 +4,7 @@ pub mod testutils;
#[tokio::test]
async fn given_alice_restarts_after_encsig_is_learned_resume_swap() {
testutils::setup_test(|ctx| async move {
testutils::setup_test(|mut ctx| async move {
let alice_swap = ctx.new_swap_as_alice().await;
let bob_swap = ctx.new_swap_as_bob().await;

View File

@ -4,7 +4,7 @@ pub mod testutils;
#[tokio::test]
async fn given_bob_restarts_after_encsig_is_sent_resume_swap() {
testutils::setup_test(|ctx| async move {
testutils::setup_test(|mut ctx| async move {
let alice_swap = ctx.new_swap_as_alice().await;
let bob_swap = ctx.new_swap_as_bob().await;

View File

@ -7,7 +7,7 @@ pub mod testutils;
#[tokio::test]
async fn given_bob_restarts_after_xmr_is_locked_resume_swap() {
testutils::setup_test(|ctx| async move {
testutils::setup_test(|mut ctx| async move {
let alice_swap = ctx.new_swap_as_alice().await;
let bob_swap = ctx.new_swap_as_bob().await;

View File

@ -9,7 +9,7 @@ pub mod testutils;
/// the encsig and fail to refund or redeem. Alice punishes.
#[tokio::test]
async fn alice_punishes_if_bob_never_acts_after_fund() {
testutils::setup_test(|ctx| async move {
testutils::setup_test(|mut ctx| async move {
let alice_swap = ctx.new_swap_as_alice().await;
let bob_swap = ctx.new_swap_as_bob().await;

View File

@ -6,7 +6,7 @@ pub mod testutils;
/// then also refunds.
#[tokio::test]
async fn given_alice_restarts_after_xmr_is_locked_abort_swap() {
testutils::setup_test(|ctx| async move {
testutils::setup_test(|mut ctx| async move {
let alice_swap = ctx.new_swap_as_alice().await;
let bob_swap = ctx.new_swap_as_bob().await;

View File

@ -2,14 +2,14 @@ use crate::testutils;
use bitcoin_harness::Bitcoind;
use futures::Future;
use get_port::get_port;
use libp2p::core::Multiaddr;
use libp2p::{core::Multiaddr, PeerId};
use monero_harness::{image, Monero};
use std::sync::Arc;
use std::{path::PathBuf, sync::Arc};
use swap::{
bitcoin,
config::Config,
monero,
protocol::{alice, alice::AliceState, bob, bob::BobState, StartingBalances},
protocol::{alice, alice::AliceState, bob, bob::BobState},
seed::Seed,
SwapAmounts,
};
@ -19,18 +19,87 @@ use tracing_core::dispatcher::DefaultGuard;
use tracing_log::LogTracer;
use uuid::Uuid;
#[derive(Debug, Clone)]
pub struct StartingBalances {
pub xmr: monero::Amount,
pub btc: bitcoin::Amount,
}
struct AliceParams {
seed: Seed,
config: Config,
swap_id: Uuid,
bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>,
db_path: PathBuf,
listen_address: Multiaddr,
}
impl AliceParams {
pub async fn builder(&self) -> alice::Builder {
alice::Builder::new(
self.seed,
self.config,
self.swap_id,
self.bitcoin_wallet.clone(),
self.monero_wallet.clone(),
self.db_path.clone(),
self.listen_address.clone(),
)
.await
}
async fn peer_id(&self) -> PeerId {
self.builder().await.peer_id()
}
}
struct BobParams {
seed: Seed,
db_path: PathBuf,
swap_id: Uuid,
bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>,
alice_address: Multiaddr,
alice_peer_id: PeerId,
}
impl BobParams {
pub fn builder(&self) -> bob::Builder {
bob::Builder::new(
self.seed,
self.db_path.clone(),
self.swap_id,
self.bitcoin_wallet.clone(),
self.monero_wallet.clone(),
self.alice_address.clone(),
self.alice_peer_id.clone(),
)
}
}
pub struct TestContext {
swap_amounts: SwapAmounts,
alice_swap_factory: alice::SwapFactory,
bob_swap_factory: bob::SwapFactory,
alice_params: AliceParams,
alice_starting_balances: StartingBalances,
alice_bitcoin_wallet: Arc<bitcoin::Wallet>,
alice_monero_wallet: Arc<monero::Wallet>,
bob_params: BobParams,
bob_starting_balances: StartingBalances,
bob_bitcoin_wallet: Arc<bitcoin::Wallet>,
bob_monero_wallet: Arc<monero::Wallet>,
}
impl TestContext {
pub async fn new_swap_as_alice(&self) -> alice::Swap {
pub async fn new_swap_as_alice(&mut self) -> alice::Swap {
let (swap, mut event_loop) = self
.alice_swap_factory
.new_swap_as_alice(self.swap_amounts)
.alice_params
.builder()
.await
.with_init_params(self.swap_amounts)
.build()
.await
.unwrap();
@ -39,10 +108,12 @@ impl TestContext {
swap
}
pub async fn new_swap_as_bob(&self) -> bob::Swap {
pub async fn new_swap_as_bob(&mut self) -> bob::Swap {
let (swap, event_loop) = self
.bob_swap_factory
.new_swap_as_bob(self.swap_amounts)
.bob_params
.builder()
.with_init_params(self.swap_amounts, Config::regtest())
.build()
.await
.unwrap();
@ -51,20 +122,16 @@ impl TestContext {
swap
}
pub async fn recover_alice_from_db(&self) -> alice::Swap {
let (swap, mut event_loop) = self
.alice_swap_factory
.recover_alice_from_db()
.await
.unwrap();
pub async fn recover_alice_from_db(&mut self) -> alice::Swap {
let (swap, mut event_loop) = self.alice_params.builder().await.build().await.unwrap();
tokio::spawn(async move { event_loop.run().await });
swap
}
pub async fn recover_bob_from_db(&self) -> bob::Swap {
let (swap, event_loop) = self.bob_swap_factory.recover_bob_from_db().await.unwrap();
pub async fn recover_bob_from_db(&mut self) -> bob::Swap {
let (swap, event_loop) = self.bob_params.builder().build().await.unwrap();
tokio::spawn(async move { event_loop.run().await });
@ -74,58 +141,37 @@ impl TestContext {
pub async fn assert_alice_redeemed(&self, state: AliceState) {
assert!(matches!(state, AliceState::BtcRedeemed));
let btc_balance_after_swap = self
.alice_swap_factory
.bitcoin_wallet
.as_ref()
.balance()
.await
.unwrap();
let btc_balance_after_swap = self.alice_bitcoin_wallet.as_ref().balance().await.unwrap();
assert_eq!(
btc_balance_after_swap,
self.alice_swap_factory.starting_balances.btc + self.swap_amounts.btc
self.alice_starting_balances.btc + self.swap_amounts.btc
- bitcoin::Amount::from_sat(bitcoin::TX_FEE)
);
let xmr_balance_after_swap = self
.alice_swap_factory
.monero_wallet
.alice_monero_wallet
.as_ref()
.get_balance()
.await
.unwrap();
assert!(
xmr_balance_after_swap
<= self.alice_swap_factory.starting_balances.xmr - self.swap_amounts.xmr
);
assert!(xmr_balance_after_swap <= self.alice_starting_balances.xmr - self.swap_amounts.xmr);
}
pub async fn assert_alice_refunded(&self, state: AliceState) {
assert!(matches!(state, AliceState::XmrRefunded));
let btc_balance_after_swap = self
.alice_swap_factory
.bitcoin_wallet
.as_ref()
.balance()
.await
.unwrap();
assert_eq!(
btc_balance_after_swap,
self.alice_swap_factory.starting_balances.btc
);
let btc_balance_after_swap = self.alice_bitcoin_wallet.as_ref().balance().await.unwrap();
assert_eq!(btc_balance_after_swap, self.alice_starting_balances.btc);
// Ensure that Alice's balance is refreshed as we use a newly created wallet
self.alice_swap_factory
.monero_wallet
self.alice_monero_wallet
.as_ref()
.inner
.refresh()
.await
.unwrap();
let xmr_balance_after_swap = self
.alice_swap_factory
.monero_wallet
.alice_monero_wallet
.as_ref()
.get_balance()
.await
@ -136,30 +182,20 @@ impl TestContext {
pub async fn assert_alice_punished(&self, state: AliceState) {
assert!(matches!(state, AliceState::BtcPunished));
let btc_balance_after_swap = self
.alice_swap_factory
.bitcoin_wallet
.as_ref()
.balance()
.await
.unwrap();
let btc_balance_after_swap = self.alice_bitcoin_wallet.as_ref().balance().await.unwrap();
assert_eq!(
btc_balance_after_swap,
self.alice_swap_factory.starting_balances.btc + self.swap_amounts.btc
self.alice_starting_balances.btc + self.swap_amounts.btc
- bitcoin::Amount::from_sat(2 * bitcoin::TX_FEE)
);
let xmr_balance_after_swap = self
.alice_swap_factory
.monero_wallet
.alice_monero_wallet
.as_ref()
.get_balance()
.await
.unwrap();
assert!(
xmr_balance_after_swap
<= self.alice_swap_factory.starting_balances.xmr - self.swap_amounts.xmr
);
assert!(xmr_balance_after_swap <= self.alice_starting_balances.xmr - self.swap_amounts.xmr);
}
pub async fn assert_bob_redeemed(&self, state: BobState) {
@ -170,44 +206,28 @@ impl TestContext {
};
let lock_tx_bitcoin_fee = self
.bob_swap_factory
.bitcoin_wallet
.bob_bitcoin_wallet
.transaction_fee(lock_tx_id)
.await
.unwrap();
let btc_balance_after_swap = self
.bob_swap_factory
.bitcoin_wallet
.as_ref()
.balance()
.await
.unwrap();
let btc_balance_after_swap = self.bob_bitcoin_wallet.as_ref().balance().await.unwrap();
assert_eq!(
btc_balance_after_swap,
self.bob_swap_factory.starting_balances.btc
- self.swap_amounts.btc
- lock_tx_bitcoin_fee
self.bob_starting_balances.btc - self.swap_amounts.btc - lock_tx_bitcoin_fee
);
// Ensure that Bob's balance is refreshed as we use a newly created wallet
self.bob_swap_factory
.monero_wallet
self.bob_monero_wallet
.as_ref()
.inner
.refresh()
.await
.unwrap();
let xmr_balance_after_swap = self
.bob_swap_factory
.monero_wallet
.as_ref()
.get_balance()
.await
.unwrap();
let xmr_balance_after_swap = self.bob_monero_wallet.as_ref().get_balance().await.unwrap();
assert_eq!(
xmr_balance_after_swap,
self.bob_swap_factory.starting_balances.xmr + self.swap_amounts.xmr
self.bob_starting_balances.xmr + self.swap_amounts.xmr
);
}
@ -218,27 +238,20 @@ impl TestContext {
panic!("Bob in unexpected state");
};
let lock_tx_bitcoin_fee = self
.bob_swap_factory
.bitcoin_wallet
.bob_bitcoin_wallet
.transaction_fee(lock_tx_id)
.await
.unwrap();
let btc_balance_after_swap = self
.bob_swap_factory
.bitcoin_wallet
.as_ref()
.balance()
.await
.unwrap();
let btc_balance_after_swap = self.bob_bitcoin_wallet.as_ref().balance().await.unwrap();
let alice_submitted_cancel = btc_balance_after_swap
== self.bob_swap_factory.starting_balances.btc
== self.bob_starting_balances.btc
- lock_tx_bitcoin_fee
- bitcoin::Amount::from_sat(bitcoin::TX_FEE);
let bob_submitted_cancel = btc_balance_after_swap
== self.bob_swap_factory.starting_balances.btc
== self.bob_starting_balances.btc
- lock_tx_bitcoin_fee
- bitcoin::Amount::from_sat(2 * bitcoin::TX_FEE);
@ -246,17 +259,8 @@ impl TestContext {
// Since we cannot be sure who submitted it we have to assert accordingly
assert!(alice_submitted_cancel || bob_submitted_cancel);
let xmr_balance_after_swap = self
.bob_swap_factory
.monero_wallet
.as_ref()
.get_balance()
.await
.unwrap();
assert_eq!(
xmr_balance_after_swap,
self.bob_swap_factory.starting_balances.xmr
);
let xmr_balance_after_swap = self.bob_monero_wallet.as_ref().get_balance().await.unwrap();
assert_eq!(xmr_balance_after_swap, self.bob_starting_balances.xmr);
}
pub async fn assert_bob_punished(&self, state: BobState) {
@ -267,37 +271,19 @@ impl TestContext {
};
let lock_tx_bitcoin_fee = self
.bob_swap_factory
.bitcoin_wallet
.bob_bitcoin_wallet
.transaction_fee(lock_tx_id)
.await
.unwrap();
let btc_balance_after_swap = self
.bob_swap_factory
.bitcoin_wallet
.as_ref()
.balance()
.await
.unwrap();
let btc_balance_after_swap = self.bob_bitcoin_wallet.as_ref().balance().await.unwrap();
assert_eq!(
btc_balance_after_swap,
self.bob_swap_factory.starting_balances.btc
- self.swap_amounts.btc
- lock_tx_bitcoin_fee
self.bob_starting_balances.btc - self.swap_amounts.btc - lock_tx_bitcoin_fee
);
let xmr_balance_after_swap = self
.bob_swap_factory
.monero_wallet
.as_ref()
.get_balance()
.await
.unwrap();
assert_eq!(
xmr_balance_after_swap,
self.bob_swap_factory.starting_balances.xmr
);
let xmr_balance_after_swap = self.bob_monero_wallet.as_ref().get_balance().await.unwrap();
assert_eq!(xmr_balance_after_swap, self.bob_starting_balances.xmr);
}
}
@ -339,17 +325,15 @@ where
)
.await;
let alice_swap_factory = alice::SwapFactory::new(
Seed::random().unwrap(),
let alice_params = AliceParams {
seed: Seed::random().unwrap(),
config,
Uuid::new_v4(),
alice_bitcoin_wallet,
alice_monero_wallet,
alice_starting_balances,
tempdir().unwrap().path().to_path_buf(),
swap_id: Uuid::new_v4(),
bitcoin_wallet: alice_bitcoin_wallet.clone(),
monero_wallet: alice_monero_wallet.clone(),
db_path: tempdir().unwrap().path().to_path_buf(),
listen_address,
)
.await;
};
let bob_starting_balances = StartingBalances {
xmr: monero::Amount::ZERO,
@ -365,22 +349,26 @@ where
)
.await;
let bob_swap_factory = bob::SwapFactory::new(
Seed::random().unwrap(),
tempdir().unwrap().path().to_path_buf(),
Uuid::new_v4(),
bob_bitcoin_wallet,
bob_monero_wallet,
config,
bob_starting_balances,
alice_swap_factory.listen_address(),
alice_swap_factory.peer_id(),
);
let bob_params = BobParams {
seed: Seed::random().unwrap(),
db_path: tempdir().unwrap().path().to_path_buf(),
swap_id: Uuid::new_v4(),
bitcoin_wallet: bob_bitcoin_wallet.clone(),
monero_wallet: bob_monero_wallet.clone(),
alice_address: alice_params.listen_address.clone(),
alice_peer_id: alice_params.peer_id().await,
};
let test = TestContext {
swap_amounts,
alice_swap_factory,
bob_swap_factory,
alice_params,
alice_starting_balances,
alice_bitcoin_wallet,
alice_monero_wallet,
bob_params,
bob_starting_balances,
bob_bitcoin_wallet,
bob_monero_wallet,
};
testfn(test).await