/// Note that if [`inbound_scid_alias`] is set, it must be used for invoices and inbound
/// payments instead of this. See [`get_inbound_payment_scid`].
///
+ /// For channels with [`confirmations_required`] set to `Some(0)`, [`outbound_scid_alias`] may
+ /// be used in place of this in outbound routes. See [`get_outbound_payment_scid`].
+ ///
/// [`inbound_scid_alias`]: Self::inbound_scid_alias
+ /// [`outbound_scid_alias`]: Self::outbound_scid_alias
/// [`get_inbound_payment_scid`]: Self::get_inbound_payment_scid
+ /// [`get_outbound_payment_scid`]: Self::get_outbound_payment_scid
+ /// [`confirmations_required`]: Self::confirmations_required
pub short_channel_id: Option<u64>,
+ /// An optional [`short_channel_id`] alias for this channel, randomly generated by us and
+ /// usable in place of [`short_channel_id`] to reference the channel in outbound routes when
+ /// the channel has not yet been confirmed (as long as [`confirmations_required`] is
+ /// `Some(0)`).
+ ///
+ /// This will be `None` as long as the channel is not available for routing outbound payments.
+ ///
+ /// [`short_channel_id`]: Self::short_channel_id
+ /// [`confirmations_required`]: Self::confirmations_required
+ pub outbound_scid_alias: Option<u64>,
/// An optional [`short_channel_id`] alias for this channel, randomly generated by our
/// counterparty and usable in place of [`short_channel_id`] in invoice route hints. Our
/// counterparty will recognize the alias provided here in place of the [`short_channel_id`]
pub fn get_inbound_payment_scid(&self) -> Option<u64> {
self.inbound_scid_alias.or(self.short_channel_id)
}
+
+ /// Gets the current SCID which should be used to identify this channel for outbound payments.
+ /// This should be used in [`Route`]s to describe the first hop or in other contexts where
+ /// we're sending or forwarding a payment outbound over this channel.
+ ///
+ /// This is either the [`ChannelDetails::short_channel_id`], if set, or the
+ /// [`ChannelDetails::outbound_scid_alias`]. See those for more information.
+ pub fn get_outbound_payment_scid(&self) -> Option<u64> {
+ self.short_channel_id.or(self.outbound_scid_alias)
+ }
}
/// If a payment fails to send, it can be in one of several states. This enum is returned as the
// `have_received_message` indicates that type negotiation has completed.
channel_type: if channel.have_received_message() { Some(channel.get_channel_type().clone()) } else { None },
short_channel_id: channel.get_short_channel_id(),
+ outbound_scid_alias: if channel.is_usable() { Some(channel.outbound_scid_alias()) } else { None },
inbound_scid_alias: channel.latest_inbound_scid_alias(),
channel_value_satoshis: channel.get_value_satoshis(),
unspendable_punishment_reserve: to_self_reserve_satoshis,
(2, channel_id, required),
(3, channel_type, option),
(4, counterparty, required),
+ (5, outbound_scid_alias, option),
(6, funding_txo, option),
(8, short_channel_id, option),
(10, channel_value_satoshis, required),
impl<'a> CandidateRouteHop<'a> {
fn short_channel_id(&self) -> u64 {
match self {
- CandidateRouteHop::FirstHop { details } => details.short_channel_id.unwrap(),
+ CandidateRouteHop::FirstHop { details } => details.get_outbound_payment_scid().unwrap(),
CandidateRouteHop::PublicHop { short_channel_id, .. } => *short_channel_id,
CandidateRouteHop::PrivateHop { hint } => hint.short_channel_id,
}
HashMap::with_capacity(if first_hops.is_some() { first_hops.as_ref().unwrap().len() } else { 0 });
if let Some(hops) = first_hops {
for chan in hops {
- if chan.short_channel_id.is_none() {
+ if chan.get_outbound_payment_scid().is_none() {
panic!("first_hops should be filled in with usable channels, not pending ones");
}
if chan.counterparty.node_id == *our_node_pubkey {
let mut features_set = false;
if let Some(first_channels) = first_hop_targets.get(&ordered_hops.last().unwrap().0.node_id) {
for details in first_channels {
- if details.short_channel_id.unwrap() == ordered_hops.last().unwrap().0.candidate.short_channel_id() {
+ if details.get_outbound_payment_scid().unwrap() == ordered_hops.last().unwrap().0.candidate.short_channel_id() {
ordered_hops.last_mut().unwrap().1 = details.counterparty.features.to_context();
features_set = true;
break;
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
channel_type: None,
short_channel_id,
+ outbound_scid_alias: None,
inbound_scid_alias: None,
channel_value_satoshis: 0,
user_channel_id: 0,
channel_type: None,
short_channel_id: Some(1),
inbound_scid_alias: None,
+ outbound_scid_alias: None,
channel_value_satoshis: 10_000_000,
user_channel_id: 0,
balance_msat: 10_000_000,