mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-04-20 16:06:00 -04:00
Fix multiple things
This commit is contained in:
parent
039db6babe
commit
bc9c3ff402
@ -1,5 +1,5 @@
|
||||
use crate::bitcoin::{parse_rpc_error_code, RpcErrorCode, Wallet};
|
||||
use crate::protocol::bob::BobState;
|
||||
use crate::protocol::bob::{BobState, BtcCancelledByAlice, BtcPunishedWhileRefundError};
|
||||
use crate::protocol::Database;
|
||||
use anyhow::{bail, Result};
|
||||
use bitcoin::Txid;
|
||||
@ -16,12 +16,11 @@ pub async fn cancel_and_refund(
|
||||
};
|
||||
|
||||
let state = match refund(swap_id, bitcoin_wallet, db).await {
|
||||
Ok(s) => {
|
||||
tracing::info!("Refund transaction submitted");
|
||||
s
|
||||
}
|
||||
Ok(s) => s,
|
||||
Err(e) => bail!(e),
|
||||
};
|
||||
|
||||
tracing::info!("Refund transaction submitted");
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
@ -65,24 +64,21 @@ pub async fn cancel(
|
||||
Err(err) => {
|
||||
if let Ok(error_code) = parse_rpc_error_code(&err) {
|
||||
if error_code == i64::from(RpcErrorCode::RpcVerifyError) {
|
||||
if err
|
||||
.to_string()
|
||||
.contains("Failed to broadcast Bitcoin refund transaction")
|
||||
{
|
||||
let txid = state6
|
||||
.construct_tx_cancel()
|
||||
.expect("Error when constructing tx_cancel")
|
||||
.txid();
|
||||
let state = BobState::BtcCancelled(state6);
|
||||
db.insert_latest_state(swap_id, state.clone().into())
|
||||
.await?;
|
||||
tracing::info!("Cancel transaction has already been confirmed on chain. The swap has therefore already been cancelled by Alice.");
|
||||
return Ok((txid, state));
|
||||
} else {
|
||||
tracing::debug!(%error_code, "parse rpc error");
|
||||
tracing::info!("General error trying to submit cancel transaction");
|
||||
}
|
||||
tracing::debug!(%error_code, "parse rpc error");
|
||||
tracing::info!("General error trying to submit cancel transaction");
|
||||
} else if error_code == i64::from(RpcErrorCode::RpcVerifyAlreadyInChain) {
|
||||
tracing::info!("Cancel transaction has already been confirmed on chain");
|
||||
}
|
||||
} else if let Some(error) = err.downcast_ref::<BtcCancelledByAlice>() {
|
||||
let txid = state6
|
||||
.construct_tx_cancel()
|
||||
.expect("Error when constructing tx_cancel")
|
||||
.txid();
|
||||
let state = BobState::BtcCancelled(state6);
|
||||
db.insert_latest_state(swap_id, state.clone().into())
|
||||
.await?;
|
||||
tracing::info!(%error);
|
||||
return Ok((txid, state));
|
||||
}
|
||||
bail!(err);
|
||||
}
|
||||
@ -116,29 +112,24 @@ pub async fn refund(
|
||||
};
|
||||
|
||||
tracing::info!(%swap_id, "Manually refunding swap");
|
||||
|
||||
match state6.publish_refund_btc(bitcoin_wallet.as_ref()).await {
|
||||
Ok(_) => (),
|
||||
Err(refund_error) => {
|
||||
if refund_error
|
||||
.to_string()
|
||||
.contains("Failed to broadcast Bitcoin refund transaction")
|
||||
{
|
||||
Ok(()) => {
|
||||
let state = BobState::BtcRefunded(state6);
|
||||
db.insert_latest_state(swap_id, state.clone().into())
|
||||
.await?;
|
||||
Ok(state)
|
||||
}
|
||||
Err(error) => {
|
||||
if let Some(error) = error.downcast_ref::<BtcPunishedWhileRefundError>() {
|
||||
tracing::info!(%error);
|
||||
let state = BobState::BtcPunished {
|
||||
tx_lock_id: state6.tx_lock_id(),
|
||||
};
|
||||
db.insert_latest_state(swap_id, state.clone().into())
|
||||
.await?;
|
||||
|
||||
tracing::info!("Cannot refund because BTC is punished by Alice.");
|
||||
return Ok(state);
|
||||
}
|
||||
bail!(refund_error);
|
||||
bail!(error);
|
||||
}
|
||||
}
|
||||
let state = BobState::BtcRefunded(state6);
|
||||
db.insert_latest_state(swap_id, state.clone().into())
|
||||
.await?;
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
|
@ -20,6 +20,20 @@ use sha2::Sha256;
|
||||
use sigma_fun::ext::dl_secp256k1_ed25519_eq::CrossCurveDLEQProof;
|
||||
use std::fmt;
|
||||
use uuid::Uuid;
|
||||
#[derive(Debug)]
|
||||
pub struct BtcCancelledByAlice;
|
||||
impl std::fmt::Display for BtcCancelledByAlice {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Cancel transaction has already been confirmed on chain. The swap has therefore already been cancelled by Alice.")
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct BtcPunishedWhileRefundError;
|
||||
impl std::fmt::Display for BtcPunishedWhileRefundError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Cannot refund because BTC is punished.")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
pub enum BobState {
|
||||
@ -663,6 +677,7 @@ impl State6 {
|
||||
|
||||
Ok(tx)
|
||||
}
|
||||
|
||||
pub fn construct_tx_cancel(&self) -> Result<Transaction> {
|
||||
bitcoin::TxCancel::new(
|
||||
&self.tx_lock,
|
||||
@ -674,24 +689,51 @@ impl State6 {
|
||||
.complete_as_bob(self.A, self.b.clone(), self.tx_cancel_sig_a.clone())
|
||||
.context("Failed to complete Bitcoin cancel transaction")
|
||||
}
|
||||
pub fn print_type_of<T>(&self, _: &T) {
|
||||
tracing::debug!("{}", std::any::type_name::<T>())
|
||||
}
|
||||
pub async fn submit_tx_cancel(
|
||||
&self,
|
||||
bitcoin_wallet: &bitcoin::Wallet,
|
||||
) -> Result<(Txid, Subscription)> {
|
||||
let transaction = self.construct_tx_cancel()?;
|
||||
|
||||
let (tx_id, subscription) = bitcoin_wallet.broadcast(transaction, "cancel").await?;
|
||||
|
||||
Ok((tx_id, subscription))
|
||||
match bitcoin_wallet.broadcast(transaction, "cancel").await {
|
||||
Ok((txid, subscription)) => Ok((txid, subscription)),
|
||||
Err(error) => {
|
||||
match error.downcast_ref::<bdk::Error>() {
|
||||
Some(bdk::Error::Electrum(bdk::electrum_client::Error::Protocol(serde_json::Value::String(ref protocol_error))))
|
||||
// UTXO is already spent, swap timeout.
|
||||
if protocol_error.contains("bad-txns-inputs-missingorspent") =>
|
||||
{
|
||||
return Err(anyhow!(BtcCancelledByAlice));
|
||||
}
|
||||
_ => {
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn publish_refund_btc(&self, bitcoin_wallet: &bitcoin::Wallet) -> Result<()> {
|
||||
let signed_tx_refund = self.signed_refund_transaction()?;
|
||||
bitcoin_wallet.broadcast(signed_tx_refund, "refund").await?;
|
||||
|
||||
Ok(())
|
||||
match bitcoin_wallet.broadcast(signed_tx_refund, "refund").await {
|
||||
Ok((_, _)) => Ok(()),
|
||||
Err(error) => {
|
||||
match error.downcast_ref::<bdk::Error>() {
|
||||
Some(bdk::Error::Electrum(bdk::electrum_client::Error::Protocol(serde_json::Value::String(ref protocol_error))))
|
||||
if protocol_error.contains("bad-txns-inputs-missingorspent") =>
|
||||
{
|
||||
return Err(anyhow!(BtcPunishedWhileRefundError));
|
||||
}
|
||||
_ => {
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn signed_refund_transaction(&self) -> Result<Transaction> {
|
||||
let tx_cancel = bitcoin::TxCancel::new(
|
||||
&self.tx_lock,
|
||||
|
@ -76,7 +76,7 @@ async fn alice_manually_punishes_after_bob_dead_and_bob_cancels() {
|
||||
|
||||
let state =
|
||||
cli::cancel_and_refund(bob_swap_id, bob_swap.bitcoin_wallet, bob_swap.db).await?;
|
||||
assert!(matches!(state, BobState::BtcPunished { .. }));
|
||||
assert!(matches!(state, BobState::BtcPunished { .. }));
|
||||
Ok(())
|
||||
})
|
||||
.await;
|
||||
|
Loading…
x
Reference in New Issue
Block a user