Allow Alice to exit execution at a specified state

This commit is contained in:
rishflab 2020-12-02 12:34:47 +11:00
parent 584cc22024
commit 5fef68322a

View File

@ -86,16 +86,38 @@ pub enum AliceState {
SafelyAborted, SafelyAborted,
} }
pub async fn swap<R>(
state: AliceState,
swarm: Swarm,
bitcoin_wallet: Arc<crate::bitcoin::Wallet>,
monero_wallet: Arc<crate::monero::Wallet>,
) -> Result<AliceState>
where
R: RngCore + CryptoRng + Send,
{
run_until(state, is_complete, swarm, bitcoin_wallet, monero_wallet).await
}
// TODO: use macro or generics
pub fn is_complete(state: &AliceState) -> bool {
matches!(state, AliceState::XmrRefunded| AliceState::BtcRedeemed | AliceState::Punished | AliceState::SafelyAborted)
}
// State machine driver for swap execution // State machine driver for swap execution
#[async_recursion] #[async_recursion]
pub async fn swap( pub async fn run_until(
state: AliceState, state: AliceState,
is_state: fn(&AliceState) -> bool,
mut swarm: Swarm, mut swarm: Swarm,
bitcoin_wallet: Arc<crate::bitcoin::Wallet>, bitcoin_wallet: Arc<crate::bitcoin::Wallet>,
monero_wallet: Arc<crate::monero::Wallet>, monero_wallet: Arc<crate::monero::Wallet>,
config: Config, config: Config,
) -> Result<AliceState> { ) -> Result<AliceState> {
match state { if is_state(&state) {
Ok(state)
} else {
match state {
AliceState::Started { AliceState::Started {
amounts, amounts,
a, a,
@ -113,12 +135,13 @@ pub async fn swap(
) )
.await?; .await?;
swap( run_until(
AliceState::Negotiated { AliceState::Negotiated {
channel, channel,
amounts, amounts,
state3, state3,
}, },
is_state,
swarm, swarm,
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
@ -134,12 +157,13 @@ pub async fn swap(
let _ = wait_for_locked_bitcoin(state3.tx_lock.txid(), bitcoin_wallet.clone(), config) let _ = wait_for_locked_bitcoin(state3.tx_lock.txid(), bitcoin_wallet.clone(), config)
.await?; .await?;
swap( run_until(
AliceState::BtcLocked { AliceState::BtcLocked {
channel, channel,
amounts, amounts,
state3, state3,
}, },
is_state,
swarm, swarm,
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
@ -161,8 +185,9 @@ pub async fn swap(
) )
.await?; .await?;
swap( run_until(
AliceState::XmrLocked { state3 }, AliceState::XmrLocked { state3 },
is_state,
swarm, swarm,
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
@ -175,11 +200,12 @@ pub async fn swap(
// step fails // step fails
match wait_for_bitcoin_encrypted_signature(&mut swarm).await { match wait_for_bitcoin_encrypted_signature(&mut swarm).await {
Ok(encrypted_signature) => { Ok(encrypted_signature) => {
swap( run_until(
AliceState::EncSignLearned { AliceState::EncSignLearned {
state3, state3,
encrypted_signature, encrypted_signature,
}, },
is_state,
swarm, swarm,
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
@ -188,8 +214,9 @@ pub async fn swap(
.await .await
} }
Err(_) => { Err(_) => {
swap( run_until(
AliceState::WaitingToCancel { state3 }, AliceState::WaitingToCancel { state3 },
is_state,
swarm, swarm,
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
@ -213,8 +240,9 @@ pub async fn swap(
) { ) {
Ok(tx) => tx, Ok(tx) => tx,
Err(_) => { Err(_) => {
return swap( return run_until(
AliceState::WaitingToCancel { state3 }, AliceState::WaitingToCancel { state3 },
is_state,
swarm, swarm,
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
@ -230,8 +258,9 @@ pub async fn swap(
publish_bitcoin_redeem_transaction(signed_tx_redeem, bitcoin_wallet.clone(), config) publish_bitcoin_redeem_transaction(signed_tx_redeem, bitcoin_wallet.clone(), config)
.await?; .await?;
swap( run_until(
AliceState::BtcRedeemed, AliceState::BtcRedeemed,
is_state,
swarm, swarm,
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
@ -250,8 +279,9 @@ pub async fn swap(
) )
.await?; .await?;
swap( run_until(
AliceState::BtcCancelled { state3, tx_cancel }, AliceState::BtcCancelled { state3, tx_cancel },
is_state,
swarm, swarm,
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
@ -276,8 +306,9 @@ pub async fn swap(
// TODO(Franck): Review error handling // TODO(Franck): Review error handling
match published_refund_tx { match published_refund_tx {
None => { None => {
swap( run_until(
AliceState::BtcPunishable { tx_refund, state3 }, AliceState::BtcPunishable { tx_refund, state3 },
is_state,
swarm, swarm,
bitcoin_wallet.clone(), bitcoin_wallet.clone(),
monero_wallet, monero_wallet,
@ -286,12 +317,13 @@ pub async fn swap(
.await .await
} }
Some(published_refund_tx) => { Some(published_refund_tx) => {
swap( run_until(
AliceState::BtcRefunded { AliceState::BtcRefunded {
tx_refund, tx_refund,
published_refund_tx, published_refund_tx,
state3, state3,
}, },
is_state,
swarm, swarm,
bitcoin_wallet.clone(), bitcoin_wallet.clone(),
monero_wallet, monero_wallet,
@ -345,8 +377,9 @@ pub async fn swap(
match select(punish_tx_finalised, refund_tx_seen).await { match select(punish_tx_finalised, refund_tx_seen).await {
Either::Left(_) => { Either::Left(_) => {
swap( run_until(
AliceState::Punished, AliceState::Punished,
is_state,
swarm, swarm,
bitcoin_wallet.clone(), bitcoin_wallet.clone(),
monero_wallet, monero_wallet,
@ -355,12 +388,13 @@ pub async fn swap(
.await .await
} }
Either::Right((published_refund_tx, _)) => { Either::Right((published_refund_tx, _)) => {
swap( run_until(
AliceState::BtcRefunded { AliceState::BtcRefunded {
tx_refund, tx_refund,
published_refund_tx, published_refund_tx,
state3, state3,
}, },
is_state,
swarm, swarm,
bitcoin_wallet.clone(), bitcoin_wallet.clone(),
monero_wallet, monero_wallet,
@ -375,4 +409,5 @@ pub async fn swap(
AliceState::Punished => Ok(AliceState::Punished), AliceState::Punished => Ok(AliceState::Punished),
AliceState::SafelyAborted => Ok(AliceState::SafelyAborted), AliceState::SafelyAborted => Ok(AliceState::SafelyAborted),
} }
}
} }