Skip to content

Clarify Mandatory Field Length Requirements and Add Note on Low R Signatures in BOLT 11 #1243

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 2 commits into
base: master
Choose a base branch
from

Conversation

nGoline
Copy link

@nGoline nGoline commented Apr 1, 2025

This PR addresses the ambiguity in BOLT 11 regarding the handling of mandatory fields (p, h, s) when their lengths are incorrect. Specifically, it clarifies that:

  • A reader MUST fail the invoice if a mandatory field (p, h, s) is present with an incorrect length, rather than skipping it. This ensures that invoices with invalid mandatory fields are not misinterpreted as valid.

Additionally, this PR adds a note to the examples section regarding the use of Low R signatures. While Low R signatures save 1 byte in DER-encoded signatures, they are not enforced in the specification. This clarification is added to help implementers avoid confusion when testing against provided vectors, as the test vectors do not enforce Low R.

Changes

  1. Updated the "Requirements" section to explicitly state that invoices must fail if mandatory fields have incorrect lengths.
  2. Added a note to the examples section explaining that Low R signatures are not enforced in the specification, even though they can save space.

Context

This PR resolves the ambiguity raised in #1235. The issue highlighted a potential misinterpretation where a p field with an invalid length could be skipped, leading to an invalid invoice being treated as valid. It also addresses confusion caused by test vectors not enforcing Low R signatures, which caused discrepancies during testing with libraries like NBitcoin.

Testing

  • Verified that the clarification aligns with the behavior of major implementations by running a Differential Fuzzing.
  • Updated documentation to ensure consistency with the clarified requirements.

Comment on lines 210 to 213
- MUST fail the payment if a mandatory field (`p` or `s`) was skipped due to an incorrect
length.
- MUST fail the payment if a `d` field is not present and a `h` field was skipped due to an
incorrect length.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a good reason to have this skipping behavior at all?

Can we just require exactly zero or one such fields, always with the correct length?

Copy link
Author

Choose a reason for hiding this comment

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

I agree it should be as straightforward as possible, but I didn't want to change the default expected behavior, so I added it to the existing spec.
It seems to me that most implementations are already enforcing what "it should have been" and not the spec line-by-line. Maybe we should open an issue to address a cleanup on the BOLT11 spec.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's worth cleaning this up from the spec, especially since some implementations already do the simpler thing.

I know @erickcestari has run into this inconsistency already with differential fuzzing. From that point of view, it would be nice to get all implementations doing the simple thing so ugly workarounds aren't needed for bitcoinfuzz.

Copy link
Collaborator

Choose a reason for hiding this comment

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

My 2 cents would be that this skipping was put in place in order to migrate to PTLCs using the same fields, where only the length would differ (e.g. SHA256 hashes would be replaced by public keys). But that doesn't really work because private keys cannot replace preimages that way because they have the same length!

Maybe @Roasbeef or @rustyrussell will be able to tell us why they initially introduced this flexibility. But I agree that if there's no compelling reason, we can harden it to simplify the spec.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This was clarified during yesterday's spec meeting: it was indeed an attempt at allowing future upgrades. But there is no clear path towards using that mechanism, so it can be removed. Instead of adding new requirements, this PR should rather remote all the existing requirements that say we must ignore existing fields having a different length than what's expected. @nGoline can you update the PR to reflect that? It will be a good clean-up of Bolt 11!

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