Skip to content

Follow-ups #3741: Exchange splice_locked messages #3873

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
167 changes: 99 additions & 68 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1424,7 +1424,7 @@ pub(crate) const COINBASE_MATURITY: u32 = 100;
/// The number of blocks to wait for a channel_announcement to propagate such that payments using an
/// older SCID can still be relayed. Once the spend of the previous funding transaction has reached
/// this number of confirmations, the corresponding SCID will be forgotten.
const CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY: u32 = 12;
const CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY: u32 = 144;

struct PendingChannelMonitorUpdate {
update: ChannelMonitorUpdate,
Expand Down Expand Up @@ -2156,6 +2156,40 @@ struct PendingSplice {
received_funding_txid: Option<Txid>,
}

#[cfg(splicing)]
impl PendingSplice {
fn check_get_splice_locked<SP: Deref>(
&mut self, context: &ChannelContext<SP>, funding: &FundingScope, height: u32,
) -> Option<msgs::SpliceLocked>
where
SP::Target: SignerProvider,
{
if !context.check_funding_meets_minimum_depth(funding, height) {
return None;
}

let confirmed_funding_txid = match funding.get_funding_txid() {
Some(funding_txid) => funding_txid,
None => {
debug_assert!(false);
return None;
},
};

match self.sent_funding_txid {
Some(sent_funding_txid) if confirmed_funding_txid == sent_funding_txid => None,
_ => {
let splice_locked = msgs::SpliceLocked {
channel_id: context.channel_id(),
splice_txid: confirmed_funding_txid,
};
self.sent_funding_txid = Some(splice_locked.splice_txid);
Some(splice_locked)
},
}
}
}

/// Wrapper around a [`Transaction`] useful for caching the result of [`Transaction::compute_txid`].
struct ConfirmedTransaction<'a> {
tx: &'a Transaction,
Expand Down Expand Up @@ -5525,6 +5559,29 @@ where
self.get_initial_counterparty_commitment_signature(funding, logger)
}

fn check_funding_meets_minimum_depth(&self, funding: &FundingScope, height: u32) -> bool {
let minimum_depth = self
.minimum_depth(funding)
.expect("ChannelContext::minimum_depth should be set for FundedChannel");

// Zero-conf channels always meet the minimum depth.
if minimum_depth == 0 {
return true;
}

if funding.funding_tx_confirmation_height == 0 {
return false;
}

let funding_tx_confirmations =
height as i64 - funding.funding_tx_confirmation_height as i64 + 1;
if funding_tx_confirmations < minimum_depth as i64 {
return false;
}

return true;
}

#[rustfmt::skip]
fn check_for_funding_tx_confirmed<L: Deref>(
&mut self, funding: &mut FundingScope, block_hash: &BlockHash, height: u32,
Expand Down Expand Up @@ -9074,58 +9131,13 @@ where
}
}

#[cfg(splicing)]
fn check_get_splice_locked(
&self, pending_splice: &PendingSplice, funding: &FundingScope, height: u32,
) -> Option<msgs::SpliceLocked> {
if !self.check_funding_meets_minimum_depth(funding, height) {
return None;
}

let confirmed_funding_txid = match funding.get_funding_txid() {
Some(funding_txid) => funding_txid,
None => {
debug_assert!(false);
return None;
},
};

match pending_splice.sent_funding_txid {
Some(sent_funding_txid) if confirmed_funding_txid == sent_funding_txid => None,
_ => Some(msgs::SpliceLocked {
channel_id: self.context.channel_id(),
splice_txid: confirmed_funding_txid,
}),
}
}

fn check_funding_meets_minimum_depth(&self, funding: &FundingScope, height: u32) -> bool {
let minimum_depth = self
.context
.minimum_depth(funding)
.expect("ChannelContext::minimum_depth should be set for FundedChannel");

// Zero-conf channels always meet the minimum depth.
if minimum_depth == 0 {
return true;
}

if funding.funding_tx_confirmation_height == 0 {
return false;
}

let funding_tx_confirmations =
height as i64 - funding.funding_tx_confirmation_height as i64 + 1;
if funding_tx_confirmations < minimum_depth as i64 {
return false;
}

return true;
self.context.check_funding_meets_minimum_depth(funding, height)
}

#[cfg(splicing)]
fn maybe_promote_splice_funding<L: Deref>(
&mut self, splice_txid: Txid, confirmed_funding_index: usize, logger: &L,
&mut self, confirmed_funding_index: usize, logger: &L,
) -> bool
where
L::Target: Logger,
Expand All @@ -9134,7 +9146,13 @@ where
debug_assert!(confirmed_funding_index < self.pending_funding.len());

let pending_splice = self.pending_splice.as_mut().unwrap();
pending_splice.sent_funding_txid = Some(splice_txid);
let splice_txid = match pending_splice.sent_funding_txid {
Some(sent_funding_txid) => sent_funding_txid,
None => {
debug_assert!(false);
return false;
},
};

if pending_splice.sent_funding_txid == pending_splice.received_funding_txid {
log_info!(
Expand All @@ -9145,6 +9163,7 @@ where
);

let funding = self.pending_funding.get_mut(confirmed_funding_index).unwrap();
debug_assert_eq!(Some(splice_txid), funding.get_funding_txid());
promote_splice_funding!(self, funding);

return true;
Expand Down Expand Up @@ -9234,7 +9253,7 @@ where

#[cfg(splicing)]
if let Some(confirmed_funding_index) = confirmed_funding_index {
let pending_splice = match self.pending_splice.as_ref() {
let pending_splice = match self.pending_splice.as_mut() {
Some(pending_splice) => pending_splice,
None => {
// TODO: Move pending_funding into pending_splice
Expand All @@ -9245,7 +9264,7 @@ where
};
let funding = self.pending_funding.get(confirmed_funding_index).unwrap();

if let Some(splice_locked) = self.check_get_splice_locked(pending_splice, funding, height) {
if let Some(splice_locked) = pending_splice.check_get_splice_locked(&self.context, funding, height) {
for &(idx, tx) in txdata.iter() {
if idx > index_in_block {
self.context.check_for_funding_tx_spent(funding, tx, logger)?;
Expand All @@ -9259,12 +9278,18 @@ where
&self.context.channel_id,
);

let announcement_sigs = self
.maybe_promote_splice_funding(splice_locked.splice_txid, confirmed_funding_index, logger)
let funding_promoted =
self.maybe_promote_splice_funding(confirmed_funding_index, logger);
let funding_txo = funding_promoted.then(|| {
self.funding
.get_funding_txo()
.expect("Splice FundingScope should always have a funding_txo")
});
let announcement_sigs = funding_promoted
.then(|| self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger))
.flatten();

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

Expand Down Expand Up @@ -9417,21 +9442,27 @@ where
}
}

let pending_splice = self.pending_splice.as_ref().unwrap();
let pending_splice = self.pending_splice.as_mut().unwrap();
let funding = self.pending_funding.get(confirmed_funding_index).unwrap();
if let Some(splice_locked) = self.check_get_splice_locked(pending_splice, funding, height) {
if let Some(splice_locked) = pending_splice.check_get_splice_locked(&self.context, funding, height) {
log_info!(logger, "Sending a splice_locked to our peer for channel {}", &self.context.channel_id);

let announcement_sigs = self
.maybe_promote_splice_funding(splice_locked.splice_txid, confirmed_funding_index, logger)
let funding_promoted =
self.maybe_promote_splice_funding(confirmed_funding_index, logger);
let funding_txo = funding_promoted.then(|| {
self.funding
.get_funding_txo()
.expect("Splice FundingScope should always have a funding_txo")
});
let announcement_sigs = funding_promoted
.then(|| chain_node_signer
.and_then(|(chain_hash, node_signer, user_config)|
self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger)
)
)
.flatten();

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

Expand Down Expand Up @@ -9925,7 +9956,7 @@ where
pub fn splice_locked<NS: Deref, L: Deref>(
&mut self, msg: &msgs::SpliceLocked, node_signer: &NS, chain_hash: ChainHash,
user_config: &UserConfig, best_block: &BestBlock, logger: &L,
) -> Result<Option<msgs::AnnouncementSignatures>, ChannelError>
) -> Result<(Option<OutPoint>, Option<msgs::AnnouncementSignatures>), ChannelError>
where
NS::Target: NodeSigner,
L::Target: Logger,
Expand Down Expand Up @@ -9958,13 +9989,18 @@ where
&self.context.channel_id,
);
promote_splice_funding!(self, funding);
return Ok(self.get_announcement_sigs(
let funding_txo = self
.funding
.get_funding_txo()
.expect("Splice FundingScope should always have a funding_txo");
let announcement_sigs = self.get_announcement_sigs(
node_signer,
chain_hash,
user_config,
best_block.height,
logger,
));
);
return Ok((Some(funding_txo), announcement_sigs));
}

let err = "unknown splice funding txid";
Expand All @@ -9988,7 +10024,7 @@ where
}

pending_splice.received_funding_txid = Some(msg.splice_txid);
Ok(None)
Ok((None, None))
}

// Send stuff to our remote peers:
Expand Down Expand Up @@ -10715,11 +10751,6 @@ where
}
}

#[cfg(splicing)]
pub fn has_pending_splice(&self) -> bool {
self.pending_splice.is_some()
}

pub fn remove_legacy_scids_before_block(&mut self, height: u32) -> alloc::vec::Drain<u64> {
let end = self
.funding
Expand Down
Loading
Loading