Skip to content

Commit 7f67ee5

Browse files
committed
WIP: Include blinded paths
1 parent ec5dd4b commit 7f67ee5

File tree

3 files changed

+72
-13
lines changed

3 files changed

+72
-13
lines changed

lightning/src/ln/channelmanager.rs

+51-4
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ use crate::offers::invoice_request::InvoiceRequestBuilder;
5858
use crate::offers::offer::{Offer, OfferBuilder};
5959
use crate::offers::parse::SemanticError;
6060
use crate::offers::refund::RefundBuilder;
61+
use crate::onion_message::BlindedPath;
6162
use crate::util::config::{UserConfig, ChannelConfig};
6263
use crate::util::events::{Event, EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination};
6364
use crate::util::events;
@@ -5434,6 +5435,10 @@ where
54345435
/// Creates an [`OfferBuilder`] such that the [`Offer`] it builds is recognized by the
54355436
/// [`OnionMessenger`] when handling [`InvoiceRequest`] messages for the offer.
54365437
///
5438+
/// Uses [`Router::find_partial_paths`] to construct a [`BlindedPath`] for the offer. If one is
5439+
/// found, also uses a derived signing pubkey for recipient privacy. Otherwise, uses the node id
5440+
/// as the signing pubkey.
5441+
///
54375442
/// [`Offer`]: crate::offers::offer::Offer
54385443
/// [`OnionMessenger`]: crate::onion_message::OnionMessenger
54395444
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
@@ -5442,13 +5447,25 @@ where
54425447
let expanded_key = &self.inbound_payment_key;
54435448
let nonce = inbound_payment::Nonce::from_entropy_source(&*self.entropy_source);
54445449

5445-
// TODO: Set blinded paths
5446-
OfferBuilder::deriving_signing_pubkey(description, node_id, expanded_key, nonce)
5450+
match self.create_blinded_paths(1) {
5451+
Ok(paths) if !paths.is_empty() => {
5452+
OfferBuilder::deriving_signing_pubkey(description, node_id, expanded_key, nonce)
5453+
.path(paths.into_iter().next().unwrap())
5454+
},
5455+
// TODO: check if node is public?
5456+
Ok(_) | Err(_) => {
5457+
OfferBuilder::deriving_signing_pubkey(description, node_id, expanded_key, nonce)
5458+
},
5459+
}
54475460
}
54485461

54495462
/// Creates a [`RefundBuilder`] such that the [`Refund`] it builds is recognized by the
54505463
/// [`OnionMessenger`] when handling [`Invoice`] messages for the refund.
54515464
///
5465+
/// Uses [`Router::find_partial_paths`] to construct a [`BlindedPath`] for the refund. If one is
5466+
/// found, also uses a derived payer id for sender privacy. Otherwise, uses the node id as the
5467+
/// payer id.
5468+
///
54525469
/// [`Refund`]: crate::offers::refund::Refund
54535470
/// [`OnionMessenger`]: crate::onion_message::OnionMessenger
54545471
/// [`Invoice`]: crate::offers::invoice::Invoice
@@ -5459,8 +5476,21 @@ where
54595476
let expanded_key = &self.inbound_payment_key;
54605477
let nonce = inbound_payment::Nonce::from_entropy_source(&*self.entropy_source);
54615478

5462-
// TODO: Set blinded paths
5463-
RefundBuilder::deriving_payer_id(description, node_id, expanded_key, nonce, amount_msats)
5479+
let builder = match self.create_blinded_paths(1) {
5480+
Ok(paths) if !paths.is_empty() => {
5481+
RefundBuilder::deriving_payer_id(
5482+
description, node_id, expanded_key, nonce, amount_msats
5483+
)?.path(paths.into_iter().next().unwrap())
5484+
},
5485+
// TODO: check if node is public?
5486+
Ok(_) | Err(_) => {
5487+
RefundBuilder::deriving_payer_id(
5488+
description, node_id, expanded_key, nonce, amount_msats
5489+
)?
5490+
},
5491+
};
5492+
5493+
Ok(builder)
54645494
}
54655495

54665496
/// Creates an [`InvoiceRequestBuilder`] such that the [`InvoiceRequest`] it builds is
@@ -5608,6 +5638,23 @@ where
56085638
inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key)
56095639
}
56105640

5641+
///
5642+
fn create_blinded_paths(&self, count: usize) -> Result<Vec<BlindedPath>, ()> {
5643+
let last_hops = self.per_peer_state.read().unwrap().iter()
5644+
.filter(|(_, peer)| peer.lock().unwrap().latest_features.supports_route_blinding())
5645+
.map(|(node_id, _)| *node_id)
5646+
.collect::<Vec<_>>();
5647+
let entropy_source = self.entropy_source.deref();
5648+
let secp_ctx = &self.secp_ctx;
5649+
5650+
self.router
5651+
.find_partial_paths(self.get_our_node_id(), last_hops.as_slice())?
5652+
.into_iter()
5653+
.map(|node_pks| BlindedPath::without_id(&node_pks[..], entropy_source, secp_ctx))
5654+
.take(count)
5655+
.collect()
5656+
}
5657+
56115658
/// Gets a fake short channel id for use in receiving [phantom node payments]. These fake scids
56125659
/// are used when constructing the phantom invoice's route hints.
56135660
///

lightning/src/onion_message/blinded_path.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -62,26 +62,26 @@ impl BlindedPath {
6262
/// will be the destination node and will receive the `path_id`.
6363
///
6464
/// Errors if less than two hops are provided or if `node_pk`(s) are invalid.
65-
pub fn with_id<ES: EntropySource, T: secp256k1::Signing + secp256k1::Verification>(
66-
id: [u8; 32], node_pks: &[PublicKey], entropy_source: &ES, secp_ctx: &Secp256k1<T>
67-
) -> Result<Self, ()> {
65+
pub fn with_id<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
66+
id: [u8; 32], node_pks: &[PublicKey], entropy_source: ES, secp_ctx: &Secp256k1<T>
67+
) -> Result<Self, ()> where ES::Target: EntropySource {
6868
Self::new(Some(id), node_pks, entropy_source, secp_ctx)
6969
}
7070

7171
/// Create a blinded path to be forwarded along `node_pks`. The last node pubkey in `node_pks`
7272
/// will be the destination node.
7373
///
7474
/// Errors if less than two hops are provided or if `node_pk`(s) are invalid.
75-
pub fn without_id<ES: EntropySource, T: secp256k1::Signing + secp256k1::Verification>(
76-
node_pks: &[PublicKey], entropy_source: &ES, secp_ctx: &Secp256k1<T>
77-
) -> Result<Self, ()> {
75+
pub fn without_id<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
76+
node_pks: &[PublicKey], entropy_source: ES, secp_ctx: &Secp256k1<T>
77+
) -> Result<Self, ()> where ES::Target: EntropySource {
7878
Self::new(None, node_pks, entropy_source, secp_ctx)
7979
}
8080

8181
// TODO: make all payloads the same size with padding + add dummy hops
82-
fn new<ES: EntropySource, T: secp256k1::Signing + secp256k1::Verification>(
83-
id: Option<[u8; 32]>, node_pks: &[PublicKey], entropy_source: &ES, secp_ctx: &Secp256k1<T>
84-
) -> Result<Self, ()> {
82+
fn new<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
83+
id: Option<[u8; 32]>, node_pks: &[PublicKey], entropy_source: ES, secp_ctx: &Secp256k1<T>
84+
) -> Result<Self, ()> where ES::Target: EntropySource {
8585
if node_pks.len() < 2 { return Err(()) }
8686
let blinding_secret_bytes = entropy_source.get_secure_random_bytes();
8787
let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");

lightning/src/routing/router.rs

+12
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ pub trait Router {
8181
&self, payer: &PublicKey, route_params: &RouteParameters,
8282
first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: &InFlightHtlcs
8383
) -> Result<Route, LightningError>;
84+
8485
/// Finds a [`Route`] between `payer` and `payee` for a payment with the given values. Includes
8586
/// `PaymentHash` and `PaymentId` to be able to correlate the request with a specific payment.
8687
fn find_route_with_id(
@@ -90,6 +91,17 @@ pub trait Router {
9091
) -> Result<Route, LightningError> {
9192
self.find_route(payer, route_params, first_hops, inflight_htlcs)
9293
}
94+
95+
/// Finds partial paths to the `recipient` node for creating `BlindedPath`s. The nodes in
96+
/// `peers` are assumed to be direct peers with the `recipient`.
97+
///
98+
/// The default implementation returns two-node paths for each node in `peers` with the
99+
/// `recipient` node.
100+
fn find_partial_paths(
101+
&self, recipient: PublicKey, peers: &[PublicKey]
102+
) -> Result<Vec<Vec<PublicKey>>, ()> {
103+
Ok(peers.iter().map(|hop| vec![*hop, recipient]).collect())
104+
}
93105
}
94106

95107
/// [`Score`] implementation that factors in in-flight HTLC liquidity.

0 commit comments

Comments
 (0)