Skip to content

Commit

Permalink
WIP: Multi-hop blinded payment paths
Browse files Browse the repository at this point in the history
  • Loading branch information
jkczyz committed Dec 8, 2023
1 parent 6d0e36e commit a82bc73
Showing 1 changed file with 54 additions and 11 deletions.
65 changes: 54 additions & 11 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1555,6 +1555,9 @@ const MAX_UNFUNDED_CHANNEL_PEERS: usize = 50;
/// many peers we reject new (inbound) connections.
const MAX_NO_CHANNEL_PEERS: usize = 250;

/// The maximum number of blinded payment paths to use in BOLT 12 invoices.
const MAX_BLINDED_PAYMENT_PATHS: usize = 3;

/// Information needed for constructing an invoice route hint for this channel.
#[derive(Clone, Debug, PartialEq)]
pub struct CounterpartyForwardingInfo {
Expand Down Expand Up @@ -7652,9 +7655,9 @@ where

match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) {
Ok((payment_hash, payment_secret)) => {
let payment_paths = vec![
self.create_one_hop_blinded_payment_path(payment_secret),
];
let payment_paths = self.create_blinded_payment_paths(
amount_msats, payment_secret, MAX_BLINDED_PAYMENT_PATHS
);
#[cfg(not(feature = "no-std"))]
let builder = refund.respond_using_derived_keys(
payment_paths, payment_hash, expanded_key, entropy
Expand Down Expand Up @@ -7831,6 +7834,18 @@ where
self.router.create_blinded_paths(recipient, peers, count, entropy_source, secp_ctx)
}

/// Creates `count` multi-hop blinded payment paths for the given `amount_msats` by delegating
/// to [`Router::create_blinded_payment_paths`]. If the router returns an error or no paths,
/// creates a one-hop blinded payment path instead.
fn create_blinded_payment_paths(
&self, amount_msats: u64, payment_secret: PaymentSecret, count: usize
) -> Vec<(BlindedPayInfo, BlindedPath)> {
self.create_multi_hop_blinded_payment_paths(amount_msats, payment_secret, count)
.ok()
.and_then(|paths| (!paths.is_empty()).then(|| paths))
.unwrap_or_else(|| vec![self.create_one_hop_blinded_payment_path(payment_secret)])
}

/// Creates a one-hop blinded payment path with [`ChannelManager::get_our_node_id`] as the
/// introduction node.
fn create_one_hop_blinded_payment_path(
Expand All @@ -7854,6 +7869,34 @@ where
).unwrap()
}

/// Creates `count` multi-hop blinded payment paths for the given `amount_msats` by delegating
/// to [`Router::create_blinded_payment_paths`].
///
/// May return fewer paths if not enough peers [`support route blinding`] or whose channels
/// don't have enough inbound liquidity.
///
/// [`support route blinding`]: crate::ln::features::InitFeatures::supports_route_blinding
fn create_multi_hop_blinded_payment_paths(
&self, amount_msats: u64, payment_secret: PaymentSecret, count: usize
) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
let entropy_source = self.entropy_source.deref();
let secp_ctx = &self.secp_ctx;

let first_hops = self.list_usable_channels();
let payee_node_id = self.get_our_node_id();
let max_cltv_expiry = self.best_block.read().unwrap().height() + LATENCY_GRACE_PERIOD_BLOCKS;
let payee_tlvs = ReceiveTlvs {
payment_secret,
payment_constraints: PaymentConstraints {
max_cltv_expiry,
htlc_minimum_msat: 1,
},
};
self.router.create_blinded_payment_paths(
payee_node_id, first_hops, payee_tlvs, amount_msats, count, entropy_source, secp_ctx
)
}

/// Gets a fake short channel id for use in receiving [phantom node payments]. These fake scids
/// are used when constructing the phantom invoice's route hints.
///
Expand Down Expand Up @@ -9091,7 +9134,7 @@ where
let amount_msats = match InvoiceBuilder::<DerivedSigningPubkey>::amount_msats(
&invoice_request
) {
Ok(amount_msats) => Some(amount_msats),
Ok(amount_msats) => amount_msats,
Err(error) => return Some(OffersMessage::InvoiceError(error.into())),
};
let invoice_request = match invoice_request.verify(expanded_key, secp_ctx) {
Expand All @@ -9103,11 +9146,11 @@ where
};
let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32;

match self.create_inbound_payment(amount_msats, relative_expiry, None) {
match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) {
Ok((payment_hash, payment_secret)) if invoice_request.keys.is_some() => {
let payment_paths = vec![
self.create_one_hop_blinded_payment_path(payment_secret),
];
let payment_paths = self.create_blinded_payment_paths(
amount_msats, payment_secret, MAX_BLINDED_PAYMENT_PATHS
);
#[cfg(not(feature = "no-std"))]
let builder = invoice_request.respond_using_derived_keys(
payment_paths, payment_hash
Expand All @@ -9126,9 +9169,9 @@ where
}
},
Ok((payment_hash, payment_secret)) => {
let payment_paths = vec![
self.create_one_hop_blinded_payment_path(payment_secret),
];
let payment_paths = self.create_blinded_payment_paths(
amount_msats, payment_secret, MAX_BLINDED_PAYMENT_PATHS
);
#[cfg(not(feature = "no-std"))]
let builder = invoice_request.respond_with(payment_paths, payment_hash);
#[cfg(feature = "no-std")]
Expand Down

0 comments on commit a82bc73

Please sign in to comment.