ASB aborts if CLI does not lock BTC

Includes a new state that is used to await BTC lock tx finality. Upon starting the swap we initially only wait for the BTC lock tx to be seen in the mempool.
This is guarded by a short timeout (3 mins), because it is assumed that in the current setup (sport_price + execution_setup only triggered upon funds being available already) the lock transaction should be picked up almost instanly after the execution setup succeeded.
pull/582/head
Daniel Karzel 3 years ago
parent c4c798ea20
commit 529de8d5fd
No known key found for this signature in database
GPG Key ID: 30C3FC2E438ADB6E

@ -15,6 +15,9 @@ pub enum Alice {
Started {
state3: alice::State3,
},
BtcLockTransactionSeen {
state3: alice::State3,
},
BtcLocked {
state3: alice::State3,
},
@ -81,6 +84,9 @@ impl From<&AliceState> for Alice {
AliceState::Started { state3 } => Alice::Started {
state3: state3.as_ref().clone(),
},
AliceState::BtcLockTransactionSeen { state3 } => Alice::BtcLockTransactionSeen {
state3: state3.as_ref().clone(),
},
AliceState::BtcLocked { state3 } => Alice::BtcLocked {
state3: state3.as_ref().clone(),
},
@ -179,6 +185,9 @@ impl From<Alice> for AliceState {
Alice::Started { state3 } => AliceState::Started {
state3: Box::new(state3),
},
Alice::BtcLockTransactionSeen { state3 } => AliceState::BtcLockTransactionSeen {
state3: Box::new(state3),
},
Alice::BtcLocked { state3 } => AliceState::BtcLocked {
state3: Box::new(state3),
},
@ -278,6 +287,9 @@ impl fmt::Display for Alice {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Alice::Started { .. } => write!(f, "Started"),
Alice::BtcLockTransactionSeen { .. } => {
write!(f, "Bitcoin lock transaction in mempool")
}
Alice::BtcLocked { .. } => f.write_str("Bitcoin locked"),
Alice::XmrLockTransactionSent { .. } => f.write_str("Monero lock transaction sent"),
Alice::XmrLocked { .. } => f.write_str("Monero locked"),

@ -6,6 +6,7 @@ use time::NumericalStdDurationShort;
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Config {
pub bitcoin_lock_mempool_timeout: Duration,
pub bitcoin_lock_confirmed_timeout: Duration,
pub bitcoin_finality_confirmations: u32,
pub bitcoin_avg_block_time: Duration,
@ -43,7 +44,8 @@ pub struct Regtest;
impl GetConfig for Mainnet {
fn get_config() -> Config {
Config {
bitcoin_lock_confirmed_timeout: 24.hours(),
bitcoin_lock_mempool_timeout: 3.minutes(),
bitcoin_lock_confirmed_timeout: 2.hours(),
bitcoin_finality_confirmations: 2,
bitcoin_avg_block_time: 10.minutes(),
bitcoin_cancel_timelock: CancelTimelock::new(72),
@ -59,7 +61,8 @@ impl GetConfig for Mainnet {
impl GetConfig for Testnet {
fn get_config() -> Config {
Config {
bitcoin_lock_confirmed_timeout: 12.hours(),
bitcoin_lock_mempool_timeout: 3.minutes(),
bitcoin_lock_confirmed_timeout: 1.hours(),
bitcoin_finality_confirmations: 2,
bitcoin_avg_block_time: 10.minutes(),
bitcoin_cancel_timelock: CancelTimelock::new(12),
@ -75,6 +78,7 @@ impl GetConfig for Testnet {
impl GetConfig for Regtest {
fn get_config() -> Config {
Config {
bitcoin_lock_mempool_timeout: 30.seconds(),
bitcoin_lock_confirmed_timeout: 1.minutes(),
bitcoin_finality_confirmations: 1,
bitcoin_avg_block_time: 5.seconds(),

@ -23,6 +23,7 @@ pub async fn cancel(
// In case no XMR has been locked, move to Safely Aborted
AliceState::Started { .. }
| AliceState::BtcLockTransactionSeen { .. }
| AliceState::BtcLocked { .. } => bail!("Cannot cancel swap {} because it is in state {} where no XMR was locked.", swap_id, state),
AliceState::XmrLockTransactionSent { monero_wallet_restore_blockheight, transfer_proof, state3, }

@ -36,7 +36,8 @@ pub async fn punish(
AliceState::Started { .. } => bail!(Error::NoBtcLocked(state)),
// Punish potentially possible (no knowledge of cancel transaction)
AliceState::BtcLocked { state3, .. }
AliceState::BtcLockTransactionSeen { state3 }
| AliceState::BtcLocked { state3, .. }
| AliceState::XmrLockTransactionSent {state3, ..}
| AliceState::XmrLocked {state3, ..}
| AliceState::XmrLockTransferProofSent {state3, ..}

@ -84,6 +84,7 @@ pub async fn redeem(
Ok((txid, state))
}
AliceState::Started { .. }
| AliceState::BtcLockTransactionSeen { .. }
| AliceState::BtcLocked { .. }
| AliceState::XmrLockTransactionSent { .. }
| AliceState::XmrLocked { .. }

@ -39,6 +39,7 @@ pub async fn refund(
// In case no XMR has been locked, move to Safely Aborted
AliceState::Started { .. }
| AliceState::BtcLockTransactionSeen { .. }
| AliceState::BtcLocked { .. } => bail!(Error::NoXmrLocked(state)),
// Refund potentially possible (no knowledge of cancel transaction)

@ -8,7 +8,9 @@ pub async fn safely_abort(swap_id: Uuid, db: Arc<Database>) -> Result<AliceState
let state = db.get_state(swap_id)?.try_into_alice()?.into();
match state {
AliceState::Started { .. } | AliceState::BtcLocked { .. } => {
AliceState::Started { .. }
| AliceState::BtcLockTransactionSeen { .. }
| AliceState::BtcLocked { .. } => {
let state = AliceState::SafelyAborted;
let db_state = (&state).into();

@ -21,6 +21,9 @@ pub enum AliceState {
Started {
state3: Box<State3>,
},
BtcLockTransactionSeen {
state3: Box<State3>,
},
BtcLocked {
state3: Box<State3>,
},
@ -79,6 +82,9 @@ impl fmt::Display for AliceState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AliceState::Started { .. } => write!(f, "started"),
AliceState::BtcLockTransactionSeen { .. } => {
write!(f, "bitcoin lock transaction in mempool")
}
AliceState::BtcLocked { .. } => write!(f, "btc is locked"),
AliceState::XmrLockTransactionSent { .. } => write!(f, "xmr lock transaction sent"),
AliceState::XmrLocked { .. } => write!(f, "xmr is locked"),

@ -70,6 +70,27 @@ where
Ok(match state {
AliceState::Started { state3 } => {
let tx_lock_status = bitcoin_wallet.subscribe_to(state3.tx_lock.clone()).await;
match timeout(
env_config.bitcoin_lock_mempool_timeout,
tx_lock_status.wait_until_seen(),
)
.await
{
Err(_) => {
info!(
minutes = %env_config.bitcoin_lock_mempool_timeout.as_secs_f64() / 60.0,
"TxLock lock was not seen in mempool in time",
);
AliceState::SafelyAborted
}
Ok(res) => {
res?;
AliceState::BtcLockTransactionSeen { state3 }
}
}
}
AliceState::BtcLockTransactionSeen { state3 } => {
let tx_lock_status = bitcoin_wallet.subscribe_to(state3.tx_lock.clone()).await;
match timeout(
env_config.bitcoin_lock_confirmed_timeout,

Loading…
Cancel
Save