From 3b599b846ee28e97510b74c95a4d2365edc181b7 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Mon, 30 Nov 2020 15:04:24 +0100 Subject: [PATCH] keysend: Check that the destination supports keysend upon init We were blindly initiating the keysend payment, which could lead to confusing outcomes. This adds a very specific error message to the error returned. Changelog-Fixed: keysend: Keysend now checks whether the destination supports keysend before attempting a payment. If not a more informative error is returned. --- plugins/keysend.c | 19 +++++++++++++++++++ tests/test_pay.py | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/plugins/keysend.c b/plugins/keysend.c index 1dac75752..ed8f2a9ae 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,24 @@ static struct keysend_data *keysend_init(struct payment *p) static void keysend_cb(struct keysend_data *d, struct payment *p) { struct createonion_hop *last_payload; size_t hopcount; + struct gossmap_node *node; + bool enabled; + const struct gossmap *gossmap = get_gossmap(p->plugin); + + /* On the root payment we perform the featurebit check. */ + if (p->parent == NULL && p->step == PAYMENT_STEP_INITIALIZED) { + node = gossmap_find_node(gossmap, p->destination); + + enabled = gossmap_node_get_feature(gossmap, node, + KEYSEND_FEATUREBIT) != -1; + if (!enabled) + return payment_fail( + p, + "Recipient %s does not support keysend payments " + "(feature bit %d missing in node announcement)", + node_id_to_hexstr(tmpctx, p->destination), + KEYSEND_FEATUREBIT); + } if (p->step != PAYMENT_STEP_ONION_PAYLOAD) return payment_continue(p); diff --git a/tests/test_pay.py b/tests/test_pay.py index e5b20f2b1..84d1142c7 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -3373,7 +3373,7 @@ def test_listpay_result_with_paymod(node_factory, bitcoind): amount_sat = 10 ** 6 - l1, l2, l3 = node_factory.line_graph(3) + l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True) invl2 = l2.rpc.invoice(amount_sat * 2, "inv_l2", "inv_l2") l1.rpc.pay(invl2['bolt11'])