From 5e874c3dc9cf1606a3cbbccab3a0d25089a97280 Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Tue, 27 Aug 2024 10:18:28 +0200 Subject: [PATCH] event: store the outpoint when is_manual_broadcast With [1], it's possible to specify `manual_broadcast` for the channel funding transaction. When `is_manual_broadcast` is set to true, the transaction in the `DiscardFunding` event is replaced with a dummy empty transaction. This commit checks if `is_manual_broadcast` is true and stores the funding OutPoint in the DiscardFunding event instead. [1] https://github.com/lightningdevkit/rust-lightning/pull/3024 Link: https://github.com/lightningdevkit/rust-lightning/issues/3164 Suggested-by: TheBlueMatt Signed-off-by: Vincenzo Palazzo --- lightning/src/events/mod.rs | 61 ++++++++++++++++++++++++++---- lightning/src/ln/channelmanager.rs | 15 +++++++- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index d756eff1b..e6de488a0 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -36,12 +36,10 @@ use crate::util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReada use crate::util::string::UntrustedString; use bitcoin::{Transaction, OutPoint}; -use bitcoin::locktime::absolute::LockTime; use bitcoin::script::ScriptBuf; use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::secp256k1::PublicKey; -use bitcoin::transaction::Version; use crate::io; use core::time::Duration; use core::ops::Deref; @@ -50,6 +48,38 @@ use crate::sync::Arc; #[allow(unused_imports)] use crate::prelude::*; +/// `FundingInfo` holds information about a channel's funding transaction. +/// +/// When LDK is set to manual propagation of the funding transaction +/// (via [`ChannelManager::unsafe_manual_funding_transaction_generated`), +/// LDK does not have the full transaction data. Instead, the `OutPoint` +/// for the funding is provided here. +/// +/// [`ChannelManager::unsafe_manual_funding_transaction_generated`]: crate::ln::channelmanager::ChannelManager::unsafe_manual_funding_transaction_generated +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum FundingInfo { + /// The full funding `Transaction`. + Tx { + /// The funding transaction + transaction: Transaction + }, + /// The `OutPoint` of the funding. + OutPoint { + /// The outpoint of the funding + outpoint: transaction::OutPoint + }, +} + +impl_writeable_tlv_based_enum!(FundingInfo, + (0, Tx) => { + (0, transaction, required) + }, + (1, OutPoint) => { + (1, outpoint, required) + } +); + + /// Some information provided on receipt of payment depends on whether the payment received is a /// spontaneous payment or a "conventional" lightning payment that's paying an invoice. #[derive(Clone, Debug, PartialEq, Eq)] @@ -1257,7 +1287,7 @@ pub enum Event { /// The channel_id of the channel which has been closed. channel_id: ChannelId, /// The full transaction received from the user - transaction: Transaction + funding_info: FundingInfo, }, /// Indicates a request to open a new channel by a peer. /// @@ -1541,11 +1571,18 @@ impl Writeable for Event { (9, channel_funding_txo, option), }); }, - &Event::DiscardFunding { ref channel_id, ref transaction } => { + &Event::DiscardFunding { ref channel_id, ref funding_info } => { 11u8.write(writer)?; + + let transaction = if let FundingInfo::Tx { transaction } = funding_info { + Some(transaction) + } else { + None + }; write_tlv_fields!(writer, { (0, channel_id, required), - (2, transaction, required) + (2, transaction, option), + (4, funding_info, required), }) }, &Event::PaymentPathSuccessful { ref payment_id, ref payment_hash, ref path } => { @@ -1924,12 +1961,20 @@ impl MaybeReadable for Event { 11u8 => { let mut f = || { let mut channel_id = ChannelId::new_zero(); - let mut transaction = Transaction{ version: Version::TWO, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; + let mut transaction: Option = None; + let mut funding_info: Option = None; read_tlv_fields!(reader, { (0, channel_id, required), - (2, transaction, required), + (2, transaction, option), + (4, funding_info, option), }); - Ok(Some(Event::DiscardFunding { channel_id, transaction } )) + + let funding_info = if let Some(tx) = transaction { + FundingInfo::Tx { transaction: tx } + } else { + funding_info.ok_or(msgs::DecodeError::InvalidValue)? + }; + Ok(Some(Event::DiscardFunding { channel_id, funding_info } )) }; f() }, diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 167ab0ac8..29020c850 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -32,6 +32,7 @@ use bitcoin::secp256k1::{SecretKey,PublicKey}; use bitcoin::secp256k1::Secp256k1; use bitcoin::{secp256k1, Sequence}; +use crate::events::FundingInfo; use crate::blinded_path::message::{MessageContext, OffersContext}; use crate::blinded_path::NodeIdLookUp; use crate::blinded_path::message::{BlindedMessagePath, ForwardNode}; @@ -3509,6 +3510,7 @@ where let _ = self.chain_monitor.update_channel(funding_txo, &monitor_update); } let mut shutdown_results = Vec::new(); + let mut is_manual_broadcast = false; if let Some(txid) = shutdown_res.unbroadcasted_batch_funding_txid { let mut funding_batch_states = self.funding_batch_states.lock().unwrap(); let affected_channels = funding_batch_states.remove(&txid).into_iter().flatten(); @@ -3518,6 +3520,10 @@ where if let Some(peer_state_mutex) = per_peer_state.get(&counterparty_node_id) { let mut peer_state = peer_state_mutex.lock().unwrap(); if let Some(mut chan) = peer_state.channel_by_id.remove(&channel_id) { + // We override the previous value, so we could change from true -> false, + // but this is fine because if a channel has manual_broadcast set to false + // we should choose the safier condition. + is_manual_broadcast = chan.context().is_manual_broadcast(); update_maps_on_chan_removal!(self, &chan.context()); shutdown_results.push(chan.context_mut().force_shutdown(false, ClosureReason::FundingBatchClosure)); } @@ -3541,9 +3547,14 @@ where channel_funding_txo: shutdown_res.channel_funding_txo, }, None)); - if let Some(transaction) = shutdown_res.unbroadcasted_funding_tx { + let funding_info = if is_manual_broadcast { + shutdown_res.channel_funding_txo.map(|outpoint| FundingInfo::OutPoint{ outpoint }) + } else { + shutdown_res.unbroadcasted_funding_tx.map(|transaction| FundingInfo::Tx{ transaction }) + }; + if let Some(funding_info) = funding_info { pending_events.push_back((events::Event::DiscardFunding { - channel_id: shutdown_res.channel_id, transaction + channel_id: shutdown_res.channel_id, funding_info }, None)); } } -- 2.39.5