-
Notifications
You must be signed in to change notification settings - Fork 418
Enable Creation of Offers and Refunds Without Blinded Path #3246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e8f5f90
5bc12d4
d6099c3
d78d640
26e4fe6
1a57e63
ddb1167
d6292d1
512e825
80e7385
596cf47
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -159,7 +159,9 @@ mod test { | |
use bitcoin::secp256k1::{self, PublicKey, Secp256k1}; | ||
use bitcoin::Block; | ||
|
||
use lightning::blinded_path::message::{BlindedMessagePath, MessageContext}; | ||
use lightning::blinded_path::message::{ | ||
BlindedMessagePath, MessageContext, MessageForwardNode, | ||
}; | ||
use lightning::blinded_path::NodeIdLookUp; | ||
use lightning::events::{Event, PaymentPurpose}; | ||
use lightning::ln::channelmanager::{PaymentId, Retry}; | ||
|
@@ -228,7 +230,7 @@ mod test { | |
|
||
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>( | ||
&self, recipient: PublicKey, local_node_receive_key: ReceiveAuthKey, | ||
context: MessageContext, _peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>, | ||
context: MessageContext, _peers: Vec<MessageForwardNode>, secp_ctx: &Secp256k1<T>, | ||
) -> Result<Vec<BlindedMessagePath>, ()> { | ||
let keys = KeysManager::new(&[0; 32], 42, 43); | ||
Ok(vec![BlindedMessagePath::one_hop( | ||
|
@@ -465,7 +467,7 @@ mod test { | |
#[tokio::test] | ||
async fn end_to_end_test() { | ||
let chanmon_cfgs = create_chanmon_cfgs(2); | ||
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); | ||
let node_cfgs = create_node_cfgs_with_node_id_message_router(2, &chanmon_cfgs); | ||
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); | ||
let nodes = create_network(2, &node_cfgs, &node_chanmgrs); | ||
|
||
|
@@ -491,7 +493,7 @@ mod test { | |
|
||
let name = HumanReadableName::from_encoded("[email protected]").unwrap(); | ||
|
||
let bs_offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap(); | ||
let bs_offer = nodes[1].node.create_offer_builder().unwrap().build().unwrap(); | ||
let resolvers = vec![Destination::Node(resolver_id)]; | ||
let retry = Retry::Attempts(0); | ||
let amt = 42_000; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2157,9 +2157,8 @@ where | |
/// # | ||
/// # fn example<T: AChannelManager>(channel_manager: T) -> Result<(), Bolt12SemanticError> { | ||
/// # let channel_manager = channel_manager.get_cm(); | ||
/// # let absolute_expiry = None; | ||
/// let offer = channel_manager | ||
/// .create_offer_builder(absolute_expiry)? | ||
/// .create_offer_builder()? | ||
/// # ; | ||
/// # // Needed for compiling for c_bindings | ||
/// # let builder: lightning::offers::offer::OfferBuilder<_, _> = offer.into(); | ||
|
@@ -2970,9 +2969,7 @@ const MAX_NO_CHANNEL_PEERS: usize = 250; | |
/// short-lived, while anything with a greater expiration is considered long-lived. | ||
/// | ||
/// Using [`ChannelManager::create_offer_builder`] or [`ChannelManager::create_refund_builder`], | ||
/// will included a [`BlindedMessagePath`] created using: | ||
/// - [`MessageRouter::create_compact_blinded_paths`] when short-lived, and | ||
/// - [`MessageRouter::create_blinded_paths`] when long-lived. | ||
/// will include a [`BlindedMessagePath`] created using [`MessageRouter::create_blinded_paths`]. | ||
/// | ||
/// Using compact [`BlindedMessagePath`]s may provide better privacy as the [`MessageRouter`] could select | ||
/// more hops. However, since they use short channel ids instead of pubkeys, they are more likely to | ||
|
@@ -11465,10 +11462,8 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => { | |
/// | ||
/// # Privacy | ||
/// | ||
/// Uses [`MessageRouter`] to construct a [`BlindedMessagePath`] for the offer based on the given | ||
/// `absolute_expiry` according to [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`]. See those docs for | ||
/// privacy implications as well as those of the parameterized [`Router`], which implements | ||
/// [`MessageRouter`]. | ||
/// Uses the [`MessageRouter`] provided to the [`ChannelManager`] at construction to build a | ||
/// [`BlindedMessagePath`] for the offer. See those docs for privacy implications. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly here, not sure what "those docs" refers to, we can probably just drop that sentence or rephrase as "see the documentation for the selected This applies elsewhere here including for refunds as well as in flow.rs for both offers and refunds. |
||
/// | ||
/// Also, uses a derived signing pubkey in the offer for recipient privacy. | ||
/// | ||
|
@@ -11478,17 +11473,40 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => { | |
/// | ||
/// # Errors | ||
/// | ||
/// Errors if the parameterized [`Router`] is unable to create a blinded path for the offer. | ||
/// Errors if the parameterized [`MessageRouter`] is unable to create a blinded path for the offer. | ||
/// | ||
/// [`BlindedMessagePath`]: crate::blinded_path::message::BlindedMessagePath | ||
/// [`Offer`]: crate::offers::offer::Offer | ||
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest | ||
pub fn create_offer_builder( | ||
&$self, absolute_expiry: Option<Duration> | ||
) -> Result<$builder, Bolt12SemanticError> { | ||
let entropy = &*$self.entropy_source; | ||
pub fn create_offer_builder(&$self) -> Result<$builder, Bolt12SemanticError> { | ||
let builder = $self.flow.create_offer_builder( | ||
&*$self.entropy_source, $self.get_peers_for_blinded_path() | ||
)?; | ||
|
||
let builder = $self.flow.create_offer_builder(entropy, absolute_expiry, $self.get_peers_for_blinded_path())?; | ||
Ok(builder.into()) | ||
} | ||
|
||
/// Same as [`Self::create_offer_builder`], but allows specifying a custom [`MessageRouter`] | ||
/// instead of using the [`MessageRouter`] provided to the [`ChannelManager`] at construction. | ||
/// | ||
/// This gives users full control over how the [`BlindedMessagePath`] is constructed, | ||
/// including the option to omit it entirely. | ||
/// | ||
/// See [`Self::create_offer_builder`] for details on offer construction, privacy, and limitations. | ||
/// | ||
/// [`BlindedMessagePath`]: crate::blinded_path::message::BlindedMessagePath | ||
/// [`Offer`]: crate::offers::offer::Offer | ||
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest | ||
pub fn create_offer_builder_using_router<ME: Deref>( | ||
&$self, | ||
router: ME, | ||
) -> Result<$builder, Bolt12SemanticError> | ||
where | ||
ME::Target: MessageRouter, | ||
{ | ||
let builder = $self.flow.create_offer_builder_using_router( | ||
router, &*$self.entropy_source, $self.get_peers_for_blinded_path() | ||
)?; | ||
|
||
Ok(builder.into()) | ||
} | ||
|
@@ -11519,8 +11537,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => { | |
/// | ||
/// Uses [`MessageRouter`] to construct a [`BlindedMessagePath`] for the refund based on the given | ||
/// `absolute_expiry` according to [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`]. See those docs for | ||
/// privacy implications as well as those of the parameterized [`Router`], which implements | ||
/// [`MessageRouter`]. | ||
/// privacy implications. | ||
/// | ||
/// Also, uses a derived payer id in the refund for payer privacy. | ||
/// | ||
|
@@ -11558,6 +11575,55 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => { | |
|
||
Ok(builder.into()) | ||
} | ||
|
||
/// Same as [`Self::create_refund_builder`], but allows specifying a custom [`MessageRouter`] | ||
/// instead of using the one provided during [`ChannelManager`] construction for | ||
/// [`BlindedMessagePath`] creation. | ||
/// | ||
/// This gives users full control over how the [`BlindedMessagePath`] is constructed for the | ||
/// refund, including the option to omit it entirely. This is useful for testing or when | ||
/// alternative privacy strategies are needed. | ||
/// | ||
/// See [`Self::create_refund_builder`] for: | ||
/// - refund recognition by [`ChannelManager`] via [`Bolt12Invoice`] handling, | ||
/// - `payment_id` rules and expiration behavior, | ||
/// - invoice revocation and refund failure handling, | ||
/// - defaulting behavior for `max_total_routing_fee_msat`, | ||
/// - and detailed payment and privacy semantics. | ||
/// | ||
/// # Errors | ||
/// | ||
/// In addition to the errors in [`Self::create_refund_builder`], this returns an error if | ||
/// the provided [`MessageRouter`] fails to construct a valid [`BlindedMessagePath`] for the refund. | ||
/// | ||
/// [`Refund`]: crate::offers::refund::Refund | ||
/// [`BlindedMessagePath`]: crate::blinded_path::message::BlindedMessagePath | ||
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice | ||
pub fn create_refund_builder_using_router<ME: Deref>( | ||
&$self, router: ME, amount_msats: u64, absolute_expiry: Duration, payment_id: PaymentId, | ||
retry_strategy: Retry, route_params_config: RouteParametersConfig | ||
) -> Result<$builder, Bolt12SemanticError> | ||
where | ||
ME::Target: MessageRouter, | ||
{ | ||
let entropy = &*$self.entropy_source; | ||
|
||
let builder = $self.flow.create_refund_builder_using_router( | ||
router, entropy, amount_msats, absolute_expiry, | ||
payment_id, $self.get_peers_for_blinded_path() | ||
)?; | ||
|
||
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop($self); | ||
|
||
let expiration = StaleExpiration::AbsoluteTimeout(absolute_expiry); | ||
$self.pending_outbound_payments | ||
.add_new_awaiting_invoice( | ||
payment_id, expiration, retry_strategy, route_params_config, None, | ||
) | ||
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?; | ||
|
||
Ok(builder.into()) | ||
} | ||
} } | ||
|
||
impl< | ||
|
@@ -11716,8 +11782,7 @@ where | |
/// # Privacy | ||
/// | ||
/// For payer privacy, uses a derived payer id and uses [`MessageRouter::create_blinded_paths`] | ||
/// to construct a [`BlindedMessagePath`] for the reply path. For further privacy implications, see the | ||
/// docs of the parameterized [`Router`], which implements [`MessageRouter`]. | ||
/// to construct a [`BlindedMessagePath`] for the reply path. | ||
/// | ||
/// # Limitations | ||
/// | ||
|
@@ -11896,8 +11961,7 @@ where | |
/// # Privacy | ||
/// | ||
/// For payer privacy, uses a derived payer id and uses [`MessageRouter::create_blinded_paths`] | ||
/// to construct a [`BlindedMessagePath`] for the reply path. For further privacy implications, see the | ||
/// docs of the parameterized [`Router`], which implements [`MessageRouter`]. | ||
/// to construct a [`BlindedMessagePath`] for the reply path. | ||
/// | ||
/// # Limitations | ||
/// | ||
|
@@ -18213,7 +18277,7 @@ pub mod bench { | |
let scorer = RwLock::new(test_utils::TestScorer::new()); | ||
let entropy = test_utils::TestKeysInterface::new(&[0u8; 32], network); | ||
let router = test_utils::TestRouter::new(Arc::new(NetworkGraph::new(network, &logger_a)), &logger_a, &scorer); | ||
let message_router = test_utils::TestMessageRouter::new(Arc::new(NetworkGraph::new(network, &logger_a)), &entropy); | ||
let message_router = test_utils::TestMessageRouter::new_default(Arc::new(NetworkGraph::new(network, &logger_a)), &entropy); | ||
|
||
let mut config: UserConfig = Default::default(); | ||
config.channel_config.max_dust_htlc_exposure = MaxDustHTLCExposure::FeeRateMultiplier(5_000_000 / 253); | ||
|
Uh oh!
There was an error while loading. Please reload this page.