Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion plugins/keysend.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <ccan/asort/asort.h>
#include <ccan/cast/cast.h>
#include <ccan/tal/str/str.h>
#include <common/bolt11.h>
#include <common/gossmap.h>
#include <common/json_param.h>
#include <common/json_stream.h>
Expand Down Expand Up @@ -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)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be > or >=? lightningd/invoice.c uses >, however the BOLT11 spec says:

Note that the maximum length of a Tagged Field's data is constricted by the maximum value of data_length. This is 1023 x 5 bits, or 639 bytes.

In common/bolt11.c BOLT11_FIELD_BYTE_LIMIT has a value of 640.

Far from an expert here and appreciate any insight. Happy to update as needed.

json_add_bool(req->js, "deschashonly", true);
} else {
json_add_string(req->js, "description", "keysend");
Expand Down
25 changes: 25 additions & 0 deletions tests/test_pay.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
tu64_encode
)
import copy
import json
import os
import pytest
import random
Expand Down Expand Up @@ -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`.
Expand Down
Loading