common: don't use a dummy zero field for payer proofs.
What changed, and why it matters
This commit updates how payment proofs are digitally signed in Core Lightning. Previously, the code inserted a fake empty field (type 0, length 0) when computing the proof signature. The new code follows a simplified specification and signs the proof data directly without that dummy field. This is a standards-compliance/spec-simplification change rather than a fix for an active vulnerability.
Treat as a standards-alignment change. Verify that all BOLT12 payer proof implementations in the same network/ecosystem adopt the same simplified signing convention to avoid interoperability failures. Review whether any deployed proofs signed under the old dummy-TLV0 rule need migration or dual-verification support.
Security signals we found
Change to cryptographic signing/verification path for BOLT12 payer proofs
Removal of synthetic TLV0 field from Merkle root computation
Spec-simplification change affecting signature compatibility/interoperability
No explicit vulnerability or security bug described in commit message
Evidence from the diff
The change removes a custom TLV iterator (tlv0_adding_leaf_iter and next_field_prepend_tlv0) that prepended a synthetic TLV0 field to payer-proof fields before computing the Merkle root used in BOLT12 payer proofs. It replaces merkle_tlv_full() with merkle_tlv(proof->fields, merkle), and updates BOLT comments to remove the requirement for a first_tlv value of 0x0000. The signature verification path (check_payer_proof) is updated consistently. This aligns the implementation with a BOLT12 specification simplification proposed by @t-bast.
Changed components
common/bolt12_proof.cBOLT12 payer proof signature generation and verificationInspect captured patch +3 / −37
diff --git a/common/bolt12_proof.c b/common/bolt12_proof.c
index 6276a233..aec5fef8 100644
--- a/common/bolt12_proof.c
+++ b/common/bolt12_proof.c
@@ -166,46 +166,13 @@ struct tlv_payer_proof *make_unsigned_proof_(const tal_t *ctx,
return pptlv;
}
-struct tlv0_adding_leaf_iter {
- const struct tlv_field *fields;
- struct tlv_field tlv0;
- int n;
-};
-
-static const struct tlv_field *next_field_prepend_tlv0(bool *is_omitted,
- struct tlv0_adding_leaf_iter *iter)
-{
- *is_omitted = false;
- if (iter->n == -1) {
- iter->n = 0;
- return &iter->tlv0;
- }
- if (iter->n >= tal_count(iter->fields))
- return NULL;
- return &iter->fields[iter->n++];
-}
-
/* BOLT-payer_proof #12:
- * - MUST set `proof_signature` as detailed in [Signature Calculation](#signature-calculation) using the `invreq_payer_id` using the merkle-root as the `msg` and a `first_tlv` value of 0x0000 (i.e. type 0, length 0).
+ * - MUST set `proof_signature` as detailed in [Signature Calculation](#signature-calculation) using the `invreq_payer_id` using the merkle-root as the `msg`.
*/
void bolt12_payer_proof_merkle(const struct tlv_payer_proof *proof,
struct sha256 *merkle)
{
- struct tlv0_adding_leaf_iter iter;
-
- /* We use a modified iterator to insert tlv0. */
- iter.fields = proof->fields;
- iter.n = -1;
- iter.tlv0.meta = NULL;
- iter.tlv0.numtype = 0;
- iter.tlv0.length = 0;
- iter.tlv0.value = NULL;
-
- merkle_tlv_full(merkle,
- next_field_prepend_tlv0,
- bolt12_calc_nonce,
- NULL,
- &iter);
+ merkle_tlv(proof->fields, merkle);
}
struct bip340sig *payer_proof_signature_(const tal_t *ctx,
@@ -479,8 +446,7 @@ const char *check_payer_proof(const tal_t *ctx,
*...
* - `proof_signature` is not a valid signature using
* `invreq_payer_id` as described in [Signature
- * Calculation](#signature-calculation), using `msg` merkle-root and
- * a `first_tlv` value of 0x0000 (i.e. type 0, length 0).
+ * Calculation](#signature-calculation), using `msg` merkle-root.
*/
bolt12_payer_proof_merkle(pptlv, &merkle);
sighash_from_merkle("payer_proof", "proof_signature", &merkle, &shash);
Why this scored 29/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.