Skip to content

Commit 2f888cb

Browse files
Add BOLT 12 features to PaymentParams
1 parent 604353a commit 2f888cb

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

lightning/src/ln/features.rs

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

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

lightning/src/routing/router.rs

Lines changed: 60 additions & 6 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};
@@ -537,12 +537,12 @@ impl Writeable for PaymentParameters {
537537
let mut blinded_hints = &vec![];
538538
match &self.payee {
539539
Payee::Clear { route_hints, .. } => clear_hints = route_hints,
540-
Payee::Blinded { route_hints } => blinded_hints = route_hints,
540+
Payee::Blinded { route_hints, .. } => blinded_hints = route_hints,
541541
}
542542
write_tlv_fields!(writer, {
543543
(0, self.payee.node_id(), option),
544544
(1, self.max_total_cltv_expiry_delta, required),
545-
(2, if let Payee::Clear { features, .. } = &self.payee { features } else { &None }, option),
545+
(2, self.payee.features(), option),
546546
(3, self.max_path_count, required),
547547
(4, *clear_hints, vec_type),
548548
(5, self.max_channel_saturation_power_of_half, required),
@@ -560,7 +560,7 @@ impl ReadableArgs<u32> for PaymentParameters {
560560
_init_and_read_tlv_fields!(reader, {
561561
(0, payee_pubkey, option),
562562
(1, max_total_cltv_expiry_delta, (default_value, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA)),
563-
(2, features, option),
563+
(2, features, (option: ReadableArgs, payee_pubkey.is_some())),
564564
(3, max_path_count, (default_value, DEFAULT_MAX_PATH_COUNT)),
565565
(4, route_hints, vec_type),
566566
(5, max_channel_saturation_power_of_half, (default_value, 2)),
@@ -573,12 +573,15 @@ impl ReadableArgs<u32> for PaymentParameters {
573573
let blinded_route_hints = blinded_route_hints.unwrap_or(vec![]);
574574
let payee = if blinded_route_hints.len() != 0 {
575575
if clear_route_hints.len() != 0 || payee_pubkey.is_some() { return Err(DecodeError::InvalidValue) }
576-
Payee::Blinded { route_hints: blinded_route_hints }
576+
Payee::Blinded {
577+
route_hints: blinded_route_hints,
578+
features: features.map(|f: Features| f.bolt12()).flatten(),
579+
}
577580
} else {
578581
Payee::Clear {
579582
route_hints: clear_route_hints,
580583
node_id: payee_pubkey.ok_or(DecodeError::InvalidValue)?,
581-
features,
584+
features: features.map(|f| f.bolt11()).flatten(),
582585
}
583586
};
584587
Ok(Self {
@@ -682,6 +685,11 @@ pub enum Payee {
682685
/// Aggregated routing info and blinded paths, for routing to the payee without knowing their
683686
/// node id.
684687
route_hints: Vec<(BlindedPayInfo, BlindedPath)>,
688+
/// Features supported by the payee.
689+
///
690+
/// May be set from the payee's invoice. May be `None` if the invoice does not contain any
691+
/// features.
692+
features: Option<Bolt12InvoiceFeatures>,
685693
},
686694
/// The recipient included these route hints in their BOLT11 invoice.
687695
Clear {
@@ -718,6 +726,52 @@ impl Payee {
718726
_ => false,
719727
}
720728
}
729+
fn features(&self) -> Option<FeaturesRef> {
730+
match self {
731+
Self::Clear { features, .. } => features.as_ref().map(|f| FeaturesRef::Bolt11(f)),
732+
Self::Blinded { features, .. } => features.as_ref().map(|f| FeaturesRef::Bolt12(f)),
733+
}
734+
}
735+
}
736+
737+
enum FeaturesRef<'a> {
738+
Bolt11(&'a InvoiceFeatures),
739+
Bolt12(&'a Bolt12InvoiceFeatures),
740+
}
741+
enum Features {
742+
Bolt11(InvoiceFeatures),
743+
Bolt12(Bolt12InvoiceFeatures),
744+
}
745+
746+
impl Features {
747+
fn bolt12(self) -> Option<Bolt12InvoiceFeatures> {
748+
match self {
749+
Self::Bolt12(f) => Some(f),
750+
_ => None,
751+
}
752+
}
753+
fn bolt11(self) -> Option<InvoiceFeatures> {
754+
match self {
755+
Self::Bolt11(f) => Some(f),
756+
_ => None,
757+
}
758+
}
759+
}
760+
761+
impl<'a> Writeable for FeaturesRef<'a> {
762+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
763+
match self {
764+
Self::Bolt11(f) => Ok(f.write(w)?),
765+
Self::Bolt12(f) => Ok(f.write(w)?),
766+
}
767+
}
768+
}
769+
770+
impl ReadableArgs<bool> for Features {
771+
fn read<R: io::Read>(reader: &mut R, bolt11: bool) -> Result<Self, DecodeError> {
772+
if bolt11 { return Ok(Self::Bolt11(Readable::read(reader)?)) }
773+
Ok(Self::Bolt12(Readable::read(reader)?))
774+
}
721775
}
722776

723777
/// A list of hops along a payment path terminating with a channel to the recipient.

0 commit comments

Comments
 (0)