mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-01-19 05:43:55 +01:00
Multi-hop blinded paths in ChannelManager
When constructing blinded paths for Offer and Refund, delegate to MessageRouter::create_blinded_paths which may produce multi-hop blinded paths. Fallback to one-hop blinded paths if the MessageRouter fails or returns no paths. Likewise, do the same for InvoiceRequest and Bolt12Invoice reply paths.
This commit is contained in:
parent
dcd8d58346
commit
606304aa32
@ -65,7 +65,7 @@ use crate::offers::merkle::SignError;
|
||||
use crate::offers::offer::{DerivedMetadata, Offer, OfferBuilder};
|
||||
use crate::offers::parse::Bolt12SemanticError;
|
||||
use crate::offers::refund::{Refund, RefundBuilder};
|
||||
use crate::onion_message::{Destination, OffersMessage, OffersMessageHandler, PendingOnionMessage, new_pending_onion_message};
|
||||
use crate::onion_message::{Destination, MessageRouter, OffersMessage, OffersMessageHandler, PendingOnionMessage, new_pending_onion_message};
|
||||
use crate::sign::{EntropySource, KeysManager, NodeSigner, Recipient, SignerProvider};
|
||||
use crate::sign::ecdsa::WriteableEcdsaChannelSigner;
|
||||
use crate::util::config::{UserConfig, ChannelConfig, ChannelConfigUpdate};
|
||||
@ -7483,32 +7483,43 @@ where
|
||||
///
|
||||
/// # Privacy
|
||||
///
|
||||
/// Uses a one-hop [`BlindedPath`] for the offer with [`ChannelManager::get_our_node_id`] as the
|
||||
/// introduction node and a derived signing pubkey for recipient privacy. As such, currently,
|
||||
/// the node must be announced. Otherwise, there is no way to find a path to the introduction
|
||||
/// node in order to send the [`InvoiceRequest`].
|
||||
/// Uses [`MessageRouter::create_blinded_paths`] to construct a [`BlindedPath`] for the offer.
|
||||
/// However, if one is not found, uses a one-hop [`BlindedPath`] with
|
||||
/// [`ChannelManager::get_our_node_id`] as the introduction node instead. In the latter case,
|
||||
/// the node must be announced, otherwise, there is no way to find a path to the introduction in
|
||||
/// order to send the [`InvoiceRequest`].
|
||||
///
|
||||
/// Also, uses a derived signing pubkey in the offer for recipient privacy.
|
||||
///
|
||||
/// # Limitations
|
||||
///
|
||||
/// Requires a direct connection to the introduction node in the responding [`InvoiceRequest`]'s
|
||||
/// reply path.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Errors if the parameterized [`Router`] is unable to create a blinded path for the offer.
|
||||
///
|
||||
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
|
||||
///
|
||||
/// [`Offer`]: crate::offers::offer::Offer
|
||||
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
|
||||
pub fn create_offer_builder(
|
||||
&self, description: String
|
||||
) -> OfferBuilder<DerivedMetadata, secp256k1::All> {
|
||||
) -> Result<OfferBuilder<DerivedMetadata, secp256k1::All>, Bolt12SemanticError> {
|
||||
let node_id = self.get_our_node_id();
|
||||
let expanded_key = &self.inbound_payment_key;
|
||||
let entropy = &*self.entropy_source;
|
||||
let secp_ctx = &self.secp_ctx;
|
||||
let path = self.create_one_hop_blinded_path();
|
||||
|
||||
OfferBuilder::deriving_signing_pubkey(description, node_id, expanded_key, entropy, secp_ctx)
|
||||
let path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
|
||||
let builder = OfferBuilder::deriving_signing_pubkey(
|
||||
description, node_id, expanded_key, entropy, secp_ctx
|
||||
)
|
||||
.chain_hash(self.chain_hash)
|
||||
.path(path)
|
||||
.path(path);
|
||||
|
||||
Ok(builder)
|
||||
}
|
||||
|
||||
/// Creates a [`RefundBuilder`] such that the [`Refund`] it builds is recognized by the
|
||||
@ -7533,10 +7544,13 @@ where
|
||||
///
|
||||
/// # Privacy
|
||||
///
|
||||
/// Uses a one-hop [`BlindedPath`] for the refund with [`ChannelManager::get_our_node_id`] as
|
||||
/// the introduction node and a derived payer id for payer privacy. As such, currently, the
|
||||
/// node must be announced. Otherwise, there is no way to find a path to the introduction node
|
||||
/// in order to send the [`Bolt12Invoice`].
|
||||
/// Uses [`MessageRouter::create_blinded_paths`] to construct a [`BlindedPath`] for the refund.
|
||||
/// However, if one is not found, uses a one-hop [`BlindedPath`] with
|
||||
/// [`ChannelManager::get_our_node_id`] as the introduction node instead. In the latter case,
|
||||
/// the node must be announced, otherwise, there is no way to find a path to the introduction in
|
||||
/// order to send the [`Bolt12Invoice`].
|
||||
///
|
||||
/// Also, uses a derived payer id in the refund for payer privacy.
|
||||
///
|
||||
/// # Limitations
|
||||
///
|
||||
@ -7545,8 +7559,10 @@ where
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Errors if a duplicate `payment_id` is provided given the caveats in the aforementioned link
|
||||
/// or if `amount_msats` is invalid.
|
||||
/// Errors if:
|
||||
/// - a duplicate `payment_id` is provided given the caveats in the aforementioned link,
|
||||
/// - `amount_msats` is invalid, or
|
||||
/// - the parameterized [`Router`] is unable to create a blinded path for the refund.
|
||||
///
|
||||
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
|
||||
///
|
||||
@ -7561,8 +7577,8 @@ where
|
||||
let expanded_key = &self.inbound_payment_key;
|
||||
let entropy = &*self.entropy_source;
|
||||
let secp_ctx = &self.secp_ctx;
|
||||
let path = self.create_one_hop_blinded_path();
|
||||
|
||||
let path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
|
||||
let builder = RefundBuilder::deriving_payer_id(
|
||||
description, node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
|
||||
)?
|
||||
@ -7620,8 +7636,11 @@ where
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Errors if a duplicate `payment_id` is provided given the caveats in the aforementioned link
|
||||
/// or if the provided parameters are invalid for the offer.
|
||||
/// Errors if:
|
||||
/// - a duplicate `payment_id` is provided given the caveats in the aforementioned link,
|
||||
/// - the provided parameters are invalid for the offer,
|
||||
/// - the parameterized [`Router`] is unable to create a blinded reply path for the invoice
|
||||
/// request.
|
||||
///
|
||||
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
|
||||
/// [`InvoiceRequest::quantity`]: crate::offers::invoice_request::InvoiceRequest::quantity
|
||||
@ -7654,9 +7673,8 @@ where
|
||||
None => builder,
|
||||
Some(payer_note) => builder.payer_note(payer_note),
|
||||
};
|
||||
|
||||
let invoice_request = builder.build_and_sign()?;
|
||||
let reply_path = self.create_one_hop_blinded_path();
|
||||
let reply_path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
|
||||
|
||||
let expiration = StaleExpiration::TimerTicks(1);
|
||||
self.pending_outbound_payments
|
||||
@ -7732,7 +7750,8 @@ where
|
||||
payment_paths, payment_hash, created_at, expanded_key, entropy
|
||||
)?;
|
||||
let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
|
||||
let reply_path = self.create_one_hop_blinded_path();
|
||||
let reply_path = self.create_blinded_path()
|
||||
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
|
||||
|
||||
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
|
||||
if refund.paths().is_empty() {
|
||||
@ -7859,12 +7878,23 @@ where
|
||||
inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key)
|
||||
}
|
||||
|
||||
/// Creates a one-hop blinded path with [`ChannelManager::get_our_node_id`] as the introduction
|
||||
/// node.
|
||||
fn create_one_hop_blinded_path(&self) -> BlindedPath {
|
||||
/// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
|
||||
///
|
||||
/// Errors if the `MessageRouter` errors or returns an empty `Vec`.
|
||||
fn create_blinded_path(&self) -> Result<BlindedPath, ()> {
|
||||
let recipient = self.get_our_node_id();
|
||||
let entropy_source = self.entropy_source.deref();
|
||||
let secp_ctx = &self.secp_ctx;
|
||||
BlindedPath::one_hop_for_message(self.get_our_node_id(), entropy_source, secp_ctx).unwrap()
|
||||
|
||||
let peers = self.per_peer_state.read().unwrap()
|
||||
.iter()
|
||||
.filter(|(_, peer)| peer.lock().unwrap().latest_features.supports_onion_messages())
|
||||
.map(|(node_id, _)| *node_id)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
self.router
|
||||
.create_blinded_paths(recipient, peers, entropy_source, secp_ctx)
|
||||
.and_then(|paths| paths.into_iter().next().ok_or(()))
|
||||
}
|
||||
|
||||
/// Creates a one-hop blinded payment path with [`ChannelManager::get_our_node_id`] as the
|
||||
|
Loading…
Reference in New Issue
Block a user