-
Notifications
You must be signed in to change notification settings - Fork 427
[RFC] Add BOLT 12 payer proof primitives #4297
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?
[RFC] Add BOLT 12 payer proof primitives #4297
Conversation
Implements the payer proof extension to BOLT 12 as specified in lightning/bolts#1295. This allows proving that a BOLT 12 invoice was paid by demonstrating possession of the payment preimage, a valid invoice signature, and a payer signature. Key additions: - Extend merkle.rs with selective disclosure primitives for creating and reconstructing merkle trees with partial TLV disclosure - Add payer_proof.rs with PayerProof, PayerProofBuilder, and UnsignedPayerProof types for building and verifying payer proofs - Support bech32 encoding with "lnp" prefix
This commit improves the BOLT 12 payer proof implementation: - Rewrite reconstruct_positions() with a clearer algorithm that tracks "continuation vs jump" to reverse the marker encoding. The new algorithm is simpler and matches the spec example exactly. - Fix reconstruct_merkle_root() to correctly handle (None, None) cases by propagating None upward instead of pulling from missing_hashes immediately. The combined hash is only pulled when an omitted subtree meets an included subtree at a higher level. - Add comprehensive documentation comments explaining: - The marker algorithm and how it reverses during reconstruction - The missing_hashes order and nonce hash ambiguity - Add tests for the reconstruction algorithm
This commit addresses issues found during spec review against bolts#1295:
1. Fix missing_hashes ordering to match spec requirement:
"MUST include the minimal set of merkle hashes... in ascending type order"
For internal nodes (combined branches), the "type" for ordering is the
minimum TLV type covered by that subtree. Updated both encoding
(build_tree_with_disclosure) and decoding (reconstruct_merkle_root).
2. Fix parsing to reject payer proofs containing invreq_metadata (type 0)
which is prohibited per spec: "MUST NOT include invreq_metadata".
3. Fix payer signature to use proper BOLT 12 tagged hash mechanism:
- Add PAYER_SIGNATURE_TAG constant
- Update compute_payer_signature_message to compute:
inner_msg = SHA256(note || merkle_root)
final = SHA256(tag_hash || tag_hash || inner_msg)
This matches the spec's [Signature Calculation] reference.
This commit adds security validations to payer proof parsing: 1. TLV ordering validation: Reject payer proofs with TLVs not in strictly ascending order per BOLT 12 requirements. Out-of-order TLVs would cause incorrect merkle tree reconstruction. 2. Duplicate TLV detection: Reject payer proofs with duplicate TLV types. Previously, duplicates would cause included_records and included_types to have inconsistent sizes. 3. Hash length validation: Reject missing_hashes and leaf_hashes with lengths not divisible by 32 bytes. Previously, invalid lengths were silently truncated. Adds 4 new unit tests for the validation logic.
|
👋 Hi! I see this is a draft PR. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4297 +/- ##
==========================================
- Coverage 89.38% 86.30% -3.08%
==========================================
Files 180 159 -21
Lines 139834 102780 -37054
Branches 139834 102780 -37054
==========================================
- Hits 124985 88707 -36278
+ Misses 12262 11641 -621
+ Partials 2587 2432 -155
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This is a first draft implementation of the payer proof extension to BOLT 12 as proposed in lightning/bolts#1295. The goal is to get early feedback on the API design before the spec is finalized.
Payer proofs allow proving that a BOLT 12 invoice was paid by demonstrating possession of:
This PR adds the core building blocks:
This is explicitly a PoC to validate the API surface - the spec itself is still being refined. Looking for feedback on:
cc @TheBlueMatt @jkczyz