mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Wait for lock tx and send transfer proof in separate state
Sending the transfer transaction in a distinct state helps ensuring that we do not send the Monero lock transaction twice in a restart scenario. Waiting for the first transaction confirmation in a separate state helps ensuring that we send the transfer proof in a restart scenario.
This commit is contained in:
parent
dfd69c9c80
commit
183e8f02de
@ -1,6 +1,6 @@
|
||||
use crate::bitcoin::EncryptedSignature;
|
||||
use crate::monero;
|
||||
use crate::monero::monero_private_key;
|
||||
use crate::monero::{monero_private_key, TransferProof};
|
||||
use crate::protocol::alice;
|
||||
use crate::protocol::alice::AliceState;
|
||||
use ::bitcoin::hashes::core::fmt::Display;
|
||||
@ -18,7 +18,17 @@ pub enum Alice {
|
||||
BtcLocked {
|
||||
state3: alice::State3,
|
||||
},
|
||||
XmrLockTransactionSent {
|
||||
monero_wallet_restore_blockheight: BlockHeight,
|
||||
transfer_proof: TransferProof,
|
||||
state3: alice::State3,
|
||||
},
|
||||
XmrLocked {
|
||||
monero_wallet_restore_blockheight: BlockHeight,
|
||||
transfer_proof: TransferProof,
|
||||
state3: alice::State3,
|
||||
},
|
||||
XmrLockTransferProofSent {
|
||||
monero_wallet_restore_blockheight: BlockHeight,
|
||||
state3: alice::State3,
|
||||
},
|
||||
@ -65,10 +75,28 @@ impl From<&AliceState> for Alice {
|
||||
AliceState::BtcLocked { state3 } => Alice::BtcLocked {
|
||||
state3: state3.as_ref().clone(),
|
||||
},
|
||||
AliceState::XmrLockTransactionSent {
|
||||
monero_wallet_restore_blockheight,
|
||||
transfer_proof,
|
||||
state3,
|
||||
} => Alice::XmrLockTransactionSent {
|
||||
monero_wallet_restore_blockheight: *monero_wallet_restore_blockheight,
|
||||
transfer_proof: transfer_proof.clone(),
|
||||
state3: state3.as_ref().clone(),
|
||||
},
|
||||
AliceState::XmrLocked {
|
||||
monero_wallet_restore_blockheight,
|
||||
transfer_proof,
|
||||
state3,
|
||||
} => Alice::XmrLocked {
|
||||
monero_wallet_restore_blockheight: *monero_wallet_restore_blockheight,
|
||||
transfer_proof: transfer_proof.clone(),
|
||||
state3: state3.as_ref().clone(),
|
||||
},
|
||||
AliceState::XmrLockTransferProofSent {
|
||||
monero_wallet_restore_blockheight,
|
||||
state3,
|
||||
} => Alice::XmrLockTransferProofSent {
|
||||
monero_wallet_restore_blockheight: *monero_wallet_restore_blockheight,
|
||||
state3: state3.as_ref().clone(),
|
||||
},
|
||||
@ -130,10 +158,28 @@ impl From<Alice> for AliceState {
|
||||
Alice::BtcLocked { state3 } => AliceState::BtcLocked {
|
||||
state3: Box::new(state3),
|
||||
},
|
||||
Alice::XmrLockTransactionSent {
|
||||
monero_wallet_restore_blockheight,
|
||||
transfer_proof,
|
||||
state3,
|
||||
} => AliceState::XmrLockTransactionSent {
|
||||
monero_wallet_restore_blockheight,
|
||||
transfer_proof,
|
||||
state3: Box::new(state3),
|
||||
},
|
||||
Alice::XmrLocked {
|
||||
monero_wallet_restore_blockheight,
|
||||
transfer_proof,
|
||||
state3,
|
||||
} => AliceState::XmrLocked {
|
||||
monero_wallet_restore_blockheight,
|
||||
transfer_proof,
|
||||
state3: Box::new(state3),
|
||||
},
|
||||
Alice::XmrLockTransferProofSent {
|
||||
monero_wallet_restore_blockheight,
|
||||
state3,
|
||||
} => AliceState::XmrLockTransferProofSent {
|
||||
monero_wallet_restore_blockheight,
|
||||
state3: Box::new(state3),
|
||||
},
|
||||
@ -192,7 +238,11 @@ impl Display for Alice {
|
||||
match self {
|
||||
Alice::Started { .. } => write!(f, "Started"),
|
||||
Alice::BtcLocked { .. } => f.write_str("Bitcoin locked"),
|
||||
Alice::XmrLockTransactionSent { .. } => f.write_str("Monero lock transaction sent"),
|
||||
Alice::XmrLocked { .. } => f.write_str("Monero locked"),
|
||||
Alice::XmrLockTransferProofSent { .. } => {
|
||||
f.write_str("Monero lock transfer proof sent")
|
||||
}
|
||||
Alice::CancelTimelockExpired { .. } => f.write_str("Cancel timelock is expired"),
|
||||
Alice::BtcCancelled { .. } => f.write_str("Bitcoin cancel transaction published"),
|
||||
Alice::BtcPunishable { .. } => f.write_str("Bitcoin punishable"),
|
||||
|
@ -22,7 +22,17 @@ pub enum AliceState {
|
||||
BtcLocked {
|
||||
state3: Box<State3>,
|
||||
},
|
||||
XmrLockTransactionSent {
|
||||
monero_wallet_restore_blockheight: BlockHeight,
|
||||
transfer_proof: TransferProof,
|
||||
state3: Box<State3>,
|
||||
},
|
||||
XmrLocked {
|
||||
monero_wallet_restore_blockheight: BlockHeight,
|
||||
transfer_proof: TransferProof,
|
||||
state3: Box<State3>,
|
||||
},
|
||||
XmrLockTransferProofSent {
|
||||
monero_wallet_restore_blockheight: BlockHeight,
|
||||
state3: Box<State3>,
|
||||
},
|
||||
@ -59,7 +69,11 @@ impl fmt::Display for AliceState {
|
||||
match self {
|
||||
AliceState::Started { .. } => write!(f, "started"),
|
||||
AliceState::BtcLocked { .. } => write!(f, "btc is locked"),
|
||||
AliceState::XmrLockTransactionSent { .. } => write!(f, "xmr lock transaction sent"),
|
||||
AliceState::XmrLocked { .. } => write!(f, "xmr is locked"),
|
||||
AliceState::XmrLockTransferProofSent { .. } => {
|
||||
write!(f, "xmr lock transfer proof sent")
|
||||
}
|
||||
AliceState::EncSigLearned { .. } => write!(f, "encrypted signature is learned"),
|
||||
AliceState::BtcRedeemed => write!(f, "btc is redeemed"),
|
||||
AliceState::BtcCancelled { .. } => write!(f, "btc is cancelled"),
|
||||
|
@ -5,6 +5,7 @@ use crate::env::Config;
|
||||
use crate::protocol::alice;
|
||||
use crate::protocol::alice::event_loop::EventLoopHandle;
|
||||
use crate::protocol::alice::AliceState;
|
||||
use crate::protocol::alice::AliceState::XmrLockTransferProofSent;
|
||||
use crate::{bitcoin, database, monero};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
@ -88,43 +89,76 @@ async fn next_state(
|
||||
}
|
||||
}
|
||||
}
|
||||
AliceState::BtcLocked { state3 } => match state3
|
||||
.expired_timelocks(bitcoin_wallet)
|
||||
.await?
|
||||
{
|
||||
AliceState::BtcLocked { state3 } => {
|
||||
match state3.expired_timelocks(bitcoin_wallet).await? {
|
||||
ExpiredTimelocks::None => {
|
||||
// Record the current monero wallet block height so we don't have to scan from
|
||||
// block 0 for scenarios where we create a refund wallet.
|
||||
let monero_wallet_restore_blockheight = monero_wallet.block_height().await?;
|
||||
|
||||
let transfer_proof = monero_wallet
|
||||
.transfer(state3.lock_xmr_transfer_request())
|
||||
.await?;
|
||||
|
||||
AliceState::XmrLockTransactionSent {
|
||||
state3,
|
||||
transfer_proof,
|
||||
monero_wallet_restore_blockheight,
|
||||
}
|
||||
}
|
||||
_ => AliceState::SafelyAborted,
|
||||
}
|
||||
}
|
||||
AliceState::XmrLockTransactionSent {
|
||||
monero_wallet_restore_blockheight,
|
||||
transfer_proof,
|
||||
state3,
|
||||
} => match state3.expired_timelocks(bitcoin_wallet).await? {
|
||||
ExpiredTimelocks::None => {
|
||||
// Record the current monero wallet block height so we don't have to scan from
|
||||
// block 0 for scenarios where we create a refund wallet.
|
||||
let monero_wallet_restore_blockheight = monero_wallet.block_height().await?;
|
||||
|
||||
let transfer_proof = monero_wallet
|
||||
.transfer(state3.lock_xmr_transfer_request())
|
||||
.await?;
|
||||
|
||||
monero_wallet
|
||||
.watch_for_transfer(state3.lock_xmr_watch_request(transfer_proof.clone(), 1))
|
||||
.await?;
|
||||
|
||||
// TODO: Waiting for XMR confirmations should be done in a separate
|
||||
// state! We have to record that Alice has already sent the transaction.
|
||||
// Otherwise Alice might publish the lock tx twice!
|
||||
|
||||
event_loop_handle
|
||||
.send_transfer_proof(transfer_proof.clone())
|
||||
.await?;
|
||||
|
||||
monero_wallet
|
||||
.watch_for_transfer(state3.lock_xmr_watch_request(transfer_proof, 10))
|
||||
.await?;
|
||||
|
||||
AliceState::XmrLocked {
|
||||
state3,
|
||||
monero_wallet_restore_blockheight,
|
||||
transfer_proof,
|
||||
}
|
||||
}
|
||||
_ => AliceState::SafelyAborted,
|
||||
_ => AliceState::CancelTimelockExpired {
|
||||
state3,
|
||||
monero_wallet_restore_blockheight,
|
||||
},
|
||||
},
|
||||
|
||||
AliceState::XmrLocked {
|
||||
state3,
|
||||
transfer_proof,
|
||||
monero_wallet_restore_blockheight,
|
||||
} => match state3.expired_timelocks(bitcoin_wallet).await? {
|
||||
ExpiredTimelocks::None => {
|
||||
event_loop_handle
|
||||
.send_transfer_proof(transfer_proof.clone())
|
||||
.await?;
|
||||
|
||||
// TODO: Handle this upon refund instead.
|
||||
// Make sure that the balance of the created wallet is unlocked instead of
|
||||
// watching for transfer.
|
||||
monero_wallet
|
||||
.watch_for_transfer(state3.lock_xmr_watch_request(transfer_proof, 10))
|
||||
.await?;
|
||||
|
||||
XmrLockTransferProofSent {
|
||||
state3,
|
||||
monero_wallet_restore_blockheight,
|
||||
}
|
||||
}
|
||||
_ => AliceState::CancelTimelockExpired {
|
||||
state3,
|
||||
monero_wallet_restore_blockheight,
|
||||
},
|
||||
},
|
||||
AliceState::XmrLockTransferProofSent {
|
||||
state3,
|
||||
monero_wallet_restore_blockheight,
|
||||
} => {
|
||||
|
@ -790,8 +790,8 @@ struct Containers<'a> {
|
||||
pub mod alice_run_until {
|
||||
use swap::protocol::alice::AliceState;
|
||||
|
||||
pub fn is_xmr_locked(state: &AliceState) -> bool {
|
||||
matches!(state, AliceState::XmrLocked { .. })
|
||||
pub fn is_xmr_lock_transaction_sent(state: &AliceState) -> bool {
|
||||
matches!(state, AliceState::XmrLockTransactionSent { .. })
|
||||
}
|
||||
|
||||
pub fn is_encsig_learned(state: &AliceState) -> bool {
|
||||
|
Loading…
Reference in New Issue
Block a user