mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-08-08 22:42:35 -04:00
Make --force the default behaviour for manual recovery
Remove the force flag. There is a resume command that tries to gracefully restarts the protocol and tries to execute the happy path. Remove e2e tests which test the --force flag.
This commit is contained in:
parent
54061f941b
commit
f511ff093c
18 changed files with 148 additions and 482 deletions
|
@ -1,22 +1,15 @@
|
|||
use crate::bitcoin::{ExpiredTimelocks, Txid, Wallet};
|
||||
use crate::bitcoin::{Txid, Wallet};
|
||||
use crate::database::{Database, Swap};
|
||||
use crate::protocol::bob::BobState;
|
||||
use anyhow::{bail, Result};
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, thiserror::Error, Clone, Copy)]
|
||||
pub enum Error {
|
||||
#[error("The cancel timelock has not expired yet.")]
|
||||
CancelTimelockNotExpiredYet,
|
||||
}
|
||||
|
||||
pub async fn cancel(
|
||||
swap_id: Uuid,
|
||||
bitcoin_wallet: Arc<Wallet>,
|
||||
db: Database,
|
||||
force: bool,
|
||||
) -> Result<Result<(Txid, BobState), Error>> {
|
||||
) -> Result<(Txid, BobState)> {
|
||||
let state = db.get_state(swap_id)?.try_into_bob()?.into();
|
||||
|
||||
let state6 = match state {
|
||||
|
@ -25,11 +18,12 @@ pub async fn cancel(
|
|||
BobState::XmrLocked(state4) => state4.cancel(),
|
||||
BobState::EncSigSent(state4) => state4.cancel(),
|
||||
BobState::CancelTimelockExpired(state6) => state6,
|
||||
BobState::BtcRefunded(state6) => state6,
|
||||
BobState::BtcCancelled(state6) => state6,
|
||||
|
||||
BobState::Started { .. }
|
||||
| BobState::SwapSetupCompleted(_)
|
||||
| BobState::BtcRedeemed(_)
|
||||
| BobState::BtcCancelled(_)
|
||||
| BobState::BtcRefunded(_)
|
||||
| BobState::XmrRedeemed { .. }
|
||||
| BobState::BtcPunished { .. }
|
||||
| BobState::SafelyAborted => bail!(
|
||||
|
@ -41,25 +35,19 @@ pub async fn cancel(
|
|||
|
||||
tracing::info!(%swap_id, "Manually cancelling swap");
|
||||
|
||||
if !force {
|
||||
tracing::debug!(%swap_id, "Checking if cancel timelock is expired");
|
||||
|
||||
if let ExpiredTimelocks::None = state6.expired_timelock(bitcoin_wallet.as_ref()).await? {
|
||||
return Ok(Err(Error::CancelTimelockNotExpiredYet));
|
||||
let txid = match state6.submit_tx_cancel(bitcoin_wallet.as_ref()).await {
|
||||
Ok(txid) => txid,
|
||||
Err(err) => {
|
||||
if let Some(bdk::Error::TransactionConfirmed) = err.downcast_ref::<bdk::Error>() {
|
||||
tracing::info!("Cancel transaction has already been published and confirmed")
|
||||
};
|
||||
bail!(err);
|
||||
}
|
||||
}
|
||||
|
||||
let txid = if let Ok(tx) = state6.check_for_tx_cancel(bitcoin_wallet.as_ref()).await {
|
||||
tracing::debug!(%swap_id, "Cancel transaction has already been published");
|
||||
|
||||
tx.txid()
|
||||
} else {
|
||||
state6.submit_tx_cancel(bitcoin_wallet.as_ref()).await?
|
||||
};
|
||||
|
||||
let state = BobState::BtcCancelled(state6);
|
||||
let db_state = state.clone().into();
|
||||
db.insert_latest_state(swap_id, Swap::Bob(db_state)).await?;
|
||||
|
||||
Ok(Ok((txid, state)))
|
||||
Ok((txid, state))
|
||||
}
|
||||
|
|
|
@ -171,7 +171,6 @@ where
|
|||
}
|
||||
RawCommand::Cancel {
|
||||
swap_id: SwapId { swap_id },
|
||||
force,
|
||||
bitcoin,
|
||||
} => {
|
||||
let (bitcoin_electrum_rpc_url, bitcoin_target_block) =
|
||||
|
@ -184,7 +183,6 @@ where
|
|||
data_dir: data::data_dir_from(data, is_testnet)?,
|
||||
cmd: Command::Cancel {
|
||||
swap_id,
|
||||
force,
|
||||
bitcoin_electrum_rpc_url,
|
||||
bitcoin_target_block,
|
||||
},
|
||||
|
@ -192,7 +190,6 @@ where
|
|||
}
|
||||
RawCommand::Refund {
|
||||
swap_id: SwapId { swap_id },
|
||||
force,
|
||||
bitcoin,
|
||||
} => {
|
||||
let (bitcoin_electrum_rpc_url, bitcoin_target_block) =
|
||||
|
@ -205,7 +202,6 @@ where
|
|||
data_dir: data::data_dir_from(data, is_testnet)?,
|
||||
cmd: Command::Refund {
|
||||
swap_id,
|
||||
force,
|
||||
bitcoin_electrum_rpc_url,
|
||||
bitcoin_target_block,
|
||||
},
|
||||
|
@ -261,13 +257,11 @@ pub enum Command {
|
|||
},
|
||||
Cancel {
|
||||
swap_id: Uuid,
|
||||
force: bool,
|
||||
bitcoin_electrum_rpc_url: Url,
|
||||
bitcoin_target_block: usize,
|
||||
},
|
||||
Refund {
|
||||
swap_id: Uuid,
|
||||
force: bool,
|
||||
bitcoin_electrum_rpc_url: Url,
|
||||
bitcoin_target_block: usize,
|
||||
},
|
||||
|
@ -376,25 +370,21 @@ enum RawCommand {
|
|||
#[structopt(flatten)]
|
||||
tor: Tor,
|
||||
},
|
||||
/// Try to cancel an ongoing swap (expert users only)
|
||||
/// Force submission of the cancel transaction overriding the protocol state
|
||||
/// machine and blockheight checks (expert users only)
|
||||
Cancel {
|
||||
#[structopt(flatten)]
|
||||
swap_id: SwapId,
|
||||
|
||||
#[structopt(short, long)]
|
||||
force: bool,
|
||||
|
||||
#[structopt(flatten)]
|
||||
bitcoin: Bitcoin,
|
||||
},
|
||||
/// Try to cancel a swap and refund the BTC (expert users only)
|
||||
/// Force submission of the refund transaction overriding the protocol state
|
||||
/// machine and blockheight checks (expert users only)
|
||||
Refund {
|
||||
#[structopt(flatten)]
|
||||
swap_id: SwapId,
|
||||
|
||||
#[structopt(short, long)]
|
||||
force: bool,
|
||||
|
||||
#[structopt(flatten)]
|
||||
bitcoin: Bitcoin,
|
||||
},
|
||||
|
@ -1190,7 +1180,6 @@ mod tests {
|
|||
data_dir: data_dir_path_cli().join(TESTNET),
|
||||
cmd: Command::Cancel {
|
||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||
force: false,
|
||||
bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL_TESTNET)
|
||||
.unwrap(),
|
||||
bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET,
|
||||
|
@ -1206,7 +1195,6 @@ mod tests {
|
|||
data_dir: data_dir_path_cli().join(MAINNET),
|
||||
cmd: Command::Cancel {
|
||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||
force: false,
|
||||
bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL).unwrap(),
|
||||
bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET,
|
||||
},
|
||||
|
@ -1221,7 +1209,6 @@ mod tests {
|
|||
data_dir: data_dir_path_cli().join(TESTNET),
|
||||
cmd: Command::Refund {
|
||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||
force: false,
|
||||
bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL_TESTNET)
|
||||
.unwrap(),
|
||||
bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET,
|
||||
|
@ -1237,7 +1224,6 @@ mod tests {
|
|||
data_dir: data_dir_path_cli().join(MAINNET),
|
||||
cmd: Command::Refund {
|
||||
swap_id: Uuid::from_str(SWAP_ID).unwrap(),
|
||||
force: false,
|
||||
bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL).unwrap(),
|
||||
bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET,
|
||||
},
|
||||
|
|
|
@ -5,45 +5,27 @@ use anyhow::{bail, Result};
|
|||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(thiserror::Error, Debug, Clone, Copy)]
|
||||
#[error("Cannot refund because swap {0} was not cancelled yet. Make sure to cancel the swap before trying to refund.")]
|
||||
pub struct SwapNotCancelledYet(pub Uuid);
|
||||
|
||||
pub async fn refund(
|
||||
swap_id: Uuid,
|
||||
bitcoin_wallet: Arc<Wallet>,
|
||||
db: Database,
|
||||
force: bool,
|
||||
) -> Result<Result<BobState, SwapNotCancelledYet>> {
|
||||
pub async fn refund(swap_id: Uuid, bitcoin_wallet: Arc<Wallet>, db: Database) -> Result<BobState> {
|
||||
let state = db.get_state(swap_id)?.try_into_bob()?.into();
|
||||
|
||||
let state6 = if force {
|
||||
match state {
|
||||
BobState::BtcLocked(state3) => state3.cancel(),
|
||||
BobState::XmrLockProofReceived { state, .. } => state.cancel(),
|
||||
BobState::XmrLocked(state4) => state4.cancel(),
|
||||
BobState::EncSigSent(state4) => state4.cancel(),
|
||||
BobState::CancelTimelockExpired(state6) => state6,
|
||||
BobState::BtcCancelled(state6) => state6,
|
||||
BobState::Started { .. }
|
||||
| BobState::SwapSetupCompleted(_)
|
||||
| BobState::BtcRedeemed(_)
|
||||
| BobState::BtcRefunded(_)
|
||||
| BobState::XmrRedeemed { .. }
|
||||
| BobState::BtcPunished { .. }
|
||||
| BobState::SafelyAborted => bail!(
|
||||
"Cannot refund swap {} because it is in state {} which is not refundable.",
|
||||
swap_id,
|
||||
state
|
||||
),
|
||||
}
|
||||
} else {
|
||||
match state {
|
||||
BobState::BtcCancelled(state6) => state6,
|
||||
_ => {
|
||||
return Ok(Err(SwapNotCancelledYet(swap_id)));
|
||||
}
|
||||
}
|
||||
let state6 = match state {
|
||||
BobState::BtcLocked(state3) => state3.cancel(),
|
||||
BobState::XmrLockProofReceived { state, .. } => state.cancel(),
|
||||
BobState::XmrLocked(state4) => state4.cancel(),
|
||||
BobState::EncSigSent(state4) => state4.cancel(),
|
||||
BobState::CancelTimelockExpired(state6) => state6,
|
||||
BobState::BtcCancelled(state6) => state6,
|
||||
BobState::Started { .. }
|
||||
| BobState::SwapSetupCompleted(_)
|
||||
| BobState::BtcRedeemed(_)
|
||||
| BobState::BtcRefunded(_)
|
||||
| BobState::XmrRedeemed { .. }
|
||||
| BobState::BtcPunished { .. }
|
||||
| BobState::SafelyAborted => bail!(
|
||||
"Cannot refund swap {} because it is in state {} which is not refundable.",
|
||||
swap_id,
|
||||
state
|
||||
),
|
||||
};
|
||||
|
||||
state6.publish_refund_btc(bitcoin_wallet.as_ref()).await?;
|
||||
|
@ -53,5 +35,5 @@ pub async fn refund(
|
|||
|
||||
db.insert_latest_state(swap_id, Swap::Bob(db_state)).await?;
|
||||
|
||||
Ok(Ok(state))
|
||||
Ok(state)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue