Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion lightning/src/chain/channelmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3906,6 +3906,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
}

fn promote_funding(&mut self, new_funding_txid: Txid) -> Result<(), ()> {
let prev_funding_txid = self.funding.funding_txid();

let new_funding = self
.pending_funding
.iter_mut()
Expand All @@ -3921,9 +3923,20 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
self.funding.prev_holder_commitment_tx.clone(),
);

let no_further_updates_allowed = self.no_further_updates_allowed();

// The swap above places the previous `FundingScope` into `pending_funding`.
for funding in self.pending_funding.drain(..) {
self.outputs_to_watch.remove(&funding.funding_txid());
let funding_txid = funding.funding_txid();
self.outputs_to_watch.remove(&funding_txid);
if no_further_updates_allowed && funding_txid != prev_funding_txid {
self.pending_events.push(Event::DiscardFunding {
channel_id: self.channel_id,
funding_info: crate::events::FundingInfo::OutPoint {
outpoint: funding.funding_outpoint(),
},
});
}
}
if let Some((alternative_funding_txid, _)) = self.alternative_funding_confirmed.take() {
// In exceedingly rare cases, it's possible there was a reorg that caused a potential funding to
Expand Down
4 changes: 4 additions & 0 deletions lightning/src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1502,6 +1502,10 @@ pub enum Event {
/// Used to indicate to the user that they can abandon the funding transaction and recycle the
/// inputs for another purpose.
///
/// When splicing, users can expect to receive an event for each negotiated splice transaction
/// that did not become locked. The negotiated splice transaction that became locked can be
/// obtained via [`Event::ChannelReady::funding_txo`].
///
/// This event is not guaranteed to be generated for channels that are closed due to a restart.
///
/// # Failure Behavior and Persistence
Expand Down
91 changes: 61 additions & 30 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ use crate::chain::transaction::{OutPoint, TransactionData};
use crate::chain::BestBlock;
use crate::events::bump_transaction::BASE_INPUT_WEIGHT;
use crate::events::ClosureReason;
#[cfg(splicing)]
use crate::events::FundingInfo;
use crate::ln::chan_utils;
#[cfg(splicing)]
use crate::ln::chan_utils::FUNDING_TRANSACTION_WITNESS_WEIGHT;
Expand Down Expand Up @@ -6086,16 +6088,35 @@ where

#[cfg(splicing)]
macro_rules! promote_splice_funding {
($self: expr, $funding: expr) => {
($self: expr, $funding: expr) => {{
let prev_funding_txid = $self.funding.get_funding_txid();
if let Some(scid) = $self.funding.short_channel_id {
$self.context.historical_scids.push(scid);
}
core::mem::swap(&mut $self.funding, $funding);
$self.interactive_tx_signing_session = None;
$self.pending_splice = None;
$self.pending_funding.clear();
$self.context.announcement_sigs_state = AnnouncementSigsState::NotSent;
};

// The swap above places the previous `FundingScope` into `pending_funding`.
let discarded_funding = $self
.pending_funding
.drain(..)
.filter(|funding| funding.get_funding_txid() != prev_funding_txid)
.map(|mut funding| {
funding
.funding_transaction
.take()
.map(|tx| FundingInfo::Tx { transaction: tx })
.unwrap_or_else(|| FundingInfo::OutPoint {
outpoint: funding
.get_funding_txo()
.expect("Negotiated splices must have a known funding outpoint"),
})
})
.collect::<Vec<_>>();
discarded_funding
}};
}

#[cfg(any(test, fuzzing))]
Expand Down Expand Up @@ -6179,6 +6200,7 @@ pub struct SpliceFundingPromotion {
pub funding_txo: OutPoint,
pub monitor_update: Option<ChannelMonitorUpdate>,
pub announcement_sigs: Option<msgs::AnnouncementSignatures>,
pub discarded_funding: Vec<FundingInfo>,
}

impl<SP: Deref> FundedChannel<SP>
Expand Down Expand Up @@ -8634,23 +8656,25 @@ where
log_trace!(logger, "Regenerating latest commitment update in channel {} with{} {} update_adds, {} update_fulfills, {} update_fails, and {} update_fail_malformeds",
&self.context.channel_id(), if update_fee.is_some() { " update_fee," } else { "" },
update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len(), update_fail_malformed_htlcs.len());
let commitment_signed =
if let Ok(update) = self.send_commitment_no_state_update(logger) {
if self.context.signer_pending_commitment_update {
log_trace!(
logger,
"Commitment update generated: clearing signer_pending_commitment_update"
);
self.context.signer_pending_commitment_update = false;
}
update
} else {
if !self.context.signer_pending_commitment_update {
log_trace!(logger, "Commitment update awaiting signer: setting signer_pending_commitment_update");
self.context.signer_pending_commitment_update = true;
}
return Err(());
};
let commitment_signed = if let Ok(update) = self.send_commitment_no_state_update(logger) {
if self.context.signer_pending_commitment_update {
log_trace!(
logger,
"Commitment update generated: clearing signer_pending_commitment_update"
);
self.context.signer_pending_commitment_update = false;
}
update
} else {
if !self.context.signer_pending_commitment_update {
log_trace!(
logger,
"Commitment update awaiting signer: setting signer_pending_commitment_update"
);
self.context.signer_pending_commitment_update = true;
}
return Err(());
};
Ok(msgs::CommitmentUpdate {
update_add_htlcs,
update_fulfill_htlcs,
Expand Down Expand Up @@ -9954,16 +9978,16 @@ where
&self.context.channel_id,
);

{
let discarded_funding = {
// Scope `funding` since it is swapped within `promote_splice_funding` and we don't want
// to unintentionally use it.
let funding = self
.pending_funding
.iter_mut()
.find(|funding| funding.get_funding_txid() == Some(splice_txid))
.unwrap();
promote_splice_funding!(self, funding);
}
promote_splice_funding!(self, funding)
};

let funding_txo = self
.funding
Expand All @@ -9984,7 +10008,12 @@ where
let announcement_sigs =
self.get_announcement_sigs(node_signer, chain_hash, user_config, block_height, logger);

Some(SpliceFundingPromotion { funding_txo, monitor_update, announcement_sigs })
Some(SpliceFundingPromotion {
funding_txo,
monitor_update,
announcement_sigs,
discarded_funding,
})
}

/// When a transaction is confirmed, we check whether it is or spends the funding transaction
Expand Down Expand Up @@ -10066,16 +10095,17 @@ where
&self.context.channel_id,
);

let (funding_txo, monitor_update, announcement_sigs) =
let (funding_txo, monitor_update, announcement_sigs, discarded_funding) =
self.maybe_promote_splice_funding(
node_signer, chain_hash, user_config, height, logger,
).map(|splice_promotion| (
Some(splice_promotion.funding_txo),
splice_promotion.monitor_update,
splice_promotion.announcement_sigs,
)).unwrap_or((None, None, None));
splice_promotion.discarded_funding,
)).unwrap_or((None, None, None, Vec::new()));

return Ok((Some(FundingConfirmedMessage::Splice(splice_locked, funding_txo, monitor_update)), announcement_sigs));
return Ok((Some(FundingConfirmedMessage::Splice(splice_locked, funding_txo, monitor_update, discarded_funding)), announcement_sigs));
}
}
}
Expand Down Expand Up @@ -10227,7 +10257,7 @@ where
log_info!(logger, "Sending a splice_locked to our peer for channel {}", &self.context.channel_id);
debug_assert!(chain_node_signer.is_some());

let (funding_txo, monitor_update, announcement_sigs) = chain_node_signer
let (funding_txo, monitor_update, announcement_sigs, discarded_funding) = chain_node_signer
.and_then(|(chain_hash, node_signer, user_config)| {
// We can only promote on blocks connected, which is when we expect
// `chain_node_signer` to be `Some`.
Expand All @@ -10237,10 +10267,11 @@ where
Some(splice_promotion.funding_txo),
splice_promotion.monitor_update,
splice_promotion.announcement_sigs,
splice_promotion.discarded_funding,
))
.unwrap_or((None, None, None));
.unwrap_or((None, None, None, Vec::new()));

return Ok((Some(FundingConfirmedMessage::Splice(splice_locked, funding_txo, monitor_update)), timed_out_htlcs, announcement_sigs));
return Ok((Some(FundingConfirmedMessage::Splice(splice_locked, funding_txo, monitor_update, discarded_funding)), timed_out_htlcs, announcement_sigs));
}
}

Expand Down
48 changes: 33 additions & 15 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11230,19 +11230,30 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
insert_short_channel_id!(short_to_chan_info, chan);
}

let mut pending_events = self.pending_events.lock().unwrap();
pending_events.push_back((
events::Event::ChannelReady {
channel_id: chan.context.channel_id(),
user_channel_id: chan.context.get_user_id(),
counterparty_node_id: chan.context.get_counterparty_node_id(),
funding_txo: Some(
splice_promotion.funding_txo.into_bitcoin_outpoint(),
),
channel_type: chan.funding.get_channel_type().clone(),
},
None,
));
{
let mut pending_events = self.pending_events.lock().unwrap();
pending_events.push_back((
events::Event::ChannelReady {
channel_id: chan.context.channel_id(),
user_channel_id: chan.context.get_user_id(),
counterparty_node_id: chan.context.get_counterparty_node_id(),
funding_txo: Some(
splice_promotion.funding_txo.into_bitcoin_outpoint(),
),
channel_type: chan.funding.get_channel_type().clone(),
},
None,
));
splice_promotion.discarded_funding.into_iter().for_each(
|funding_info| {
let event = Event::DiscardFunding {
channel_id: chan.context.channel_id(),
funding_info,
};
pending_events.push_back((event, None));
},
);
}

if let Some(announcement_sigs) = splice_promotion.announcement_sigs {
log_trace!(
Expand Down Expand Up @@ -13409,7 +13420,7 @@ where
pub(super) enum FundingConfirmedMessage {
Establishment(msgs::ChannelReady),
#[cfg(splicing)]
Splice(msgs::SpliceLocked, Option<OutPoint>, Option<ChannelMonitorUpdate>),
Splice(msgs::SpliceLocked, Option<OutPoint>, Option<ChannelMonitorUpdate>, Vec<FundingInfo>),
}

impl<
Expand Down Expand Up @@ -13485,7 +13496,7 @@ where
}
},
#[cfg(splicing)]
Some(FundingConfirmedMessage::Splice(splice_locked, funding_txo, monitor_update_opt)) => {
Some(FundingConfirmedMessage::Splice(splice_locked, funding_txo, monitor_update_opt, discarded_funding)) => {
let counterparty_node_id = funded_channel.context.get_counterparty_node_id();
let channel_id = funded_channel.context.channel_id();

Expand Down Expand Up @@ -13515,6 +13526,13 @@ where
funding_txo: Some(funding_txo.into_bitcoin_outpoint()),
channel_type: funded_channel.funding.get_channel_type().clone(),
}, None));
discarded_funding.into_iter().for_each(|funding_info| {
let event = Event::DiscardFunding {
channel_id: funded_channel.context.channel_id(),
funding_info,
};
pending_events.push_back((event, None));
});
}

pending_msg_events.push(MessageSendEvent::SendSpliceLocked {
Expand Down
Loading