Skip to content

Introduce Stronger Typing for VerifiedInvoiceRequest and Refactor Invoice Building Flow #3964

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

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

Conversation

shaavan
Copy link
Member

@shaavan shaavan commented Jul 26, 2025

Previously, VerifiedInvoiceRequest used an optional field to decide between calling using_derived_key or using_explicit_key invoice builders. However, this approach relied on runtime checks, and didn't enforce the correct builder usage at compile time.

To address this, this PR introduces a stronger type distinction by parameterizing VerifiedInvoiceRequest with a SigningPubkeyStrategy. This ensures that only the appropriate builder method (using_derived_key or using_explicit_key) is available for the corresponding variant, enforcing correctness at compile time.

This change also refactors the downstream invoice_builder interface in OffersMessageFlow by taking the following steps:

  • Split the builder method based on the VerifiedInvoiceRequest variant, ensuring that only the correct method can be called, and shifting the responsibility of matching the variant to the user at compile time.
  • Move signing logic back to ChannelManager, aligning with the pattern used in other builders. This allows users to further customize the InvoiceBuilder before signing.
  • Introduce a closure for (payment_hash, payment_secret) generation, consolidating the amount_msats input into a single source of truth. This ensures consistency between invoice creation and payment path generation.

In the upcoming commits, we will be phasing the current style of
VerifiedInvoiceRequest, in favour of newer version.
To keep the changes modular, and clean we rename the current
VerifiedInvoiceRequest to VerifiedInvoiceRequestLegacy.
@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Jul 26, 2025

👋 Thanks for assigning @jkczyz as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@shaavan
Copy link
Member Author

shaavan commented Jul 26, 2025

cc @jkczyz

@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @valentinewallace! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@jkczyz jkczyz self-requested a review July 29, 2025 15:21
@ldk-reviews-bot
Copy link

🔔 2nd Reminder

Hey @jkczyz @valentinewallace! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @jkczyz @valentinewallace! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 3rd Reminder

Hey @jkczyz @valentinewallace! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 2nd Reminder

Hey @jkczyz @valentinewallace! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 4th Reminder

Hey @jkczyz @valentinewallace! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 3rd Reminder

Hey @jkczyz @valentinewallace! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.


/// An enum representing a verified invoice request, which can either have derived signing keys or
/// require explicit signing keys.
pub enum VerifiedInvoiceRequestEnum {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we name this InvoiceRequestVerifiedFromOffer. Would like to avoid the Enum suffix.

Copy link
Member Author

Choose a reason for hiding this comment

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

Since this enum contains the verified invoice request used to build the corresponding invoice, and distinguishes between the signing strategies used to sign that invoice, I felt that the name InvoiceSigningInfo could reflect its role clearly.

I’ve introduced this name in pr3964.02 — would love to hear your thoughts! Thanks a lot!

@ldk-reviews-bot
Copy link

🔔 5th Reminder

Hey @valentinewallace! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

shaavan added 5 commits August 6, 2025 18:01
In the following commits we will introduce `fields` function
for other types as well, so to keep code DRY we convert the
function to a macro.
This commit reintroduces `VerifiedInvoiceRequest`, now parameterized by
`SigningPubkeyStrategy`.

The key motivation is to restrict which functions can be called on a
`VerifiedInvoiceRequest` based on its strategy type. This enables
compile-time guarantees — ensuring that an incorrect `InvoiceBuilder`
cannot be constructed for a given request, and misuses are caught early.
This commit replaces the legacy `VerifiedInvoiceRequestLegacy`
with the new `InvoiceSigningInfo` type in the codebase.
This change improves type safety and architectural clarity
by introducing dedicated `InvoiceBuilder` methods tied to
each variant of `VerifiedInvoiceRequestEnum`.

With this change, users are now required to match on the
enum variant before calling the corresponding builder method.
This pushes the responsibility of selecting the correct
builder to the user and ensures that invalid builder
usage is caught at compile time, rather than relying
on runtime checks.

The signing logic has also been moved from the builder
to the `ChannelManager`. This shift simplifies the
builder's role and aligns it with the rest of the API,
where builder methods return a configurable object that
can be extended before signing. The result is a more
consistent and predictable interface that separates
concerns cleanly and makes future maintenance easier.
To ensure correct Bolt12 payment flow behavior, the `amount_msats`
used for generating the `payment_hash`, `payment_secret`,
and payment path must remain consistent. Previously, these steps
could inadvertently diverge due to separate sources of `amount_msats`.

This commit refactors the interface to use a `get_payment_info` closure,
which captures the required variables and provides a single source of
truth for both payment info (payment_hash, payment_secret) and path
generation. This ensures consistency and eliminates subtle bugs
that could arise from mismatched amounts across the flow.
@shaavan
Copy link
Member Author

shaavan commented Aug 7, 2025

Updated from pr3964.01 to pr3964.02 (diff):
Addressed @jkczyz comments

Changes:

  1. Improved functional naming, and documentations.

Copy link

codecov bot commented Aug 7, 2025

Codecov Report

❌ Patch coverage is 71.91011% with 50 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.92%. Comparing base (5ceb625) to head (67a6c09).
⚠️ Report is 95 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/channelmanager.rs 28.20% 25 Missing and 3 partials ⚠️
lightning/src/offers/invoice_request.rs 79.62% 11 Missing ⚠️
lightning/src/offers/flow.rs 89.65% 0 Missing and 6 partials ⚠️
lightning/src/offers/invoice.rs 76.47% 3 Missing and 1 partial ⚠️
lightning/src/ln/offers_tests.rs 87.50% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main    #3964    +/-   ##
========================================
  Coverage   88.92%   88.92%            
========================================
  Files         173      174     +1     
  Lines      123794   124624   +830     
  Branches   123794   124624   +830     
========================================
+ Hits       110081   110820   +739     
- Misses      11253    11302    +49     
- Partials     2460     2502    +42     
Flag Coverage Δ
fuzzing 22.15% <2.00%> (-0.06%) ⬇️
tests 88.75% <71.91%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ldk-reviews-bot
Copy link

🔔 6th Reminder

Hey @valentinewallace! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

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.

3 participants