Skip to content

Commit a82bc73

Browse files
committed
WIP: Multi-hop blinded payment paths
1 parent 6d0e36e commit a82bc73

File tree

1 file changed

+54
-11
lines changed

1 file changed

+54
-11
lines changed

lightning/src/ln/channelmanager.rs

+54-11
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,9 @@ const MAX_UNFUNDED_CHANNEL_PEERS: usize = 50;
15551555
/// many peers we reject new (inbound) connections.
15561556
const MAX_NO_CHANNEL_PEERS: usize = 250;
15571557

1558+
/// The maximum number of blinded payment paths to use in BOLT 12 invoices.
1559+
const MAX_BLINDED_PAYMENT_PATHS: usize = 3;
1560+
15581561
/// Information needed for constructing an invoice route hint for this channel.
15591562
#[derive(Clone, Debug, PartialEq)]
15601563
pub struct CounterpartyForwardingInfo {
@@ -7652,9 +7655,9 @@ where
76527655

76537656
match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) {
76547657
Ok((payment_hash, payment_secret)) => {
7655-
let payment_paths = vec![
7656-
self.create_one_hop_blinded_payment_path(payment_secret),
7657-
];
7658+
let payment_paths = self.create_blinded_payment_paths(
7659+
amount_msats, payment_secret, MAX_BLINDED_PAYMENT_PATHS
7660+
);
76587661
#[cfg(not(feature = "no-std"))]
76597662
let builder = refund.respond_using_derived_keys(
76607663
payment_paths, payment_hash, expanded_key, entropy
@@ -7831,6 +7834,18 @@ where
78317834
self.router.create_blinded_paths(recipient, peers, count, entropy_source, secp_ctx)
78327835
}
78337836

7837+
/// Creates `count` multi-hop blinded payment paths for the given `amount_msats` by delegating
7838+
/// to [`Router::create_blinded_payment_paths`]. If the router returns an error or no paths,
7839+
/// creates a one-hop blinded payment path instead.
7840+
fn create_blinded_payment_paths(
7841+
&self, amount_msats: u64, payment_secret: PaymentSecret, count: usize
7842+
) -> Vec<(BlindedPayInfo, BlindedPath)> {
7843+
self.create_multi_hop_blinded_payment_paths(amount_msats, payment_secret, count)
7844+
.ok()
7845+
.and_then(|paths| (!paths.is_empty()).then(|| paths))
7846+
.unwrap_or_else(|| vec![self.create_one_hop_blinded_payment_path(payment_secret)])
7847+
}
7848+
78347849
/// Creates a one-hop blinded payment path with [`ChannelManager::get_our_node_id`] as the
78357850
/// introduction node.
78367851
fn create_one_hop_blinded_payment_path(
@@ -7854,6 +7869,34 @@ where
78547869
).unwrap()
78557870
}
78567871

7872+
/// Creates `count` multi-hop blinded payment paths for the given `amount_msats` by delegating
7873+
/// to [`Router::create_blinded_payment_paths`].
7874+
///
7875+
/// May return fewer paths if not enough peers [`support route blinding`] or whose channels
7876+
/// don't have enough inbound liquidity.
7877+
///
7878+
/// [`support route blinding`]: crate::ln::features::InitFeatures::supports_route_blinding
7879+
fn create_multi_hop_blinded_payment_paths(
7880+
&self, amount_msats: u64, payment_secret: PaymentSecret, count: usize
7881+
) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
7882+
let entropy_source = self.entropy_source.deref();
7883+
let secp_ctx = &self.secp_ctx;
7884+
7885+
let first_hops = self.list_usable_channels();
7886+
let payee_node_id = self.get_our_node_id();
7887+
let max_cltv_expiry = self.best_block.read().unwrap().height() + LATENCY_GRACE_PERIOD_BLOCKS;
7888+
let payee_tlvs = ReceiveTlvs {
7889+
payment_secret,
7890+
payment_constraints: PaymentConstraints {
7891+
max_cltv_expiry,
7892+
htlc_minimum_msat: 1,
7893+
},
7894+
};
7895+
self.router.create_blinded_payment_paths(
7896+
payee_node_id, first_hops, payee_tlvs, amount_msats, count, entropy_source, secp_ctx
7897+
)
7898+
}
7899+
78577900
/// Gets a fake short channel id for use in receiving [phantom node payments]. These fake scids
78587901
/// are used when constructing the phantom invoice's route hints.
78597902
///
@@ -9091,7 +9134,7 @@ where
90919134
let amount_msats = match InvoiceBuilder::<DerivedSigningPubkey>::amount_msats(
90929135
&invoice_request
90939136
) {
9094-
Ok(amount_msats) => Some(amount_msats),
9137+
Ok(amount_msats) => amount_msats,
90959138
Err(error) => return Some(OffersMessage::InvoiceError(error.into())),
90969139
};
90979140
let invoice_request = match invoice_request.verify(expanded_key, secp_ctx) {
@@ -9103,11 +9146,11 @@ where
91039146
};
91049147
let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32;
91059148

9106-
match self.create_inbound_payment(amount_msats, relative_expiry, None) {
9149+
match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) {
91079150
Ok((payment_hash, payment_secret)) if invoice_request.keys.is_some() => {
9108-
let payment_paths = vec![
9109-
self.create_one_hop_blinded_payment_path(payment_secret),
9110-
];
9151+
let payment_paths = self.create_blinded_payment_paths(
9152+
amount_msats, payment_secret, MAX_BLINDED_PAYMENT_PATHS
9153+
);
91119154
#[cfg(not(feature = "no-std"))]
91129155
let builder = invoice_request.respond_using_derived_keys(
91139156
payment_paths, payment_hash
@@ -9126,9 +9169,9 @@ where
91269169
}
91279170
},
91289171
Ok((payment_hash, payment_secret)) => {
9129-
let payment_paths = vec![
9130-
self.create_one_hop_blinded_payment_path(payment_secret),
9131-
];
9172+
let payment_paths = self.create_blinded_payment_paths(
9173+
amount_msats, payment_secret, MAX_BLINDED_PAYMENT_PATHS
9174+
);
91329175
#[cfg(not(feature = "no-std"))]
91339176
let builder = invoice_request.respond_with(payment_paths, payment_hash);
91349177
#[cfg(feature = "no-std")]

0 commit comments

Comments
 (0)