Use builder terminology instead of factory

This is not really a factory as a factory design pattern is about
producing several instances.

In the current usage, we are only interested in one swap instance. Once
the swap instance is created, the factory becomes useless. Hence, it is
more of a builder pattern.
This commit is contained in:
Franck Royer 2021-01-19 15:21:40 +11:00
parent 9148af2dbe
commit c11042ff0d
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
4 changed files with 175 additions and 140 deletions

View File

@ -23,7 +23,7 @@ use swap::{
config::Config, config::Config,
database::Database, database::Database,
monero, monero,
protocol::{alice, bob, bob::SwapFactory, StartingBalances}, protocol::{alice, bob, bob::Builder},
trace::init_tracing, trace::init_tracing,
SwapAmounts, SwapAmounts,
}; };
@ -82,7 +82,7 @@ async fn main() -> Result<()> {
send_monero, receive_bitcoin, swap_id send_monero, receive_bitcoin, swap_id
); );
let alice_factory = alice::SwapFactory::new( let alice_factory = alice::Builder::new(
seed, seed,
config, config,
swap_id, swap_id,
@ -92,7 +92,8 @@ async fn main() -> Result<()> {
listen_addr, listen_addr,
) )
.await; .await;
let (swap, mut event_loop) = alice_factory.new_swap(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 }); tokio::spawn(async move { event_loop.run().await });
alice::run(swap).await?; alice::run(swap).await?;
@ -126,7 +127,7 @@ async fn main() -> Result<()> {
send_bitcoin, receive_monero, swap_id send_bitcoin, receive_monero, swap_id
); );
let bob_factory = SwapFactory::new( let bob_factory = Builder::new(
seed, seed,
db_path, db_path,
swap_id, swap_id,
@ -135,7 +136,10 @@ async fn main() -> Result<()> {
alice_addr, alice_addr,
alice_peer_id, alice_peer_id,
); );
let (swap, event_loop) = bob_factory.new_swap(swap_amounts, config).await?; let (swap, event_loop) = bob_factory
.with_init_params(swap_amounts, config)
.build()
.await?;
tokio::spawn(async move { event_loop.run().await }); tokio::spawn(async move { event_loop.run().await });
bob::run(swap).await?; bob::run(swap).await?;
@ -169,7 +173,7 @@ async fn main() -> Result<()> {
) )
.await?; .await?;
let alice_factory = alice::SwapFactory::new( let alice_factory = alice::Builder::new(
seed, seed,
config, config,
swap_id, swap_id,
@ -179,7 +183,7 @@ async fn main() -> Result<()> {
listen_addr, listen_addr,
) )
.await; .await;
let (swap, mut event_loop) = alice_factory.resume().await?; let (swap, mut event_loop) = alice_factory.build().await?;
tokio::spawn(async move { event_loop.run().await }); tokio::spawn(async move { event_loop.run().await });
alice::run(swap).await?; alice::run(swap).await?;
@ -200,7 +204,7 @@ async fn main() -> Result<()> {
) )
.await?; .await?;
let bob_factory = SwapFactory::new( let bob_factory = Builder::new(
seed, seed,
db_path, db_path,
swap_id, swap_id,
@ -209,7 +213,7 @@ async fn main() -> Result<()> {
alice_addr, alice_addr,
alice_peer_id, alice_peer_id,
); );
let (swap, event_loop) = bob_factory.resume().await?; let (swap, event_loop) = bob_factory.build().await?;
tokio::spawn(async move { event_loop.run().await }); tokio::spawn(async move { event_loop.run().await });
bob::run(swap).await?; bob::run(swap).await?;

View File

@ -24,10 +24,7 @@ pub use self::{
state::*, state::*,
swap::{run, run_until}, swap::{run, run_until},
}; };
use crate::{ use crate::{config::Config, database::Database, network::transport::build, seed::Seed};
config::Config, database::Database, network::transport::build, protocol::StartingBalances,
seed::Seed,
};
use libp2p::{core::Multiaddr, identity::Keypair}; use libp2p::{core::Multiaddr, identity::Keypair};
use rand::rngs::OsRng; use rand::rngs::OsRng;
use std::{path::PathBuf, sync::Arc}; use std::{path::PathBuf, sync::Arc};
@ -53,7 +50,7 @@ pub struct Swap {
pub db: Database, pub db: Database,
} }
pub struct SwapFactory { pub struct Builder {
swap_id: Uuid, swap_id: Uuid,
identity: Keypair, identity: Keypair,
peer_id: PeerId, peer_id: PeerId,
@ -64,9 +61,16 @@ pub struct SwapFactory {
bitcoin_wallet: Arc<bitcoin::Wallet>, bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>, monero_wallet: Arc<monero::Wallet>,
init_params: InitParams,
} }
impl SwapFactory { enum InitParams {
None,
New { swap_amounts: SwapAmounts },
}
impl Builder {
pub async fn new( pub async fn new(
seed: Seed, seed: Seed,
config: Config, config: Config,
@ -89,71 +93,83 @@ impl SwapFactory {
listen_address, listen_address,
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
init_params: InitParams::None,
} }
} }
pub async fn new_swap(self, swap_amounts: SwapAmounts) -> Result<(Swap, EventLoop)> { pub fn with_init_params(self, swap_amounts: SwapAmounts) -> Self {
let initial_state = init_alice_state( Self {
swap_amounts.btc, init_params: InitParams::New { swap_amounts },
swap_amounts.xmr, ..self
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 async fn resume(self) -> Result<(Swap, EventLoop)> { pub async fn build(self) -> Result<(Swap, EventLoop)> {
// reopen the existing database match self.init_params {
let db = Database::open(self.db_path.as_path())?; InitParams::New { swap_amounts } => {
let initial_state = init_alice_state(
swap_amounts.btc,
swap_amounts.xmr,
self.bitcoin_wallet.clone(),
self.config,
)
.await?;
let resume_state = if let database::Swap::Alice(state) = db.get_state(self.swap_id)? { let (event_loop, event_loop_handle) = init_alice_event_loop(
state.into() self.listen_address.clone(),
} else { self.identity.clone(),
bail!( self.peer_id.clone(),
"Trying to load swap with id {} for the wrong direction.", )?;
self.swap_id
)
};
let (event_loop, event_loop_handle) = init_alice_event_loop( let db = Database::open(self.db_path.as_path())?;
self.listen_address.clone(),
self.identity.clone(),
self.peer_id.clone(),
)?;
Ok(( Ok((
Swap { Swap {
state: resume_state, event_loop_handle,
event_loop_handle, bitcoin_wallet: self.bitcoin_wallet.clone(),
bitcoin_wallet: self.bitcoin_wallet.clone(), monero_wallet: self.monero_wallet.clone(),
monero_wallet: self.monero_wallet.clone(), config: self.config,
config: self.config, db,
swap_id: self.swap_id, state: initial_state,
db, swap_id: self.swap_id,
}, },
event_loop, 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) = init_alice_event_loop(
self.listen_address.clone(),
self.identity.clone(),
self.peer_id.clone(),
)?;
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,
))
}
}
} }
pub fn peer_id(&self) -> PeerId { pub fn peer_id(&self) -> PeerId {

View File

@ -23,10 +23,7 @@ pub use self::{
state::*, state::*,
swap::{run, run_until}, swap::{run, run_until},
}; };
use crate::{ use crate::{config::Config, database::Database, network::transport::build, seed::Seed};
config::Config, database::Database, network::transport::build, protocol::StartingBalances,
seed::Seed,
};
use libp2p::identity::Keypair; use libp2p::identity::Keypair;
use rand::rngs::OsRng; use rand::rngs::OsRng;
use std::{path::PathBuf, sync::Arc}; use std::{path::PathBuf, sync::Arc};
@ -50,7 +47,7 @@ pub struct Swap {
pub swap_id: Uuid, pub swap_id: Uuid,
} }
pub struct SwapFactory { pub struct Builder {
swap_id: Uuid, swap_id: Uuid,
identity: Keypair, identity: Keypair,
peer_id: PeerId, peer_id: PeerId,
@ -61,9 +58,19 @@ pub struct SwapFactory {
bitcoin_wallet: Arc<bitcoin::Wallet>, bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>, monero_wallet: Arc<monero::Wallet>,
init_params: InitParams,
} }
impl SwapFactory { enum InitParams {
None,
New {
swap_amounts: SwapAmounts,
config: Config,
},
}
impl Builder {
pub fn new( pub fn new(
seed: Seed, seed: Seed,
db_path: PathBuf, db_path: PathBuf,
@ -85,63 +92,75 @@ impl SwapFactory {
alice_peer_id, alice_peer_id,
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
init_params: InitParams::None,
} }
} }
pub async fn new_swap( pub fn with_init_params(self, swap_amounts: SwapAmounts, config: Config) -> Self {
self, Self {
swap_amounts: SwapAmounts, init_params: InitParams::New {
config: Config, swap_amounts,
) -> Result<(bob::Swap, bob::EventLoop)> { config,
let initial_state = self
.make_initial_state(swap_amounts.btc, swap_amounts.xmr, config)
.await?;
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, ..self
)) }
} }
pub async fn resume(self) -> Result<(bob::Swap, bob::EventLoop)> { pub async fn build(self) -> Result<(bob::Swap, bob::EventLoop)> {
// reopen the existing database match self.init_params {
let db = Database::open(self.db_path.as_path())?; 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)? { let (event_loop, event_loop_handle) = self.init_event_loop()?;
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(( Ok((
Swap { Swap {
state: resume_state, state: initial_state,
event_loop_handle, event_loop_handle,
db, db,
bitcoin_wallet: self.bitcoin_wallet.clone(), bitcoin_wallet: self.bitcoin_wallet.clone(),
monero_wallet: self.monero_wallet.clone(), monero_wallet: self.monero_wallet.clone(),
swap_id: self.swap_id, swap_id: self.swap_id,
}, },
event_loop, 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( fn init_event_loop(
&self, &self,
) -> Result<(bob::event_loop::EventLoop, bob::event_loop::EventLoopHandle)> { ) -> Result<(bob::event_loop::EventLoop, bob::event_loop::EventLoopHandle)> {

View File

@ -9,7 +9,7 @@ use swap::{
bitcoin, bitcoin,
config::Config, config::Config,
monero, monero,
protocol::{alice, alice::AliceState, bob, bob::BobState, StartingBalances}, protocol::{alice, alice::AliceState, bob, bob::BobState},
seed::Seed, seed::Seed,
SwapAmounts, SwapAmounts,
}; };
@ -28,12 +28,12 @@ pub struct StartingBalances {
pub struct TestContext { pub struct TestContext {
swap_amounts: SwapAmounts, swap_amounts: SwapAmounts,
alice_swap_factory: Option<alice::SwapFactory>, alice_swap_factory: Option<alice::Builder>,
alice_starting_balances: StartingBalances, alice_starting_balances: StartingBalances,
alice_bitcoin_wallet: Arc<bitcoin::Wallet>, alice_bitcoin_wallet: Arc<bitcoin::Wallet>,
alice_monero_wallet: Arc<monero::Wallet>, alice_monero_wallet: Arc<monero::Wallet>,
bob_swap_factory: Option<bob::SwapFactory>, bob_swap_factory: Option<bob::Builder>,
bob_starting_balances: StartingBalances, bob_starting_balances: StartingBalances,
bob_bitcoin_wallet: Arc<bitcoin::Wallet>, bob_bitcoin_wallet: Arc<bitcoin::Wallet>,
bob_monero_wallet: Arc<monero::Wallet>, bob_monero_wallet: Arc<monero::Wallet>,
@ -45,7 +45,8 @@ impl TestContext {
.alice_swap_factory .alice_swap_factory
.take() .take()
.unwrap() .unwrap()
.new_swap(self.swap_amounts) .with_init_params(self.swap_amounts)
.build()
.await .await
.unwrap(); .unwrap();
@ -59,7 +60,8 @@ impl TestContext {
.bob_swap_factory .bob_swap_factory
.take() .take()
.unwrap() .unwrap()
.new_swap(self.swap_amounts, Config::regtest()) .with_init_params(self.swap_amounts, Config::regtest())
.build()
.await .await
.unwrap(); .unwrap();
@ -73,7 +75,7 @@ impl TestContext {
.alice_swap_factory .alice_swap_factory
.take() .take()
.unwrap() .unwrap()
.resume() .build()
.await .await
.unwrap(); .unwrap();
@ -83,13 +85,7 @@ impl TestContext {
} }
pub async fn recover_bob_from_db(&mut self) -> bob::Swap { pub async fn recover_bob_from_db(&mut self) -> bob::Swap {
let (swap, event_loop) = self let (swap, event_loop) = self.bob_swap_factory.take().unwrap().build().await.unwrap();
.bob_swap_factory
.take()
.unwrap()
.resume()
.await
.unwrap();
tokio::spawn(async move { event_loop.run().await }); tokio::spawn(async move { event_loop.run().await });
@ -283,7 +279,7 @@ where
) )
.await; .await;
let alice_swap_factory = alice::SwapFactory::new( let alice_swap_factory = alice::Builder::new(
Seed::random().unwrap(), Seed::random().unwrap(),
config, config,
Uuid::new_v4(), Uuid::new_v4(),
@ -308,7 +304,7 @@ where
) )
.await; .await;
let bob_swap_factory = bob::SwapFactory::new( let bob_swap_factory = bob::Builder::new(
Seed::random().unwrap(), Seed::random().unwrap(),
tempdir().unwrap().path().to_path_buf(), tempdir().unwrap().path().to_path_buf(),
Uuid::new_v4(), Uuid::new_v4(),