common: fix up test vectors' invoice_merkle_root.
What changed, and why it matters
This change fixes a test-vector generator used only in Core Lightning's own test suite. The generator was accidentally printing the invoice merkle root twice and labeling the second copy as the 'proof merkle root.' The fix computes and prints the actual proof merkle root. This is a test-data bug, not a bug in live payment code, so it does not directly endanger user funds or node security.
No urgent action required for operators. Merge the fix so that generated BOLT12 proof test vectors are correct and downstream implementers do not rely on invalid vectors. Review any vectors generated from the buggy revision and regenerate them if they were published.
Security signals we found
Test-only vector generator bug
Incorrect merkle root printed in generated test vectors
No change to production signing/verification logic
Reported by external contributor (@t-bast)
Evidence from the diff
In common/test/run-bolt12_proof_vectors.c, generate_valid_vector() now computes bolt12_payer_proof_merkle(proof, &pproot) and prints that value for the JSON key ‘proof_merkle_root’ instead of reusing the invoice merkle root variable (&mroot). It also moves tlv_update_fields() to occur before the proof merkle root is calculated so the proof_signature field is included in the TLV field list. The file is a test runner that produces BOLT12 proof test vectors; it is not part of the production signing or verification path.
Changed components
common/test/run-bolt12_proof_vectors.cInspect captured patch +6 / −5
diff --git a/common/test/run-bolt12_proof_vectors.c b/common/test/run-bolt12_proof_vectors.c
index ce535200..e8a1e129 100644
--- a/common/test/run-bolt12_proof_vectors.c
+++ b/common/test/run-bolt12_proof_vectors.c
@@ -160,7 +160,7 @@ static void generate_valid_vector(const char *name,
bool (*include_field)(const struct tlv_field *, void *),
bool explicit_empty_omitted)
{
- struct sha256 mroot, shash;
+ struct sha256 mroot, pproot, shash;
struct tlv_payer_proof *proof;
secp256k1_keypair kp = keypair_for_letter(payer_letter);
u8 *invoice_wire;
@@ -179,6 +179,10 @@ static void generate_valid_vector(const char *name,
}
proof->proof_signature = payer_proof_signature(proof, proof, sign_payer, &kp);
assert(proof->proof_signature);
+ /* Refresh fields to include proof_signature */
+ tlv_update_fields(proof, tlv_payer_proof, &proof->fields);
+
+ bolt12_payer_proof_merkle(proof, &pproot);
printf("{\n");
printf("\"name\":\"%s\",\n", name);
@@ -201,7 +205,7 @@ static void generate_valid_vector(const char *name,
printf("\"invoice_sighash\":\"%s\",\n", fmt_sha256(tmpctx, &shash));
printf("\"invoice_signature\":\"%s\",\n",
tal_hexstr(tmpctx, inv->signature->u8, sizeof(inv->signature->u8)));
- printf("\"proof_merkle_root\":\"%s\",\n", fmt_sha256(tmpctx, &mroot));
+ printf("\"proof_merkle_root\":\"%s\",\n", fmt_sha256(tmpctx, &pproot));
printf("\"proof_leaf_hashes\":[\n");
print_hashes_json(proof->proof_leaf_hashes, tal_count(proof->proof_leaf_hashes));
printf("],\n");
@@ -213,9 +217,6 @@ static void generate_valid_vector(const char *name,
printf("]\n");
printf("},\n");
- /* Refresh fields to include proof_signature */
- tlv_update_fields(proof, tlv_payer_proof, &proof->fields);
-
printf("\"result\":{\n");
printf("\"payer_sig\":\"%s\",\n",
fmt_bip340sig(tmpctx, proof->proof_signature));
Why this scored 18/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.