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::bitcoin::EncryptedSignature;
|
||||||
use crate::monero;
|
use crate::monero;
|
||||||
use crate::monero::monero_private_key;
|
use crate::monero::{monero_private_key, TransferProof};
|
||||||
use crate::protocol::alice;
|
use crate::protocol::alice;
|
||||||
use crate::protocol::alice::AliceState;
|
use crate::protocol::alice::AliceState;
|
||||||
use ::bitcoin::hashes::core::fmt::Display;
|
use ::bitcoin::hashes::core::fmt::Display;
|
||||||
@ -18,7 +18,17 @@ pub enum Alice {
|
|||||||
BtcLocked {
|
BtcLocked {
|
||||||
state3: alice::State3,
|
state3: alice::State3,
|
||||||
},
|
},
|
||||||
|
XmrLockTransactionSent {
|
||||||
|
monero_wallet_restore_blockheight: BlockHeight,
|
||||||
|
transfer_proof: TransferProof,
|
||||||
|
state3: alice::State3,
|
||||||
|
},
|
||||||
XmrLocked {
|
XmrLocked {
|
||||||
|
monero_wallet_restore_blockheight: BlockHeight,
|
||||||
|
transfer_proof: TransferProof,
|
||||||
|
state3: alice::State3,
|
||||||
|
},
|
||||||
|
XmrLockTransferProofSent {
|
||||||
monero_wallet_restore_blockheight: BlockHeight,
|
monero_wallet_restore_blockheight: BlockHeight,
|
||||||
state3: alice::State3,
|
state3: alice::State3,
|
||||||
},
|
},
|
||||||
@ -65,10 +75,28 @@ impl From<&AliceState> for Alice {
|
|||||||
AliceState::BtcLocked { state3 } => Alice::BtcLocked {
|
AliceState::BtcLocked { state3 } => Alice::BtcLocked {
|
||||||
state3: state3.as_ref().clone(),
|
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 {
|
AliceState::XmrLocked {
|
||||||
monero_wallet_restore_blockheight,
|
monero_wallet_restore_blockheight,
|
||||||
|
transfer_proof,
|
||||||
state3,
|
state3,
|
||||||
} => Alice::XmrLocked {
|
} => 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,
|
monero_wallet_restore_blockheight: *monero_wallet_restore_blockheight,
|
||||||
state3: state3.as_ref().clone(),
|
state3: state3.as_ref().clone(),
|
||||||
},
|
},
|
||||||
@ -130,10 +158,28 @@ impl From<Alice> for AliceState {
|
|||||||
Alice::BtcLocked { state3 } => AliceState::BtcLocked {
|
Alice::BtcLocked { state3 } => AliceState::BtcLocked {
|
||||||
state3: Box::new(state3),
|
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 {
|
Alice::XmrLocked {
|
||||||
monero_wallet_restore_blockheight,
|
monero_wallet_restore_blockheight,
|
||||||
|
transfer_proof,
|
||||||
state3,
|
state3,
|
||||||
} => AliceState::XmrLocked {
|
} => 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,
|
monero_wallet_restore_blockheight,
|
||||||
state3: Box::new(state3),
|
state3: Box::new(state3),
|
||||||
},
|
},
|
||||||
@ -192,7 +238,11 @@ impl Display for Alice {
|
|||||||
match self {
|
match self {
|
||||||
Alice::Started { .. } => write!(f, "Started"),
|
Alice::Started { .. } => write!(f, "Started"),
|
||||||
Alice::BtcLocked { .. } => f.write_str("Bitcoin locked"),
|
Alice::BtcLocked { .. } => f.write_str("Bitcoin locked"),
|
||||||
|
Alice::XmrLockTransactionSent { .. } => f.write_str("Monero lock transaction sent"),
|
||||||
Alice::XmrLocked { .. } => f.write_str("Monero locked"),
|
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::CancelTimelockExpired { .. } => f.write_str("Cancel timelock is expired"),
|
||||||
Alice::BtcCancelled { .. } => f.write_str("Bitcoin cancel transaction published"),
|
Alice::BtcCancelled { .. } => f.write_str("Bitcoin cancel transaction published"),
|
||||||
Alice::BtcPunishable { .. } => f.write_str("Bitcoin punishable"),
|
Alice::BtcPunishable { .. } => f.write_str("Bitcoin punishable"),
|
||||||
|
@ -22,7 +22,17 @@ pub enum AliceState {
|
|||||||
BtcLocked {
|
BtcLocked {
|
||||||
state3: Box<State3>,
|
state3: Box<State3>,
|
||||||
},
|
},
|
||||||
|
XmrLockTransactionSent {
|
||||||
|
monero_wallet_restore_blockheight: BlockHeight,
|
||||||
|
transfer_proof: TransferProof,
|
||||||
|
state3: Box<State3>,
|
||||||
|
},
|
||||||
XmrLocked {
|
XmrLocked {
|
||||||
|
monero_wallet_restore_blockheight: BlockHeight,
|
||||||
|
transfer_proof: TransferProof,
|
||||||
|
state3: Box<State3>,
|
||||||
|
},
|
||||||
|
XmrLockTransferProofSent {
|
||||||
monero_wallet_restore_blockheight: BlockHeight,
|
monero_wallet_restore_blockheight: BlockHeight,
|
||||||
state3: Box<State3>,
|
state3: Box<State3>,
|
||||||
},
|
},
|
||||||
@ -59,7 +69,11 @@ impl fmt::Display for AliceState {
|
|||||||
match self {
|
match self {
|
||||||
AliceState::Started { .. } => write!(f, "started"),
|
AliceState::Started { .. } => write!(f, "started"),
|
||||||
AliceState::BtcLocked { .. } => write!(f, "btc is locked"),
|
AliceState::BtcLocked { .. } => write!(f, "btc is locked"),
|
||||||
|
AliceState::XmrLockTransactionSent { .. } => write!(f, "xmr lock transaction sent"),
|
||||||
AliceState::XmrLocked { .. } => write!(f, "xmr is locked"),
|
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::EncSigLearned { .. } => write!(f, "encrypted signature is learned"),
|
||||||
AliceState::BtcRedeemed => write!(f, "btc is redeemed"),
|
AliceState::BtcRedeemed => write!(f, "btc is redeemed"),
|
||||||
AliceState::BtcCancelled { .. } => write!(f, "btc is cancelled"),
|
AliceState::BtcCancelled { .. } => write!(f, "btc is cancelled"),
|
||||||
|
@ -5,6 +5,7 @@ use crate::env::Config;
|
|||||||
use crate::protocol::alice;
|
use crate::protocol::alice;
|
||||||
use crate::protocol::alice::event_loop::EventLoopHandle;
|
use crate::protocol::alice::event_loop::EventLoopHandle;
|
||||||
use crate::protocol::alice::AliceState;
|
use crate::protocol::alice::AliceState;
|
||||||
|
use crate::protocol::alice::AliceState::XmrLockTransferProofSent;
|
||||||
use crate::{bitcoin, database, monero};
|
use crate::{bitcoin, database, monero};
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use rand::{CryptoRng, RngCore};
|
use rand::{CryptoRng, RngCore};
|
||||||
@ -88,10 +89,8 @@ async fn next_state(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AliceState::BtcLocked { state3 } => match state3
|
AliceState::BtcLocked { state3 } => {
|
||||||
.expired_timelocks(bitcoin_wallet)
|
match state3.expired_timelocks(bitcoin_wallet).await? {
|
||||||
.await?
|
|
||||||
{
|
|
||||||
ExpiredTimelocks::None => {
|
ExpiredTimelocks::None => {
|
||||||
// Record the current monero wallet block height so we don't have to scan from
|
// 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.
|
// block 0 for scenarios where we create a refund wallet.
|
||||||
@ -101,30 +100,65 @@ async fn next_state(
|
|||||||
.transfer(state3.lock_xmr_transfer_request())
|
.transfer(state3.lock_xmr_transfer_request())
|
||||||
.await?;
|
.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 => {
|
||||||
monero_wallet
|
monero_wallet
|
||||||
.watch_for_transfer(state3.lock_xmr_watch_request(transfer_proof.clone(), 1))
|
.watch_for_transfer(state3.lock_xmr_watch_request(transfer_proof.clone(), 1))
|
||||||
.await?;
|
.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 {
|
AliceState::XmrLocked {
|
||||||
state3,
|
state3,
|
||||||
monero_wallet_restore_blockheight,
|
monero_wallet_restore_blockheight,
|
||||||
|
transfer_proof,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => AliceState::SafelyAborted,
|
_ => AliceState::CancelTimelockExpired {
|
||||||
|
state3,
|
||||||
|
monero_wallet_restore_blockheight,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
|
||||||
AliceState::XmrLocked {
|
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,
|
state3,
|
||||||
monero_wallet_restore_blockheight,
|
monero_wallet_restore_blockheight,
|
||||||
} => {
|
} => {
|
||||||
|
@ -790,8 +790,8 @@ struct Containers<'a> {
|
|||||||
pub mod alice_run_until {
|
pub mod alice_run_until {
|
||||||
use swap::protocol::alice::AliceState;
|
use swap::protocol::alice::AliceState;
|
||||||
|
|
||||||
pub fn is_xmr_locked(state: &AliceState) -> bool {
|
pub fn is_xmr_lock_transaction_sent(state: &AliceState) -> bool {
|
||||||
matches!(state, AliceState::XmrLocked { .. })
|
matches!(state, AliceState::XmrLockTransactionSent { .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_encsig_learned(state: &AliceState) -> bool {
|
pub fn is_encsig_learned(state: &AliceState) -> bool {
|
||||||
|
Loading…
Reference in New Issue
Block a user