Skip to content

Commit 79e3442

Browse files
Check for mpp support when routing to blinded payees
1 parent d249732 commit 79e3442

File tree

2 files changed

+43
-11
lines changed

2 files changed

+43
-11
lines changed

lightning/src/ln/features.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,7 @@ impl_feature_len_prefixed_write!(ChannelFeatures);
792792
impl_feature_len_prefixed_write!(NodeFeatures);
793793
impl_feature_len_prefixed_write!(InvoiceFeatures);
794794
impl_feature_len_prefixed_write!(BlindedHopFeatures);
795+
impl_feature_len_prefixed_write!(Bolt12InvoiceFeatures);
795796

796797
// Some features only appear inside of TLVs, so they don't have a length prefix when serialized.
797798
macro_rules! impl_feature_tlv_write {

lightning/src/routing/router.rs

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
1616
use crate::blinded_path::{BlindedHop, BlindedPath};
1717
use crate::ln::PaymentHash;
1818
use crate::ln::channelmanager::{ChannelDetails, PaymentId};
19-
use crate::ln::features::{ChannelFeatures, InvoiceFeatures, NodeFeatures};
19+
use crate::ln::features::{Bolt12InvoiceFeatures, ChannelFeatures, InvoiceFeatures, NodeFeatures};
2020
use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT};
2121
use crate::offers::invoice::BlindedPayInfo;
2222
use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees};
@@ -536,7 +536,7 @@ impl Writeable for PaymentParameters {
536536
let mut blinded_hints = &vec![];
537537
match &self.payee {
538538
Payee::Clear { route_hints, .. } => clear_hints = route_hints,
539-
Payee::Blinded(hints) => blinded_hints = hints,
539+
Payee::Blinded { route_hints, .. } => blinded_hints = route_hints,
540540
}
541541
write_tlv_fields!(writer, {
542542
(0, self.payee.node_id(), option),
@@ -549,6 +549,7 @@ impl Writeable for PaymentParameters {
549549
(7, self.previously_failed_channels, vec_type),
550550
(8, *blinded_hints, optional_vec),
551551
(9, self.payee.final_cltv_expiry_delta(), option),
552+
(10, self.payee.bolt12_features(), option),
552553
});
553554
Ok(())
554555
}
@@ -567,12 +568,13 @@ impl ReadableArgs<u32> for PaymentParameters {
567568
(7, previously_failed_channels, vec_type),
568569
(8, blinded_route_hints, optional_vec),
569570
(9, final_cltv_expiry_delta, (default_value, default_final_cltv_expiry_delta)),
571+
(10, bolt12_features, option),
570572
});
571573
let clear_route_hints = route_hints.unwrap_or(vec![]);
572574
let blinded_route_hints = blinded_route_hints.unwrap_or(vec![]);
573575
let payee = if blinded_route_hints.len() != 0 {
574576
if clear_route_hints.len() != 0 || payee_pubkey.is_some() { return Err(DecodeError::InvalidValue) }
575-
Payee::Blinded(blinded_route_hints)
577+
Payee::Blinded { route_hints: blinded_route_hints, features: bolt12_features }
576578
} else {
577579
Payee::Clear {
578580
route_hints: clear_route_hints,
@@ -620,7 +622,7 @@ impl PaymentParameters {
620622
/// Creates parameters for paying to a blinded payee.
621623
pub fn blinded(blinded_route_hints: Vec<(BlindedPayInfo, BlindedPath)>) -> Self {
622624
Self {
623-
payee: Payee::Blinded(blinded_route_hints),
625+
payee: Payee::Blinded { route_hints: blinded_route_hints, features: None },
624626
expiry_time: None,
625627
max_total_cltv_expiry_delta: DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA,
626628
max_path_count: DEFAULT_MAX_PATH_COUNT,
@@ -629,13 +631,25 @@ impl PaymentParameters {
629631
}
630632
}
631633

634+
/// Includes the payee's features. Errors if the parameters were not initialized with
635+
/// [`PaymentParameters::blinded`].
636+
///
637+
/// This is not exported to bindings users since bindings don't support move semantics
638+
pub fn with_bolt12_features(self, features: Bolt12InvoiceFeatures) -> Result<Self, ()> {
639+
match self.payee {
640+
Payee::Clear { .. } => Err(()),
641+
Payee::Blinded { route_hints, .. } =>
642+
Ok(Self { payee: Payee::Blinded { route_hints, features: Some(features) }, ..self })
643+
}
644+
}
645+
632646
/// Includes the payee's features. Errors if the parameters were initialized with blinded payment
633647
/// paths.
634648
///
635649
/// This is not exported to bindings users since bindings don't support move semantics
636650
pub fn with_bolt11_features(self, features: InvoiceFeatures) -> Result<Self, ()> {
637651
match self.payee {
638-
Payee::Blinded(_) => Err(()),
652+
Payee::Blinded { .. } => Err(()),
639653
Payee::Clear { route_hints, node_id, final_cltv_expiry_delta, .. } =>
640654
Ok(Self {
641655
payee: Payee::Clear {
@@ -651,7 +665,7 @@ impl PaymentParameters {
651665
/// This is not exported to bindings users since bindings don't support move semantics
652666
pub fn with_route_hints(self, route_hints: Vec<RouteHint>) -> Result<Self, ()> {
653667
match self.payee {
654-
Payee::Blinded(_) => Err(()),
668+
Payee::Blinded { .. } => Err(()),
655669
Payee::Clear { node_id, features, final_cltv_expiry_delta, .. } =>
656670
Ok(Self {
657671
payee: Payee::Clear {
@@ -696,7 +710,16 @@ impl PaymentParameters {
696710
pub enum Payee {
697711
/// The recipient provided blinded paths and payinfo to reach them. The blinded paths themselves
698712
/// will be included in the final [`Route`].
699-
Blinded(Vec<(BlindedPayInfo, BlindedPath)>),
713+
Blinded {
714+
/// Aggregated routing info and blinded paths, for routing to the payee without knowing their
715+
/// node id.
716+
route_hints: Vec<(BlindedPayInfo, BlindedPath)>,
717+
/// Features supported by the payee.
718+
///
719+
/// May be set from the payee's invoice. May be `None` if the invoice does not contain any
720+
/// features.
721+
features: Option<Bolt12InvoiceFeatures>,
722+
},
700723
/// The recipient included these route hints in their BOLT11 invoice.
701724
Clear {
702725
/// The node id of the payee.
@@ -722,6 +745,12 @@ impl Payee {
722745
_ => None,
723746
}
724747
}
748+
fn bolt12_features(&self) -> &Option<Bolt12InvoiceFeatures> {
749+
match self {
750+
Self::Blinded { features, .. } => features,
751+
_ => &None,
752+
}
753+
}
725754
fn bolt11_features(&self) -> &Option<InvoiceFeatures> {
726755
match self {
727756
Self::Clear { features, .. } => features,
@@ -736,14 +765,14 @@ impl Payee {
736765
}
737766
fn blinded_route_hints(&self) -> &[(BlindedPayInfo, BlindedPath)] {
738767
match self {
739-
Self::Blinded(hints) => &hints[..],
768+
Self::Blinded { route_hints, .. } => &route_hints[..],
740769
Self::Clear { .. } => &[]
741770
}
742771
}
743772

744773
fn clear_route_hints(&self) -> &[RouteHint] {
745774
match self {
746-
Self::Blinded(_) => &[],
775+
Self::Blinded { .. } => &[],
747776
Self::Clear { route_hints, .. } => &route_hints[..]
748777
}
749778
}
@@ -1210,8 +1239,8 @@ where L::Target: Logger {
12101239
}
12111240
}
12121241
},
1213-
Payee::Blinded(hints) => {
1214-
for (_, blinded_path) in hints.iter() {
1242+
Payee::Blinded { route_hints, .. } => {
1243+
for (_, blinded_path) in route_hints.iter() {
12151244
if blinded_path.blinded_hops.len() == 0 {
12161245
return Err(LightningError{err: "0-hop blinded path provided".to_owned(), action: ErrorAction::IgnoreError});
12171246
} else if &blinded_path.introduction_node_id == our_node_pubkey {
@@ -1302,6 +1331,8 @@ where L::Target: Logger {
13021331
false
13031332
} else if let Some(features) = payment_params.payee.bolt11_features() {
13041333
features.supports_basic_mpp()
1334+
} else if let Some(features) = payment_params.payee.bolt12_features() {
1335+
features.supports_basic_mpp()
13051336
} else if let Some(payee) = payee_node_id {
13061337
network_nodes.get(&payee).map_or(false, |node| node.announcement_info.as_ref().map_or(false,
13071338
|info| info.features.supports_basic_mpp()))

0 commit comments

Comments
 (0)