From 4a7cfe3e629dd526353b7668f903231b168be908 Mon Sep 17 00:00:00 2001 From: Wes Payne Date: Wed, 3 Sep 2025 17:25:23 -0700 Subject: [PATCH] keysend: enforce BOLT11 description length limit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The keysend plugin previously used `> 1023` as the cutoff for description length when inserting an invoice. This was inconsistent with invoice.c, which enforces the BOLT11 description field limit defined in `common/bolt11.h`. This patch switches to using `BOLT11_FIELD_BYTE_LIMIT` directly. As a result, keysend no longer fails on descriptions between 641–1023 bytes, which previously caused unexpected failures. A new regression test (`test_keysend_description_size_limit`) exercises boundary cases just below, at, and above the limit. Changelog-None Signed-off-by: Wes Payne --- plugins/keysend.c | 3 ++- tests/test_pay.py | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/plugins/keysend.c b/plugins/keysend.c index 6104bf607ccd..e9b6fb50bdcb 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -563,7 +564,7 @@ static struct command_result *htlc_accepted_call(struct command *cmd, (const char *)desc_field->value); json_add_string(req->js, "description", desc); /* Don't exceed max possible desc length! */ - if (strlen(desc) > 1023) + if (strlen(desc) >= BOLT11_FIELD_BYTE_LIMIT) json_add_bool(req->js, "deschashonly", true); } else { json_add_string(req->js, "description", "keysend"); diff --git a/tests/test_pay.py b/tests/test_pay.py index ab78f76a701a..72d5d20e2201 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -11,6 +11,7 @@ tu64_encode ) import copy +import json import os import pytest import random @@ -3697,6 +3698,30 @@ def test_keysend_maxfee(node_factory): assert len(l3.rpc.listinvoices()['invoices']) == 1 +@pytest.mark.parametrize("tlv_payload_length", [638, 639, 640, 641, 1022, 1023, 1024]) +def test_keysend_description_size_limit(node_factory, tlv_payload_length): + """ + Test keysend description handling near BOLT11 field size limits. + + Checks boundary conditions where the payload length is just below, + exactly at, and just above the maximum allowed tagged-field size. + + See common/bolt11.h: BOLT11_FIELD_BYTE_LIMIT. + """ + l1, l2 = node_factory.line_graph(2, wait_for_announce=True) + amt = 10000 + prefix = 'keysend: {"message": ""}' + base_len = len(prefix) + + # Prep TLV payload with test length + body_len = tlv_payload_length - base_len + tlv_payload = json.dumps({"message": "a" * body_len}).encode().hex() + + # Send keysend payment with test payload + l1.rpc.keysend(l2.info["id"], amt, extratlvs={7629169: tlv_payload}) + assert len(l2.rpc.listinvoices()["invoices"]) == 1 + + def test_invalid_onion_channel_update(node_factory): ''' Some onion failures "should" send a `channel_update`.