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

[RFC] Implement a way to do BOLT 12 Proof of Payment #3593

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

vincenzopalazzo
Copy link
Contributor

@vincenzopalazzo vincenzopalazzo commented Feb 7, 2025

This is already possible if we manually_handle_bolt12_invoices, but
this approach requires a significant amount of work from the user.

This commit adds the bolt12 invoice to the PaymentSend event when
the payment is completed. This always gives the user the option to
provide proof of payment.

I am opening this up for an initial review, but I need to look inside the DNSSECProof to add this proof, but
probably be also a follow-up PR

Opening in draft for now to make the CI happy

Fixes: #3344

@vincenzopalazzo vincenzopalazzo marked this pull request as draft February 7, 2025 23:18
@vincenzopalazzo vincenzopalazzo force-pushed the macros/proof-of-payment-bolt12 branch from c7e9e61 to cc714ae Compare February 7, 2025 23:33
@vincenzopalazzo vincenzopalazzo force-pushed the macros/proof-of-payment-bolt12 branch from a5c211c to 9cdbb44 Compare February 10, 2025 16:59
@vincenzopalazzo vincenzopalazzo marked this pull request as ready for review February 10, 2025 16:59
@vincenzopalazzo vincenzopalazzo force-pushed the macros/proof-of-payment-bolt12 branch from 9cdbb44 to 8f5dc5e Compare February 10, 2025 20:19
Copy link

codecov bot commented Feb 10, 2025

Codecov Report

Attention: Patch coverage is 93.02326% with 3 lines in your changes missing coverage. Please review.

Project coverage is 89.71%. Comparing base (18166d0) to head (8f5dc5e).
Report is 31 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/offers_tests.rs 85.71% 1 Missing and 1 partial ⚠️
lightning/src/ln/outbound_payment.rs 95.45% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3593      +/-   ##
==========================================
+ Coverage   88.51%   89.71%   +1.19%     
==========================================
  Files         149      149              
  Lines      114968   126473   +11505     
  Branches   114968   126473   +11505     
==========================================
+ Hits       101768   113467   +11699     
+ Misses      10707    10609      -98     
+ Partials     2493     2397      -96     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

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

Thank you for picking this up! Sorry about the delay in review, not sure why this slipped through the cracks.

@@ -1259,7 +1271,7 @@ impl OutboundPayments {

let onion_session_privs = self.add_new_pending_payment(payment_hash,
recipient_onion.clone(), payment_id, keysend_preimage, &route, Some(retry_strategy),
Some(route_params.payment_params.clone()), entropy_source, best_block_height)
Some(route_params.payment_params.clone()), entropy_source, best_block_height, None)
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: might want to rename send_payment_internal to make explicit at callsites that this shouldn't be used for BOLT 12

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Choosing the name send_payment_for_non_bolt12_invoice in according with the other name send_payment_for_bolt12_invoice

This should show the difference between the function call, where send_payment_for_non_bolt12_invoice can be used everywhere there is a non-bolt12 workflow involved!

However, I am open to suggestions if you havea better naming convention to use!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in d831270

@@ -2291,6 +2305,7 @@ impl OutboundPayments {
payment_metadata: None, // only used for retries, and we'll never retry on startup
keysend_preimage: None, // only used for retries, and we'll never retry on startup
invoice_request: None, // only used for retries, and we'll never retry on startup
bolt12_invoice: None, // only used for retries, and we'll never retry on startup! TODO(vincenzopalazzo): double check this
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm, yea, we actually might want to store these somehow. Can happen in a later PR though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok so I will add a comment inside the main issue to track it down and I will open a followup PR in the next week! as I was planning for the DNS sec proof. Thanks

@vincenzopalazzo
Copy link
Contributor Author

vincenzopalazzo commented Feb 16, 2025

Thanks for the review @TheBlueMatt, I applied the suggestion in the review. In the meanwhile, I rebased on top of main to fix the conflict and ran the CI again

@vincenzopalazzo vincenzopalazzo force-pushed the macros/proof-of-payment-bolt12 branch from 0e7b503 to a4897fb Compare February 16, 2025 13:11
This commit prepares the code to pass down the BOLT12 invoice
inside the `PaymentSent` event.

To achieve this, the `bolt12` field has been added to the
`PendingOutboundPayment::Retryable` enum, allowing it to be
attached to the `PaymentSent` event when the payment is completed.

Link: lightningdevkit#3344
Signed-off-by: Vincenzo Palazzo <[email protected]>
To enable proof of payment, we need to share the bolt12 invoice with the library user.

This is already possible if we `manually_handle_bolt12_invoices`, but
this approach requires a significant amount of work from the user.

This commit adds the bolt12 invoice to the PaymentSend event when
the payment is completed. This allows the user to always have the option to
perform proof of payment.

Link: lightningdevkit#3344
Signed-off-by: Vincenzo Palazzo <[email protected]>
@vincenzopalazzo vincenzopalazzo force-pushed the macros/proof-of-payment-bolt12 branch from a4897fb to 2c65d6a Compare March 3, 2025 19:15
@@ -1090,6 +1112,7 @@ impl OutboundPayments {
.take()
.ok_or(Bolt12PaymentError::UnexpectedInvoice)?
.invoice_request,
static_invoice: String::from("we should have the static invoice here"),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yea, should be easy to pass it form the callsite.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yep sorry I pushed the code but I was not happy for the approach, I am rolling back the static invoice work and see if I can come up with a clean approach today!

Thanks for the comments, tho!

@vincenzopalazzo vincenzopalazzo force-pushed the macros/proof-of-payment-bolt12 branch from 9b72246 to 2c65d6a Compare March 5, 2025 16:31
…ceReceived

This is tricky because we need to work with the conditional compilation
and inside macros that persist this event the conditional compilation
is not available (if I understand correctly).

Signed-off-by: Vincenzo Palazzo <[email protected]>
@vincenzopalazzo
Copy link
Contributor Author

Ok @TheBlueMatt this PR is really funny to work! I worked to clean up the PR a bit and divide the code to support both Bolt12 and static invoices. However, I am currently working on supporting the async payment functionality. As far as I understand, the code involving async payments is a bit tricky to support for the following reasons (code available 85c3f73).

The async workflow is initialized with initiate_async_payment, where we pass down the payment_id and the static invoice value. Then we call static_invoice_received, which generates the event PendingOutboundPayment::StaticInvoiceReceived. After that, we iterate over the entry in send_payment_for_static_invoice and follow the Bolt12 pay code path (at this point, we need to pass down the static invoice).

The only way I have to access the static invoice when passing it down inside PendingOutboundPayment::StaticInvoiceReceived breaks the storage code because the static invoice is not available without cfg(async_payment).

  • Is there any way to use the persistence macros (impl_writeable_tlv_based_enum_upgradable) with a cfg?
  • If we want to read and pass the static invoice in PendingOutboundPayment::StaticInvoiceReceived, we could store a serialized version of the static invoice (a sequence of bytes), but this seems rather hacky.
  • I still need to delve into the mechanics of async payment as implemented in LDK, but if I understand correctly, there is a refactoring that I can do to make access to the static invoice a bit easier?

I would prefer the 3rd point, but this requires a follow-up PR to rework a little bit how the async payment is handled and I do not know if there is any plan for that,t or there is other code that will be depending on this architecture in the pipeline.

Probably @valentinewallace will be interested in this conversation

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

Successfully merging this pull request may close these issues.

BOLT 12 Proof of Payment
2 participants