|
|
@ -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),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|