Skip to content

Commit 00ee78d

Browse files
committed
Track historical SCIDs from previous funding
When a splice is locked, the SCID from the previous funding transaction needs to be remembered so that pending HTLCs can be handled properly. Additionally, when they need to be cleaned up once they should no longer be used. Track these SCIDs as splices are locked and clean any up as blocks are connected.
1 parent 96d4e80 commit 00ee78d

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

lightning/src/ln/channel.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ use crate::util::config::{
7676
};
7777
use crate::util::errors::APIError;
7878
use crate::util::logger::{Logger, Record, WithContext};
79-
use crate::util::scid_utils::scid_from_parts;
79+
use crate::util::scid_utils::{block_from_scid, scid_from_parts};
8080
use crate::util::ser::{
8181
Readable, ReadableArgs, RequiredWrapper, TransactionU16LenLimited, Writeable, Writer,
8282
};
@@ -1407,6 +1407,11 @@ pub(crate) const UNFUNDED_CHANNEL_AGE_LIMIT_TICKS: usize = 60;
14071407
/// Number of blocks needed for an output from a coinbase transaction to be spendable.
14081408
pub(crate) const COINBASE_MATURITY: u32 = 100;
14091409

1410+
/// The number of blocks to wait for a channel_announcement to propagate such that payments using an
1411+
/// older SCID can still be relayed. Once the spend of the previous funding transaction has reached
1412+
/// this number of confirmations, the corresponding SCID will be forgotten.
1413+
const CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY: u32 = 12;
1414+
14101415
struct PendingChannelMonitorUpdate {
14111416
update: ChannelMonitorUpdate,
14121417
}
@@ -2413,6 +2418,10 @@ where
24132418
// blinded paths instead of simple scid+node_id aliases.
24142419
outbound_scid_alias: u64,
24152420

2421+
/// Short channel ids used by any prior FundingScope. These are maintained such that
2422+
/// ChannelManager can look up the channel for any pending HTLCs.
2423+
historical_scids: Vec<u64>,
2424+
24162425
// We track whether we already emitted a `ChannelPending` event.
24172426
channel_pending_event_emitted: bool,
24182427

@@ -3259,6 +3268,7 @@ where
32593268

32603269
latest_inbound_scid_alias: None,
32613270
outbound_scid_alias: 0,
3271+
historical_scids: Vec::new(),
32623272

32633273
channel_pending_event_emitted: false,
32643274
funding_tx_broadcast_safe_event_emitted: false,
@@ -3501,6 +3511,7 @@ where
35013511

35023512
latest_inbound_scid_alias: None,
35033513
outbound_scid_alias,
3514+
historical_scids: Vec::new(),
35043515

35053516
channel_pending_event_emitted: false,
35063517
funding_tx_broadcast_safe_event_emitted: false,
@@ -5592,6 +5603,11 @@ where
55925603

55935604
Ok(())
55945605
}
5606+
5607+
/// Returns SCIDs that have been associated with the channel's funding transactions.
5608+
pub fn historical_scids(&self) -> &[u64] {
5609+
&self.historical_scids[..]
5610+
}
55955611
}
55965612

55975613
// Internal utility functions for channels
@@ -5789,6 +5805,9 @@ where
57895805
#[cfg(splicing)]
57905806
macro_rules! promote_splice_funding {
57915807
($self: expr, $funding: expr) => {
5808+
if let Some(scid) = $self.funding.short_channel_id {
5809+
$self.context.historical_scids.push(scid);
5810+
}
57925811
core::mem::swap(&mut $self.funding, $funding);
57935812
$self.pending_splice = None;
57945813
$self.pending_funding.clear();
@@ -10597,6 +10616,30 @@ where
1059710616
pub fn has_pending_splice(&self) -> bool {
1059810617
self.pending_splice.is_some()
1059910618
}
10619+
10620+
pub fn remove_legacy_scids_before_block(&mut self, height: u32) -> alloc::vec::Drain<u64> {
10621+
let end = self
10622+
.funding
10623+
.get_short_channel_id()
10624+
.and_then(|current_scid| {
10625+
let historical_scids = &self.context.historical_scids;
10626+
historical_scids
10627+
.iter()
10628+
.zip(historical_scids.iter().skip(1).chain(core::iter::once(&current_scid)))
10629+
.map(|(_, next_scid)| {
10630+
let funding_height = block_from_scid(*next_scid);
10631+
let retain_scid =
10632+
funding_height + CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY - 1 > height;
10633+
retain_scid
10634+
})
10635+
.position(|retain_scid| retain_scid)
10636+
})
10637+
.unwrap_or(0);
10638+
10639+
// Drains the oldest historical SCIDs until reaching one without
10640+
// CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY confirmations.
10641+
self.context.historical_scids.drain(0..end)
10642+
}
1060010643
}
1060110644

1060210645
/// A not-yet-funded outbound (from holder) channel using V1 channel establishment.
@@ -12020,6 +12063,7 @@ where
1202012063
(57, holding_cell_failure_attribution_data, optional_vec), // Added in 0.2
1202112064
(58, self.interactive_tx_signing_session, option), // Added in 0.2
1202212065
(59, self.funding.minimum_depth_override, option), // Added in 0.2
12066+
(60, self.context.historical_scids, optional_vec), // Added in 0.2
1202312067
});
1202412068

1202512069
Ok(())
@@ -12337,6 +12381,7 @@ where
1233712381
let mut is_manual_broadcast = None;
1233812382

1233912383
let mut pending_funding = Some(Vec::new());
12384+
let mut historical_scids = Some(Vec::new());
1234012385

1234112386
let mut interactive_tx_signing_session: Option<InteractiveTxSigningSession> = None;
1234212387

@@ -12382,6 +12427,7 @@ where
1238212427
(57, holding_cell_failure_attribution_data, optional_vec),
1238312428
(58, interactive_tx_signing_session, option), // Added in 0.2
1238412429
(59, minimum_depth_override, option), // Added in 0.2
12430+
(60, historical_scids, optional_vec), // Added in 0.2
1238512431
});
1238612432

1238712433
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
@@ -12655,6 +12701,7 @@ where
1265512701
latest_inbound_scid_alias,
1265612702
// Later in the ChannelManager deserialization phase we scan for channels and assign scid aliases if its missing
1265712703
outbound_scid_alias,
12704+
historical_scids: historical_scids.unwrap(),
1265812705

1265912706
funding_tx_broadcast_safe_event_emitted: funding_tx_broadcast_safe_event_emitted.unwrap_or(false),
1266012707
channel_pending_event_emitted: channel_pending_event_emitted.unwrap_or(true),

lightning/src/ln/channelmanager.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3181,6 +3181,9 @@ macro_rules! locked_close_channel {
31813181
debug_assert!(alias_removed);
31823182
}
31833183
short_to_chan_info.remove(&$channel_context.outbound_scid_alias());
3184+
for scid in $channel_context.historical_scids() {
3185+
short_to_chan_info.remove(scid);
3186+
}
31843187
}}
31853188
}
31863189

@@ -11973,6 +11976,18 @@ where
1197311976
channel.check_for_stale_feerate(&logger, feerate)?;
1197411977
}
1197511978
}
11979+
11980+
// Remove any SCIDs used by older funding transactions
11981+
{
11982+
let legacy_scids = channel.remove_legacy_scids_before_block(height);
11983+
if !legacy_scids.as_slice().is_empty() {
11984+
let mut short_to_chan_info = self.short_to_chan_info.write().unwrap();
11985+
for scid in legacy_scids {
11986+
short_to_chan_info.remove(&scid);
11987+
}
11988+
}
11989+
}
11990+
1197611991
channel.best_block_updated(height, header.time, self.chain_hash, &self.node_signer, &self.default_configuration, &&WithChannelContext::from(&self.logger, &channel.context, None))
1197711992
});
1197811993

@@ -14348,6 +14363,11 @@ where
1434814363
if let Some(short_channel_id) = channel.funding.get_short_channel_id() {
1434914364
short_to_chan_info.insert(short_channel_id, (channel.context.get_counterparty_node_id(), channel.context.channel_id()));
1435014365
}
14366+
14367+
for short_channel_id in channel.context.historical_scids() {
14368+
short_to_chan_info.insert(*short_channel_id, (channel.context.get_counterparty_node_id(), channel.context.channel_id()));
14369+
}
14370+
1435114371
per_peer_state.entry(channel.context.get_counterparty_node_id())
1435214372
.or_insert_with(|| Mutex::new(empty_peer_state()))
1435314373
.get_mut().unwrap()

0 commit comments

Comments
 (0)