From 41362aaf5cde2c2d1cf35f89b6dde6d6ff8ba185 Mon Sep 17 00:00:00 2001 From: ok300 <106775972+ok300@users.noreply.github.com> Date: Mon, 2 Oct 2023 17:56:54 +0200 Subject: [PATCH 1/2] Reverse swap status defaults to Initial when empty --- libs/sdk-core/src/persist/reverseswap.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/sdk-core/src/persist/reverseswap.rs b/libs/sdk-core/src/persist/reverseswap.rs index 113cfe18b..afa7413fd 100644 --- a/libs/sdk-core/src/persist/reverseswap.rs +++ b/libs/sdk-core/src/persist/reverseswap.rs @@ -1,7 +1,6 @@ use super::db::SqliteStorage; use crate::{FullReverseSwapInfo, ReverseSwapInfoCached, ReverseSwapStatus}; use anyhow::Result; -use rusqlite::types::FromSqlError; use rusqlite::{named_params, Row}; impl SqliteStorage { @@ -47,7 +46,7 @@ impl SqliteStorage { debug!("Persisting new status for reverse swap {id} to be {status:?}"); self.get_connection()?.execute( - "UPDATE reverse_swaps_info SET status=:status where id=:id", + "INSERT OR REPLACE INTO reverse_swaps_info VALUES(:id, :status)", named_params! { ":status": serde_json::to_value(status)?, ":id": id, @@ -82,8 +81,10 @@ impl SqliteStorage { sat_per_vbyte: row.get("sat_per_vbyte")?, redeem_script: row.get("redeem_script")?, cache: ReverseSwapInfoCached { + // The status is stored in the main DB, which is empty when the node is restored. + // We therefore default to the Initial state. This will be updated at the end of sync(). status: serde_json::from_value(row.get("status")?) - .map_err(|_| FromSqlError::InvalidType)?, + .unwrap_or(ReverseSwapStatus::Initial), }, }) } From 247392eb0514ab2517282cc7703c20a20be0f03b Mon Sep 17 00:00:00 2001 From: ok300 <106775972+ok300@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:54:51 +0200 Subject: [PATCH 2/2] Handle Cancelled edge cases for reverse swap --- libs/sdk-core/src/breez_services.rs | 4 +++- libs/sdk-core/src/models.rs | 2 ++ libs/sdk-core/src/reverseswap.rs | 35 ++++++++++++++++++++++------- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/libs/sdk-core/src/breez_services.rs b/libs/sdk-core/src/breez_services.rs index 3e0b58f15..1f7fe81c1 100644 --- a/libs/sdk-core/src/breez_services.rs +++ b/libs/sdk-core/src/breez_services.rs @@ -1182,10 +1182,12 @@ impl BreezServices { r#" info, breez_sdk_core::input_parser=warn, + breez_sdk_core::backup=info, + breez_sdk_core::persist::reverseswap=info, + breez_sdk_core::reverseswap=info, gl_client=warn, h2=warn, hyper=warn, - breez_sdk_core::reverseswap=info, lightning_signer=warn, reqwest=warn, rustls=warn, diff --git a/libs/sdk-core/src/models.rs b/libs/sdk-core/src/models.rs index 3a78e1b98..f6b455cb1 100644 --- a/libs/sdk-core/src/models.rs +++ b/libs/sdk-core/src/models.rs @@ -364,6 +364,8 @@ impl From for ReverseSwapInfo { #[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)] pub enum ReverseSwapStatus { /// HODL invoice payment is not completed yet + /// + /// This is also the temporary status of a reverse swap when restoring a node, until `sync` finishes. Initial = 0, /// HODL invoice payment was successfully triggered and confirmed by Boltz, but the reverse swap diff --git a/libs/sdk-core/src/reverseswap.rs b/libs/sdk-core/src/reverseswap.rs index 5dfc319d4..450b2b67b 100644 --- a/libs/sdk-core/src/reverseswap.rs +++ b/libs/sdk-core/src/reverseswap.rs @@ -6,8 +6,8 @@ use crate::chain::{get_utxos, ChainService, MempoolSpace}; use crate::models::{ReverseSwapServiceAPI, ReverseSwapperRoutingAPI}; use crate::ReverseSwapStatus::*; use crate::{ - BreezEvent, Config, FullReverseSwapInfo, NodeAPI, ReverseSwapInfoCached, ReverseSwapPairInfo, - ReverseSwapStatus, + BreezEvent, Config, FullReverseSwapInfo, NodeAPI, PaymentStatus, ReverseSwapInfoCached, + ReverseSwapPairInfo, ReverseSwapStatus, }; use anyhow::{anyhow, ensure, Result}; use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR; @@ -449,11 +449,17 @@ impl BTCSendSwap { "Tried to get status for non-monitored reverse swap" ); + let payment_hash_hex = &rsi.get_preimage_hash().to_hex(); + let payment_status = self.persister.get_payment_by_hash(payment_hash_hex)?; + if let Some(ref payment) = payment_status { + if payment.status == PaymentStatus::Failed { + warn!("Payment failed for reverse swap {}", rsi.id); + return Ok(Some(Cancelled)); + } + } + let new_status = match ¤t_status { - Initial => match self - .persister - .get_payment_by_hash(&rsi.get_preimage_hash().to_hex())? - { + Initial => match payment_status { Some(_) => Some(InProgress), None => match self .reverse_swap_service_api @@ -469,11 +475,24 @@ impl BTCSendSwap { _ => None, }, }, - InProgress | CompletedSeen => match self.get_claim_tx_status(rsi).await? { - TxStatus::Unknown => None, + InProgress => match self.get_claim_tx_status(rsi).await? { + TxStatus::Unknown => { + let block_height = self.chain_service.current_tip().await?; + match block_height >= rsi.timeout_block_height { + true => { + warn!("Reverse swap {} crossed the timeout block height", rsi.id); + Some(Cancelled) + } + false => None, + } + } TxStatus::Mempool => Some(CompletedSeen), TxStatus::Confirmed => Some(CompletedConfirmed), }, + CompletedSeen => match self.get_claim_tx_status(rsi).await? { + TxStatus::Confirmed => Some(CompletedConfirmed), + _ => None, + }, _ => None, };