common: update BOLTs, reject "empty offer_chains" offers.
What changed, and why it matters
This commit tightens validation of a special kind of Lightning payment request called a BOLT12 offer. Previously, the software treated an offer that explicitly listed zero supported blockchains the same as one that didn't list any at all. The updated specification says such an empty list is invalid, so the code now rejects it. The commit message notes this is mostly a formality because the node couldn't actually pay these offers anyway, but it fixes a spec-compliance edge case and a test-vector mismatch.
Review whether any other BOLT12 fields that can be empty are being treated as missing, and ensure the new BOLT version is consistently applied across CI and release builds. No urgent security patch appears needed.
Security signals we found
Spec-compliance validation fix for BOLT12 offer parsing
Rejection of malformed offer_chains with zero entries
Correction of inverted chain-matching logic comment
Evidence from the diff
The change updates the pinned BOLT specification version and modifies bolt12.c so that an offer containing offer_chains as an empty array is rejected with the error ‘offer_chains with zero entries’. The comment and logic in bolt12_chains_match are also corrected: the spec now says the node must not respond if it does not accept invoices for at least one of the chains, rather than any of the chains. A test case is added to exercise the new rejection.
Changed components
common/bolt12.ccommon/test/run-bolt12-encode-test.cMakefile (BOLT version pin)Inspect captured patch +11 / −2
diff --git a/Makefile b/Makefile
index 5a5f6fee..8e12c6ae 100644
--- a/Makefile
+++ b/Makefile
@@ -33,7 +33,7 @@ CCANDIR := ccan
# Where we keep the BOLT RFCs
BOLTDIR := ../bolts/
-DEFAULT_BOLTVERSION := d98366c900e20eb5475be8dee0c58878dca1f967
+DEFAULT_BOLTVERSION := 34455ffe28b308dd7ac7552234d565890af8605b
# Can be overridden on cmdline.
BOLTVERSION := $(DEFAULT_BOLTVERSION)
diff --git a/common/bolt12.c b/common/bolt12.c
index 4621e62f..d4fcd005 100644
--- a/common/bolt12.c
+++ b/common/bolt12.c
@@ -28,7 +28,7 @@ bool bolt12_chains_match(const struct bitcoin_blkid *chains,
* - if the node does not accept bitcoin invoices:
* - MUST NOT respond to the offer
* - otherwise: (`offer_chains` is set):
- * - if the node does not accept invoices for any of the `chains`:
+ * - if the node does not accept invoices for at least one of the `chains`:
* - MUST NOT respond to the offer
*/
if (!chains) {
@@ -62,6 +62,10 @@ static char *check_features_and_chain(const tal_t *ctx,
if (must_be_chain) {
if (!bolt12_chains_match(chains, num_chains, must_be_chain))
return tal_fmt(ctx, "wrong chain");
+ } else {
+ /* Chains is *empty*, that can never work. */
+ if (chains && tal_count(chains) == 0)
+ return tal_fmt(ctx, "offer_chains with zero entries");
}
if (our_features) {
diff --git a/common/test/run-bolt12-encode-test.c b/common/test/run-bolt12-encode-test.c
index 911ce003..43f3e5e0 100644
--- a/common/test/run-bolt12-encode-test.c
+++ b/common/test/run-bolt12-encode-test.c
@@ -448,6 +448,11 @@ int main(int argc, char *argv[])
offer->offer_paths = paths;
offer->offer_paths[1]->path = NULL;
print_invalid_offer(offer, "Second offer_path is empty");
+ offer->offer_paths = NULL;
+
+ offer->offer_chains = tal_arr(offer, struct bitcoin_blkid, 0);
+ print_invalid_offer(offer, "offer_chains with zero entries");
+ offer->offer_chains = NULL;
printf("]\n");
common_shutdown();
Why this scored 23/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.