diff --git a/coordinator/src/db/hodl_invoice.rs b/coordinator/src/db/hodl_invoice.rs index ad06a7f82..0e44de855 100644 --- a/coordinator/src/db/hodl_invoice.rs +++ b/coordinator/src/db/hodl_invoice.rs @@ -9,6 +9,7 @@ use diesel::AsExpression; use diesel::ExpressionMethods; use diesel::FromSqlRow; use diesel::PgConnection; +use diesel::QueryDsl; use diesel::QueryResult; use diesel::RunQueryDsl; use std::any::TypeId; @@ -53,6 +54,13 @@ pub fn create_hodl_invoice( Ok(()) } +pub fn get_r_hash_by_order_id(conn: &mut PgConnection, order_id: Uuid) -> QueryResult { + hodl_invoices::table + .filter(hodl_invoices::order_id.eq(order_id)) + .select(hodl_invoices::r_hash) + .get_result(conn) +} + pub fn update_hodl_invoice_to_accepted( conn: &mut PgConnection, hash: &str, @@ -87,19 +95,6 @@ pub fn update_hodl_invoice_to_settled( .get_result(conn) } -pub fn update_hodl_invoice_to_failed( - conn: &mut PgConnection, - order_id: Uuid, -) -> QueryResult { - diesel::update(hodl_invoices::table) - .filter(hodl_invoices::order_id.eq(order_id)) - .set(( - hodl_invoices::updated_at.eq(OffsetDateTime::now_utc()), - hodl_invoices::invoice_state.eq(InvoiceState::Failed), - )) - .execute(conn) -} - pub fn update_hodl_invoice_to_failed_by_r_hash( conn: &mut PgConnection, r_hash: String, diff --git a/coordinator/src/trade/mod.rs b/coordinator/src/trade/mod.rs index bb01fe525..a897ee057 100644 --- a/coordinator/src/trade/mod.rs +++ b/coordinator/src/trade/mod.rs @@ -149,7 +149,17 @@ impl TradeExecutor { if params.external_funding.is_some() { // The channel was funded externally. We need to post process the dlc channel // offer. - if let Err(e) = self.post_process_proposal(trader_id, order_id).await { + if let Err(e) = self.settle_invoice(trader_id, order_id).await { + tracing::error!(%trader_id, %order_id, "Failed to settle invoice with provided pre_image. Cancelling offer. Error: {e:#}"); + + if let Err(e) = self.cancel_offer(trader_id).await { + tracing::error!(%trader_id, %order_id, "Failed to cancel offer. Error: {e:#}"); + } + + if let Err(e) = self.cancel_hodl_invoice(order_id).await { + tracing::error!(%trader_id, %order_id, "Failed to cancel hodl invoice. Error: {e:#}"); + } + let message = OrderbookMessage::TraderMessage { trader_id, message: Message::TradeError { @@ -183,20 +193,8 @@ impl TradeExecutor { tracing::error!(%trader_id, %order_id, "Failed to cancel offer. Error: {e:#}"); } - // if the order was externally funded we need to set the hodl invoice to failed. - if let Err(e) = spawn_blocking({ - let pool = self.node.pool.clone(); - move || { - let mut conn = pool.get()?; - db::hodl_invoice::update_hodl_invoice_to_failed(&mut conn, order_id)?; - - anyhow::Ok(()) - } - }) - .await - .expect("task to finish") - { - tracing::error!(%trader_id, %order_id, "Failed to set hodl invoice to failed. Error: {e:#}"); + if let Err(e) = self.cancel_hodl_invoice(order_id).await { + tracing::error!(%trader_id, %order_id, "Failed to cancel hodl_invoice. Error: {e:#}"); } } @@ -221,35 +219,6 @@ impl TradeExecutor { }; } - async fn post_process_proposal(&self, trader: PublicKey, order_id: Uuid) -> Result<()> { - match self.settle_invoice(trader, order_id).await { - Ok(()) => Ok(()), - Err(e) => { - tracing::error!(%trader, %order_id, "Failed to settle invoice with provided pre_image. Cancelling offer. Error: {e:#}"); - - if let Err(e) = self.cancel_offer(trader).await { - tracing::error!(%trader, %order_id, "Failed to cancel offer. Error: {e:#}"); - } - - if let Err(e) = spawn_blocking({ - let pool = self.node.pool.clone(); - move || { - let mut conn = pool.get()?; - db::hodl_invoice::update_hodl_invoice_to_failed(&mut conn, order_id)?; - - anyhow::Ok(()) - } - }) - .await - .expect("task to finish") - { - tracing::error!(%trader, %order_id, "Failed to set hodl invoice to failed. Error: {e:#}"); - } - Err(e) - } - } - } - /// Settles the accepted invoice for the given trader async fn settle_invoice(&self, trader: PublicKey, order_id: Uuid) -> Result<()> { let pre_image = spawn_blocking({ @@ -305,6 +274,22 @@ impl TradeExecutor { Ok(()) } + pub async fn cancel_hodl_invoice(&self, order_id: Uuid) -> Result<()> { + // if the order was externally funded we need to set the hodl invoice to failed. + let r_hash = spawn_blocking({ + let pool = self.node.pool.clone(); + move || { + let mut conn = pool.get()?; + let r_hash = db::hodl_invoice::get_r_hash_by_order_id(&mut conn, order_id)?; + + anyhow::Ok(r_hash) + } + }) + .await??; + + self.node.lnd_bridge.cancel_invoice(r_hash).await + } + /// Execute a trade action according to the coordinator's current trading status with the /// trader. /// diff --git a/crates/lnd-bridge/examples/cancel_invoice_api.rs b/crates/lnd-bridge/examples/cancel_invoice_api.rs index 9395d1b55..860ff9b52 100644 --- a/crates/lnd-bridge/examples/cancel_invoice_api.rs +++ b/crates/lnd-bridge/examples/cancel_invoice_api.rs @@ -9,8 +9,8 @@ async fn main() -> Result<()> { let macaroon = "[enter macroon here]".to_string(); let lnd_bridge = lnd_bridge::LndBridge::new("localhost:18080".to_string(), macaroon, false); - let payment_hash = "".to_string(); - lnd_bridge.cancel_invoice(payment_hash).await?; + let r_hash = "".to_string(); + lnd_bridge.cancel_invoice(r_hash).await?; Ok(()) } diff --git a/crates/lnd-bridge/src/lib.rs b/crates/lnd-bridge/src/lib.rs index 3f67a40a9..089ee9799 100644 --- a/crates/lnd-bridge/src/lib.rs +++ b/crates/lnd-bridge/src/lib.rs @@ -150,7 +150,7 @@ impl LndBridge { Ok(invoice) } - pub async fn cancel_invoice(&self, payment_hash: String) -> Result<()> { + pub async fn cancel_invoice(&self, r_hash: String) -> Result<()> { let builder = self.client.request( Method::POST, format!( @@ -163,7 +163,9 @@ impl LndBridge { let resp = builder .header("content-type", "application/json") .header("Grpc-Metadata-macaroon", self.macaroon.clone()) - .json(&CancelInvoice { payment_hash }) + .json(&CancelInvoice { + payment_hash: r_hash, + }) .send() .await?;