-
Notifications
You must be signed in to change notification settings - Fork 403
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
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3246 +/- ##
==========================================
+ Coverage 89.26% 91.12% +1.85%
==========================================
Files 155 156 +1
Lines 119968 141224 +21256
Branches 119968 141224 +21256
==========================================
+ Hits 107092 128688 +21596
+ Misses 10265 10003 -262
+ Partials 2611 2533 -78 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
lightning/src/ln/offers_tests.rs
Outdated
assert_eq!(refund.payer_id(), alice_id); | ||
assert!(refund.paths().is_empty()); | ||
} | ||
|
||
/// Checks that blinded paths are compact for short-lived offers. | ||
#[test] | ||
fn creates_short_lived_offer() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming at least for the following tests is no longer relevant, it seems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I understand, with the introduction of BlindedPathParameters
, it seems like the behavior these tests were checking isn't relevant anymore. Should we think about removing these tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's wait on the resolution of #3246 (comment). We'll ultimately want to test cases allowed by whatever interface is exposed to the user.
7a18051
to
bc00884
Compare
Updated from pr3246.06 to pr3246.07 (diff): Changes:
|
bc00884
to
3bcc420
Compare
lightning/src/ln/channelmanager.rs
Outdated
let context = MessageContext::Offers(context); | ||
let path = $self | ||
.create_blinded_paths(context) | ||
.and_then(|paths| paths.into_iter().next().ok_or(())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... @TheBlueMatt I don't think this interface is sufficient to allow someone to specify they want more than one path in the offer, unless we include all the paths returned by the MessageRouter
instead of just one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, IMO we should include all paths - if the router wants to do something funky in the offer, so be it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What should we have DefaultMessageRouter
do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What we currently do (use the context of why we're asking for a path to decide how many paths to include)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose DefaultMessageRouter
could use both MessageContex
and BlindedPathType
-- or which MessageRouter
method is called, if we revert to that state -- to determine if more than one path should be returned. That way we'd allow users to pass BlindedPathType::Full
to create_offer_builder
such that they can create an offer with more than one path (e.g., when an offer doesn't need to be in a QR code).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, that makes sense but then I'm confused about your previous comment about keeping get interface the same as it is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we change MessageRouter
to only have one method, then we need to pass in BlindedPathType
. But then the peers
parameter will need to be Vec<MessageForwardNode>
even when used with BlindedPathType::Full
instead of Vec<PublicKey>
. So callers could pass in a MessageForwardNode
with an scid even though it isn't expected, resulting in the last hop being compact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So callers could pass in a MessageForwardNode with an scid even though it isn't expected, resulting in the last hop being compact.
Makes sense! I have reintroduced the two function flow back in pr3246.11
Also, I have updated the DefaultMessageRouter's create_compact_blinded_paths
to only return a single path in pr3246.11
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused why this is a concern, if the MessageRouter
insists on a specific type of blinded path in general, so what? Ideally the MessageRouter
gets to pick what it wants to do, though I think we're not allowed to have a compact introduction point in reply paths? Even in that case, though, ISTM we can communicate the restrictions and if the MessageRouter
is buggy we can just fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused why this is a concern, if the
MessageRouter
insists on a specific type of blinded path in general, so what? Ideally theMessageRouter
gets to pick what it wants to do,
Nothing is preventing a MessageRouter
from doing so. It would just need access to the channels.
It's just kinda ugly for DefaultMessageRouter
to need to clear short_channel_id
depending on how it is called. Plus, ChannelManager
needs to do additional lookups to get this information just to have it discarded. I'm fine either way, but it doesn't optimize the usual case (i.e., use non-compact paths for reply paths).
though I think we're not allowed to have a compact introduction point in reply paths? Even in that case, though, ISTM we can communicate the restrictions and if the
MessageRouter
is buggy we can just fail.
Yeah, though it doesn't look like we are enforcing this at the moment.
dd1401f
to
3c3224d
Compare
Updated from pr3246.16 to pr3246.17 (diff): Changes
Reasoning Open to thoughts or suggestions, of course! |
Previously, the `compact_paths` flag was only used to determine whether to use a compact introduction node when creating compact blinded paths. With the upcoming change to accept `MessageForwardNode` in `create_blinded_paths`, there's a risk of SCIDs being passed (and used) even when the user intends to create a full-length blinded path. This patch updates the logic in `create_blinded_paths_from_iter` to ignore SCIDs unless `compact_paths` is explicitly true—preserving correct behavior for full-length blinded paths.
f4b5919
to
ba0b3f1
Compare
Updated from pr3246.17 to pr3246.18 (diff): Changes:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go ahead an squash. @TheBlueMatt the approach is essentially what is described in #3246 (comment) without the helpers like without_blinded_paths
(i.e. constructing the alternative MessagesRouter
implementations using a constructor.
I'm definitely okay with having methods to override the router used, and like the changes to not decide in |
It could create compact paths by default if I guess by passing the |
To prepare for supporting both standard and compact blinded paths, this commit updates the `create_blinded_paths` function to take a `Vec<MessageForwardNode>` as input. This change ensures the function has all the information it needs to handle both types of blinded path creation. This refactor that sets the stage for upcoming enhancements.
Introduced two new default routers: - `CompactMessageRouter` – for creating compact blinded paths - `NullMessageRouter` – for intentionally creating no blinded paths This makes the purpose of each router explicit and ensures their functions remain unique. It also builds on the flexibility introduced in the previous commit, where `create_blinded_paths` was updated to support a MessageForwardNode.
Added a new helper function to encapsulate the logic for fetching peers used in blinded path creation. This keeps the code DRY by reducing duplication and makes the logic easier to reuse across different message routers.
Introduced two new builder functions that accept a custom `MessageRouter` as input. This gives users the flexibility to plug in their own router implementation, enabling custom logic for blinded path creation when building Offers or Refunds. It’s a step toward greater extensibility and control in how paths are constructed.
This change updates the default `create_offer_builder` to always use `create_blinded_paths`, enabling deterministic creation of only full-length blinded paths. Now that we provide `create_offer_builder_using_router`, users who need custom path logic (like compact blinded path) can pass in their own `MessageRouter`. This allows the default builder to remain simple and consistent, while offering flexibility through the alternate function.
Aligned the `create_refund_builder` logic with `create_offer_builder` by updating it to use `create_blinded_paths`. Now that custom routers can be passed via `create_refund_builder_using_router`, the default builder can consistently generate full-length blinded paths without branching logic. This simplifies the default behavior while keeping flexibility available for custom use cases.
With the recent updates to `create_blinded_paths` supporting flexible routing through `MessageRouter`, the specialized variants—`create_compact_blinded_paths` and `create_blinded_paths_using_absolute_expiry`—have become unnecessary. This commit removes those now-redundant functions to simplify the codebase and reduce maintenance overhead.
Introduced tests to validate the behavior of Offers and Refunds created without blinded paths, using `NullMessageRouter`.
Right, this is what I was thinking - give the router enough information to decide and let it decide, then let users override the router if they want to override the decision.
I guess if you want to always use a compact path (even for long-lived paths)? Could also have some kind of configurable router that just lets you pick the time limit.
Agreed, it can be a separate function tho. |
I see the point you're suggesting, Matt, and I agree there’s some convenience in having the router automatically decide the blinded path type based on The current approach has the benefit of being explicit and predictable. By default, we always generate a full-length path, providing a consistent baseline across all offers. If a user wants a compact path—for example, for short-lived offers—they can opt into it clearly via the router they pass in. Conversely, if the user parameterizes This trades away automatic decision-making by the router in favor of something I believe is more valuable in the long run: user awareness and control. It also avoids introducing heuristics that could surprise users unless they’re quite familiar with the internal logic. In that sense, prioritizing clear defaults and explicit opt-in behavior, I believe, makes the design more intuitive and easier to reason about over time. Curious to hear your thoughts—thanks! |
Regarding this point, I tend to agree that removing the |
PR Description:
An Offer and a Refund can exist without a blinded path, where the
signing_pubkey
is used to determine the destination. While we could already handle Offers and Refunds without a blinded path, we didn’t have a way to create them like this. This PR addresses that gap and simplifies the blinded path creation flow.The Key Changes:
Pass Router to Builders:
Both
create_offer_builder
andcreate_refund_builder
now take a router as a parameter. This gives users control over how blinded paths are created. For example, users can now choose not to include any blinded paths, or use a custom router for specific behavior.Unified Blinded Path Creation:
The Blinded Path creation has been simplified by only keeping a single function for Blinded Path creation, i.e.,
create_blinded_path
. Older, separate variants likecreate_compact_blinded_paths
andcreate_blinded_paths_using_absolute_expiry
are now redundant and have been removed. This makes the flow cleaner and easier to maintain.Router-Driven Flexibility:
The
DefaultMessageRouter
now uses aRouterConfig
to allow it to create any kind of blinded path (if any) to create. This simplifies the flow, while maintaining the same functionality.This PR makes blinded path creation more straightforward and gives users better control, while preserving the core logic of the
MessageRouter
.blocked on #3412