Skip to content

Commit 45447b6

Browse files
committed
Expose outbound SCID alias in ChannelDetails and use in routing
This supports routing outbound over 0-conf channels by utilizing the outbound SCID alias that we assign to all channels to refer to the selected channel when routing.
1 parent 1bb9114 commit 45447b6

File tree

3 files changed

+25
-3
lines changed

3 files changed

+25
-3
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,13 @@ pub struct ChannelDetails {
12231223
/// [`inbound_scid_alias`]: Self::inbound_scid_alias
12241224
/// [`get_inbound_payment_scid`]: Self::get_inbound_payment_scid
12251225
pub short_channel_id: Option<u64>,
1226+
/// An optional [`short_channel_id`] alias for this channel, randomly generated by us and
1227+
/// usable in place of [`short_channel_id`] to reference the channel in outbound routes even if
1228+
/// the channel has not yet been confirmed (as long as [`confirmations_required`] is
1229+
/// `Some(0)`).
1230+
///
1231+
/// This will be `None` as long as the channel is not available for routing outbound payments.
1232+
pub outbound_scid_alias: Option<u64>,
12261233
/// An optional [`short_channel_id`] alias for this channel, randomly generated by our
12271234
/// counterparty and usable in place of [`short_channel_id`] in invoice route hints. Our
12281235
/// counterparty will recognize the alias provided here in place of the [`short_channel_id`]
@@ -1328,6 +1335,16 @@ impl ChannelDetails {
13281335
pub fn get_inbound_payment_scid(&self) -> Option<u64> {
13291336
self.inbound_scid_alias.or(self.short_channel_id)
13301337
}
1338+
1339+
/// Gets the current SCID which should be used to identify this channel for outbound payments.
1340+
/// This should be used in [`Route`]s to describe the first hop or in other contexts where
1341+
/// we're sending or forwarding a payment outbound over this channel.
1342+
///
1343+
/// This is either the [`ChannelDetails::short_channel_id`], if set, or the
1344+
/// [`ChannelDetails::outbound_scid_alias`]. See those for more information.
1345+
pub fn get_outbound_payment_scid(&self) -> Option<u64> {
1346+
self.short_channel_id.or(self.outbound_scid_alias)
1347+
}
13311348
}
13321349

13331350
/// If a payment fails to send, it can be in one of several states. This enum is returned as the
@@ -1949,6 +1966,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
19491966
// `have_received_message` indicates that type negotiation has completed.
19501967
channel_type: if channel.have_received_message() { Some(channel.get_channel_type().clone()) } else { None },
19511968
short_channel_id: channel.get_short_channel_id(),
1969+
outbound_scid_alias: if channel.is_live() { Some(channel.outbound_scid_alias()) } else { None },
19521970
inbound_scid_alias: channel.latest_inbound_scid_alias(),
19531971
channel_value_satoshis: channel.get_value_satoshis(),
19541972
unspendable_punishment_reserve: to_self_reserve_satoshis,
@@ -6225,6 +6243,7 @@ impl_writeable_tlv_based!(ChannelDetails, {
62256243
(2, channel_id, required),
62266244
(3, channel_type, option),
62276245
(4, counterparty, required),
6246+
(5, outbound_scid_alias, option),
62286247
(6, funding_txo, option),
62296248
(8, short_channel_id, option),
62306249
(10, channel_value_satoshis, required),

lightning/src/ln/priv_short_conf_tests.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,4 +616,6 @@ fn test_simple_0_conf_channel() {
616616

617617
assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
618618
assert_eq!(nodes[1].node.list_usable_channels().len(), 1);
619+
620+
send_payment(&nodes[0], &[&nodes[1]], 100_000);
619621
}

lightning/src/routing/router.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ enum CandidateRouteHop<'a> {
368368
impl<'a> CandidateRouteHop<'a> {
369369
fn short_channel_id(&self) -> u64 {
370370
match self {
371-
CandidateRouteHop::FirstHop { details } => details.short_channel_id.unwrap(),
371+
CandidateRouteHop::FirstHop { details } => details.get_outbound_payment_scid().unwrap(),
372372
CandidateRouteHop::PublicHop { short_channel_id, .. } => *short_channel_id,
373373
CandidateRouteHop::PrivateHop { hint } => hint.short_channel_id,
374374
}
@@ -766,7 +766,7 @@ where L::Target: Logger {
766766
HashMap::with_capacity(if first_hops.is_some() { first_hops.as_ref().unwrap().len() } else { 0 });
767767
if let Some(hops) = first_hops {
768768
for chan in hops {
769-
if chan.short_channel_id.is_none() {
769+
if chan.get_outbound_payment_scid().is_none() {
770770
panic!("first_hops should be filled in with usable channels, not pending ones");
771771
}
772772
if chan.counterparty.node_id == *our_node_pubkey {
@@ -1318,7 +1318,7 @@ where L::Target: Logger {
13181318
let mut features_set = false;
13191319
if let Some(first_channels) = first_hop_targets.get(&ordered_hops.last().unwrap().0.node_id) {
13201320
for details in first_channels {
1321-
if details.short_channel_id.unwrap() == ordered_hops.last().unwrap().0.candidate.short_channel_id() {
1321+
if details.get_outbound_payment_scid().unwrap() == ordered_hops.last().unwrap().0.candidate.short_channel_id() {
13221322
ordered_hops.last_mut().unwrap().1 = details.counterparty.features.to_context();
13231323
features_set = true;
13241324
break;
@@ -1727,6 +1727,7 @@ mod tests {
17271727
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
17281728
channel_type: None,
17291729
short_channel_id,
1730+
outbound_scid_alias: None,
17301731
inbound_scid_alias: None,
17311732
channel_value_satoshis: 0,
17321733
user_channel_id: 0,

0 commit comments

Comments
 (0)