Skip to content

Commit 15138e4

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 b715d73 commit 15138e4

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
@@ -969,6 +969,13 @@ pub struct ChannelDetails {
969969
/// [`inbound_scid_alias`]: Self::inbound_scid_alias
970970
/// [`get_inbound_payment_scid`]: Self::get_inbound_payment_scid
971971
pub short_channel_id: Option<u64>,
972+
/// An optional [`short_channel_id`] alias for this channel, randomly generated by us and
973+
/// usable in place of [`short_channel_id`] to reference the channel in outbound routes even if
974+
/// the channel has not yet been confirmed (as long as [`confirmations_required`] is
975+
/// `Some(0)`).
976+
///
977+
/// This will be `None` as long as the channel is not available for routing outbound payments.
978+
pub outbound_scid_alias: Option<u64>,
972979
/// An optional [`short_channel_id`] alias for this channel, randomly generated by our
973980
/// counterparty and usable in place of [`short_channel_id`] in invoice route hints. Our
974981
/// counterparty will recognize the alias provided here in place of the [`short_channel_id`]
@@ -1086,6 +1093,16 @@ impl ChannelDetails {
10861093
pub fn get_inbound_payment_scid(&self) -> Option<u64> {
10871094
self.inbound_scid_alias.or(self.short_channel_id)
10881095
}
1096+
1097+
/// Gets the current SCID which should be used to identify this channel for outbound payments.
1098+
/// This should be used in [`Route`]s to describe the first hop or in other contexts where
1099+
/// we're sending or forwarding a payment outbound over this channel.
1100+
///
1101+
/// This is either the [`ChannelDetails::short_channel_id`], if set, or the
1102+
/// [`ChannelDetails::outbound_scid_alias`]. See those for more information.
1103+
pub fn get_outbound_payment_scid(&self) -> Option<u64> {
1104+
self.short_channel_id.or(self.outbound_scid_alias)
1105+
}
10891106
}
10901107

10911108
/// If a payment fails to send, it can be in one of several states. This enum is returned as the
@@ -1712,6 +1729,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
17121729
// `have_received_message` indicates that type negotiation has completed.
17131730
channel_type: if channel.have_received_message() { Some(channel.get_channel_type().clone()) } else { None },
17141731
short_channel_id: channel.get_short_channel_id(),
1732+
outbound_scid_alias: if channel.is_live() { Some(channel.outbound_scid_alias()) } else { None },
17151733
inbound_scid_alias: channel.latest_inbound_scid_alias(),
17161734
channel_value_satoshis: channel.get_value_satoshis(),
17171735
unspendable_punishment_reserve: to_self_reserve_satoshis,
@@ -5982,6 +6000,7 @@ impl_writeable_tlv_based!(ChannelDetails, {
59826000
(2, channel_id, required),
59836001
(3, channel_type, option),
59846002
(4, counterparty, required),
6003+
(5, outbound_scid_alias, option),
59856004
(6, funding_txo, option),
59866005
(8, short_channel_id, option),
59876006
(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
@@ -639,4 +639,6 @@ fn test_simple_0conf_channel() {
639639

640640
assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
641641
assert_eq!(nodes[1].node.list_usable_channels().len(), 1);
642+
643+
send_payment(&nodes[0], &[&nodes[1]], 100_000);
642644
}

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
}
@@ -777,7 +777,7 @@ where L::Target: Logger {
777777
HashMap::with_capacity(if first_hops.is_some() { first_hops.as_ref().unwrap().len() } else { 0 });
778778
if let Some(hops) = first_hops {
779779
for chan in hops {
780-
if chan.short_channel_id.is_none() {
780+
if chan.get_outbound_payment_scid().is_none() {
781781
panic!("first_hops should be filled in with usable channels, not pending ones");
782782
}
783783
if chan.counterparty.node_id == *our_node_pubkey {
@@ -1331,7 +1331,7 @@ where L::Target: Logger {
13311331
let mut features_set = false;
13321332
if let Some(first_channels) = first_hop_targets.get(&ordered_hops.last().unwrap().0.node_id) {
13331333
for details in first_channels {
1334-
if details.short_channel_id.unwrap() == ordered_hops.last().unwrap().0.candidate.short_channel_id() {
1334+
if details.get_outbound_payment_scid().unwrap() == ordered_hops.last().unwrap().0.candidate.short_channel_id() {
13351335
ordered_hops.last_mut().unwrap().1 = details.counterparty.features.to_context();
13361336
features_set = true;
13371337
break;
@@ -1742,6 +1742,7 @@ mod tests {
17421742
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
17431743
channel_type: None,
17441744
short_channel_id,
1745+
outbound_scid_alias: None,
17451746
inbound_scid_alias: None,
17461747
channel_value_satoshis: 0,
17471748
user_channel_id: 0,

0 commit comments

Comments
 (0)