bolt12: add Merkle tree and BIP-340 message signatures - #11061
Open
bitromortac wants to merge 9 commits into
Open
bolt12: add Merkle tree and BIP-340 message signatures#11061bitromortac wants to merge 9 commits into
bitromortac wants to merge 9 commits into
Conversation
The bolt12 package can already encode and decode the TLV layer but has no way to carry an offer as a human-transportable string, which is the form the spec specifies for QR codes, URLs and email signatures. BOLT 12's envelope is subtractive relative to BIP-173: there is no BCH checksum, because the BIP-340 signature over the Merkle root already secures the payload, and a '+' continuation marker may split the string across lines. btcutil/bech32's public API always wraps the checksum, so the alphabet layer is duplicated here rather than reused. Enforce a whitelist of BOLT 12 prefixes (lno, lnr, lni) on both Encode and Decode.
Vendor the BOLT 12 offers-test.json fixtures so the offer decoder and validator are checked against the specification's own strings rather than hand-authored ones, which cannot drift from the spec without someone noticing. Invalid vectors are tested to verify they are rejected at some layer, and an aggregate stage census pins the distribution across bech32 decode, TLV decode, and validation.
The invoice_request codec has round-trip coverage against locally- constructed messages only, so a canonical-encoding bug would go unnoticed until a real peer rejected a signature. Drive the decoder from the spec's signature-test invoice_request and assert that re-encoding is byte-identical to the wire bytes, because the signature commits to the Merkle root of that exact encoding.
Add changes for the bech32 work in bolt12.
BOLT 12 signs the Merkle root of a tree built from the message's TLV records. MerkleRoot constructs the tree from a []tlv.Record by hashing each record into an LnLeaf and a uniqueness LnNonce, combining them into LnBranch nodes, and recursing to a single root. signableTLVs selects the records that enter the root, excluding the 240-1000 range the spec reserves for signature fields. The vendored signature-test.json vectors pin the construction byte-for-byte against the spec, down to every intermediate LnLeaf, LnNonce, and LnBranch digest.
SignMessage and VerifySignature wrap btcec's Schnorr API around the Merkle root with the spec's tagged-hash domain separator. Typed helpers bind the construction to invoice requests and invoices, so callers sign and verify messages rather than raw roots. The signed vectors in signature-test.json verify the construction against the spec, and a tamper matrix pins rejection of modified roots, signatures, keys, and tags.
ValidateInvoiceRequestRead and ValidateInvoiceRead now run VerifyInvoiceRequest and VerifyInvoice as their final step, so a decoded message whose BIP-340 signature does not verify against invreq_payer_id or invoice_node_id is rejected instead of only checked for presence. This satisfies the reader-side MUSTs of the BOLT 12 invoice_request and invoice requirements, and the docstrings now state the contract instead of deferring it to callers. The invoice_request wiring is pinned by the spec's signed vector; no signed invoice vector exists, so the invoice side is pinned by round-trip tests. Reader-validation fixtures now sign with Bob's key, and the happy-path invoice_request test reuses the shared validInvoiceRequest fixture.
Add changes for the Merkle tree and BIP-340 signature work in bolt12.
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #10736. Based on #11001.
Adds Merkle tree construction over TLV records (
MerkleRoot) and BIP-340 Schnorr message signatures (signMessage,verifySignature) for BOLT 12 invoice requests and invoices, and verifies the signature on read so a decoded message with an invalid signature is rejected.Additionally, this PR vendors upstream
lightning/boltssignature test vectors (signature-test.json) to pin Merkle construction and signature verification byte-for-byte against the spec.