Skip to content

Commit 9455aaf

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 8a500f2 commit 9455aaf

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
};
@@ -1421,6 +1421,11 @@ pub(crate) const UNFUNDED_CHANNEL_AGE_LIMIT_TICKS: usize = 60;
14211421
/// Number of blocks needed for an output from a coinbase transaction to be spendable.
14221422
pub(crate) const COINBASE_MATURITY: u32 = 100;
14231423

1424+
/// The number of blocks to wait for a channel_announcement to propagate such that payments using an
1425+
/// older SCID can still be relayed. Once the spend of the previous funding transaction has reached
1426+
/// this number of confirmations, the corresponding SCID will be forgotten.
1427+
const CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY: u32 = 12;
1428+
14241429
struct PendingChannelMonitorUpdate {
14251430
update: ChannelMonitorUpdate,
14261431
}
@@ -2425,6 +2430,10 @@ where
24252430
// blinded paths instead of simple scid+node_id aliases.
24262431
outbound_scid_alias: u64,
24272432

2433+
/// Short channel ids used by any prior FundingScope. These are maintained such that
2434+
/// ChannelManager can look up the channel for any pending HTLCs.
2435+
historical_scids: Vec<u64>,
2436+
24282437
// We track whether we already emitted a `ChannelPending` event.
24292438
channel_pending_event_emitted: bool,
24302439

@@ -3275,6 +3284,7 @@ where
32753284

32763285
latest_inbound_scid_alias: None,
32773286
outbound_scid_alias: 0,
3287+
historical_scids: Vec::new(),
32783288

32793289
channel_pending_event_emitted: false,
32803290
funding_tx_broadcast_safe_event_emitted: false,
@@ -3517,6 +3527,7 @@ where
35173527

35183528
latest_inbound_scid_alias: None,
35193529
outbound_scid_alias,
3530+
historical_scids: Vec::new(),
35203531

35213532
channel_pending_event_emitted: false,
35223533
funding_tx_broadcast_safe_event_emitted: false,
@@ -5604,6 +5615,11 @@ where
56045615

56055616
Ok(())
56065617
}
5618+
5619+
/// Returns SCIDs that have been associated with the channel's funding transactions.
5620+
pub fn historical_scids(&self) -> &[u64] {
5621+
&self.historical_scids[..]
5622+
}
56075623
}
56085624

56095625
// Internal utility functions for channels
@@ -5805,6 +5821,9 @@ where
58055821
#[cfg(splicing)]
58065822
macro_rules! promote_splice_funding {
58075823
($self: expr, $funding: expr) => {
5824+
if let Some(scid) = $self.funding.short_channel_id {
5825+
$self.context.historical_scids.push(scid);
5826+
}
58085827
core::mem::swap(&mut $self.funding, $funding);
58095828
$self.pending_splice = None;
58105829
$self.pending_funding.clear();
@@ -10643,6 +10662,30 @@ where
1064310662
pub fn has_pending_splice(&self) -> bool {
1064410663
self.pending_splice.is_some()
1064510664
}
10665+
10666+
pub fn remove_legacy_scids_before_block(&mut self, height: u32) -> alloc::vec::Drain<u64> {
10667+
let end = self
10668+
.funding
10669+
.get_short_channel_id()
10670+
.and_then(|current_scid| {
10671+
let historical_scids = &self.context.historical_scids;
10672+
historical_scids
10673+
.iter()
10674+
.zip(historical_scids.iter().skip(1).chain(core::iter::once(&current_scid)))
10675+
.map(|(_, next_scid)| {
10676+
let funding_height = block_from_scid(*next_scid);
10677+
let retain_scid =
10678+
funding_height + CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY - 1 > height;
10679+
retain_scid
10680+
})
10681+
.position(|retain_scid| retain_scid)
10682+
})
10683+
.unwrap_or(0);
10684+
10685+
// Drains the oldest historical SCIDs until reaching one without
10686+
// CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY confirmations.
10687+
self.context.historical_scids.drain(0..end)
10688+
}
1064610689
}
1064710690

1064810691
/// A not-yet-funded outbound (from holder) channel using V1 channel establishment.
@@ -12073,6 +12116,7 @@ where
1207312116
(57, holding_cell_failure_attribution_data, optional_vec), // Added in 0.2
1207412117
(58, self.interactive_tx_signing_session, option), // Added in 0.2
1207512118
(59, self.funding.minimum_depth_override, option), // Added in 0.2
12119+
(60, self.context.historical_scids, optional_vec), // Added in 0.2
1207612120
});
1207712121

1207812122
Ok(())
@@ -12390,6 +12434,7 @@ where
1239012434
let mut is_manual_broadcast = None;
1239112435

1239212436
let mut pending_funding = Some(Vec::new());
12437+
let mut historical_scids = Some(Vec::new());
1239312438

1239412439
let mut interactive_tx_signing_session: Option<InteractiveTxSigningSession> = None;
1239512440

@@ -12435,6 +12480,7 @@ where
1243512480
(57, holding_cell_failure_attribution_data, optional_vec),
1243612481
(58, interactive_tx_signing_session, option), // Added in 0.2
1243712482
(59, minimum_depth_override, option), // Added in 0.2
12483+
(60, historical_scids, optional_vec), // Added in 0.2
1243812484
});
1243912485

1244012486
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
@@ -12708,6 +12754,7 @@ where
1270812754
latest_inbound_scid_alias,
1270912755
// Later in the ChannelManager deserialization phase we scan for channels and assign scid aliases if its missing
1271012756
outbound_scid_alias,
12757+
historical_scids: historical_scids.unwrap(),
1271112758

1271212759
funding_tx_broadcast_safe_event_emitted: funding_tx_broadcast_safe_event_emitted.unwrap_or(false),
1271312760
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
@@ -3192,6 +3192,9 @@ macro_rules! locked_close_channel {
31923192
debug_assert!(alias_removed);
31933193
}
31943194
short_to_chan_info.remove(&$channel_context.outbound_scid_alias());
3195+
for scid in $channel_context.historical_scids() {
3196+
short_to_chan_info.remove(scid);
3197+
}
31953198
}}
31963199
}
31973200

@@ -12120,6 +12123,18 @@ where
1212012123
channel.check_for_stale_feerate(&logger, feerate)?;
1212112124
}
1212212125
}
12126+
12127+
// Remove any SCIDs used by older funding transactions
12128+
{
12129+
let legacy_scids = channel.remove_legacy_scids_before_block(height);
12130+
if !legacy_scids.as_slice().is_empty() {
12131+
let mut short_to_chan_info = self.short_to_chan_info.write().unwrap();
12132+
for scid in legacy_scids {
12133+
short_to_chan_info.remove(&scid);
12134+
}
12135+
}
12136+
}
12137+
1212312138
channel.best_block_updated(height, header.time, self.chain_hash, &self.node_signer, &self.default_configuration, &&WithChannelContext::from(&self.logger, &channel.context, None))
1212412139
});
1212512140

@@ -14502,6 +14517,11 @@ where
1450214517
if let Some(short_channel_id) = channel.funding.get_short_channel_id() {
1450314518
short_to_chan_info.insert(short_channel_id, (channel.context.get_counterparty_node_id(), channel.context.channel_id()));
1450414519
}
14520+
14521+
for short_channel_id in channel.context.historical_scids() {
14522+
short_to_chan_info.insert(*short_channel_id, (channel.context.get_counterparty_node_id(), channel.context.channel_id()));
14523+
}
14524+
1450514525
per_peer_state.entry(channel.context.get_counterparty_node_id())
1450614526
.or_insert_with(|| Mutex::new(empty_peer_state()))
1450714527
.get_mut().unwrap()

0 commit comments

Comments
 (0)