Skip to content
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

[2/4] Route Blinding Receives: Receive and send to a single blinded path in an invoice. #8735

Open
wants to merge 14 commits into
base: elle-rb-receives-1
Choose a base branch
from

Conversation

ellemouton
Copy link
Collaborator

@ellemouton ellemouton commented May 7, 2024

Tracking Issue: #6690

Depends on #8752

High level overview:

This PR is the first in a set of 3 PRs that will implement route blinding receive logic in LND.
As LND does not yet support blot 12 invoices, this PR adds them to the Bolt11 invoice serialisation.

With this PR, a user can request that a bolt 11 invoice include blinded paths and will also
be able to pay to a bolt 11 invoice that includes blinded paths. However, with this PR, only one of the
paths in the invoice will be used. A follow up PR will add the ability to make use of multiple paths.

Lower level overview:

  1. Logic for constructing a full blinded payment path packet given a candidate route to ourselves.
  2. Graph traversal logic for finding a set of candidate routes to ourselves to use in a blinded path.
  3. Various receiver side updates to ensure that we correctly handle an incoming payment from a blinded route (by for example, extracting the payment address from the pathID). Also a few updates for the case where we receive MP payments for a blinded path.
  4. A couple of sender side updates to ensure that MP payments to a single blinded path can work
  5. Updates and additions to the route blinding itests to cover the new receive logic :)

Copy link

coderabbitai bot commented May 14, 2024

Important

Auto Review Skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ellemouton ellemouton changed the title [1/3] Route Blinding Receives: Receive to a single blinded path in an invoice. [2/3] Route Blinding Receives: Receive and send to a single blinded path in an invoice. May 14, 2024
@ellemouton ellemouton force-pushed the rb-receives branch 2 times, most recently from a7c5c6d to 09d0075 Compare May 15, 2024 10:59
@ellemouton ellemouton changed the base branch from master to elle-rb-receives-1 May 15, 2024 11:00
expectedFinalSize: 10,
},
{
name: "existing padding and diff of 1",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: the fact that it takes 2 iterations less by just having an existing Padding field might warrant that we just add a zero length padding field from the get go?

// incMultiplier while the maximum HTLC msat value is adjusted via the
// decMultiplier. If adjustments of the HTLC values no longer make sense
// then the original HTLC value is used.
func addPolicyBuffer(policy *models.ChannelEdgePolicy,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a naive first implementation. Some thoughts:

  1. We could have different multipliers for each field
  2. Perhaps not good enough to just multiply by a constant cause this might let the sender do some fingerprinting especially in the case where the route is super short. So perhaps we should also round to the nearest 10 or something?


// FindBlindedPaths finds a selection of paths to the destination node that can
// be used in blinded payment paths.
func (r *ChannelRouter) FindBlindedPaths(destination route.Vertex,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some food for thought here:

  • If we let the user set a non-equal MinHops and MaxHops, then this gonna pretty much select the shortest paths as is.. since those will always have the largest success probability. So perhaps we should also have a MinNumPaths and then always only select paths of the same length as long there are enough with that length to satisfy the MinNumPaths?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • we also in general probably dont want to include paths of diff lengths. Currently the user has the power to enforce this through just setting MaxNumHops = MinNumHops but I dont think they should have to do that

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wanna hear other people's thoughts before I update anything though

This commit adds a helper function called `padHopInfo` along with a test
for it. This function will be used later on when building a blinded
path. It is used to ensure that all encrypted blobs of a blinded path
that we construct are padded to the same size.
This commit adds a function that can be used to compute the accumulated
path policy for a blinded path as defined in the spec:

https://github.com/lightning/bolts/blob/db278ab9b2baa0b30cfe79fb3de39280595938d3/04-onion-routing.md?plain=1#L255
This commit adds a helper function that will be used to adjust a hops
policy values by certain given increase and decrease multipliers. This
will be used in blinded paths to give policy values some buffer to avoid
easy probing of blinded paths.
This commit adds all the logic for building a blinded path (from a given
route) and packaging it up in a zpay32.BlindedPaymentPath struct so that
it is ready for adding to an invoice.

Note that in this commit, the logic for choosing an actual path to us
that can then be used in a blinded path is abstracted away. This logic
will be fleshed out in a future commit.
Here we add a new `Blind` option to the `AddInvoiceData` which will
signal that the new invoice should encode a blinded route.

Certain other changes are also made in the case that this invoice
contains a blinded route:
1) the payment address/secret no longer needs to be in the invoice
   itself since it will be put in the `PathID` recored of the encrypted
   recipient record for our hop.
2) When we sign the invoice, we now use an ephemeral key since we dont
   want the sender to be able to derive our real node pub key from the
   invoice signature.
3) The invoice's FinalCLTV field should be zero for blinded invoices
   since the CLTV delta info will be communicated in the accumulated
   route policy values.
This commit adds a new function, `findBlindedPaths`, that does a depth
first search from the target node to find a set of blinded paths to the
target node given the set of restrictions. This function will select and
return any candidate path. A candidate path is a path to the target node
with a size determined by the given hop number constraints where all the
nodes on the path signal the route blinding feature _and_ the
introduction node for the path has more than one public channel. Any
filtering of paths based on payment value or success probabilities is
left to the caller.
Add a `FindBlindedPaths` method to the `ChannelRouter` which will use
the new `findBlindedPaths` function to get a set of candidate blinded
path routes. It then uses mission control to select the best of these
paths.

Note that as of this commit, the MC data we get from these queries won't
mean much since we wont have data about a channel in the direction
towards us. But we do this now in preparation for a future PR which will
start writing mission control success pairs for successful receives from
blinded route paths.
Expose the ability to add blinded paths to an invoice. Also expose
various configuration values.

We also let the lncfg.Invoices struct satisfy the Validator interface so
that we can verify all its config values in one place.
We've covered all the logic for building a blinded path to ourselves and
putting that into an invoice - so now we start preparing to actually be
able to recognise the incoming payment as one from a blinded path we
created.

The incoming update_add_htlc will have an `encrypted_recipient_data`
blob for us that we would have put in the original invoice. From this we
extract the PathID which we wrote. We consider this the payment address
and we use this to derive the associated invoice location.

Blinded path payments will not include MPP records, so the payment
address and total payment amount must be gleaned from the pathID and new
totalAmtMsat onion field respectively.
The route blinding itests are now updated so that recipient logic is
tested. The creation of a blinded route is also now done through the
AddInvoice API instead of manually.
Update the SendPayment flow so that it is able to send to an invoice
containing a blinded path.
Update one of the route blinding itests to do a full end-to-end test
where the recipient generates and invoice with a blinded path and the
sender just provides that invoice to SendPayment.

The tests also covers the edge case where the recipient is the
introduction node.
Make various sender side adjustments so that a sender is able to send an
MP payment to a single blinded path without actually including an MPP
record in the payment.
@ellemouton ellemouton changed the title [2/3] Route Blinding Receives: Receive and send to a single blinded path in an invoice. [2/4] Route Blinding Receives: Receive and send to a single blinded path in an invoice. May 16, 2024
@saubyk
Copy link
Collaborator

saubyk commented May 16, 2024

cc: @calvinrzachman for review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants