From 9e1f00b945ba0c0823c497272a02219c552854a1 Mon Sep 17 00:00:00 2001 From: Lagrang3 Date: Thu, 19 Dec 2024 10:02:35 +0100 Subject: [PATCH 1/3] xpay-handle-pay: bugfix, handle null parameters Changelog-Fixed: xpay-handle-pay: handle null parameters passed in the "param" list. Reported-by: @hMsats Signed-off-by: Lagrang3 --- plugins/xpay/xpay.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/xpay/xpay.c b/plugins/xpay/xpay.c index e5fd9266f45d..3f0e3844bab2 100644 --- a/plugins/xpay/xpay.c +++ b/plugins/xpay/xpay.c @@ -1914,6 +1914,12 @@ static struct command_result *handle_rpc_command(struct command *cmd, bolt11 = params_tok + 1; if (params_tok->size == 2) amount_msat = json_next(bolt11); + + /* some arguments could have null values in the list */ + if (bolt11 && json_tok_is_null(buf, bolt11)) + bolt11 = NULL; + if (amount_msat && json_tok_is_null(buf, amount_msat)) + amount_msat = NULL; } else if (params_tok->type == JSMN_OBJECT) { const jsmntok_t *t, *maxfeepercent = NULL, *exemptfee = NULL; size_t i; From 684fc042d0a4b704b962170d6596641ebb4c1a4f Mon Sep 17 00:00:00 2001 From: Lagrang3 Date: Thu, 19 Dec 2024 11:12:07 +0100 Subject: [PATCH 2/3] xpay-handle-pay: don't assume bolt11 is non NULL Changelog-None: xpay-handle-pay: don't assume bolt11 param is non NULL Signed-off-by: Lagrang3 --- plugins/xpay/xpay.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/plugins/xpay/xpay.c b/plugins/xpay/xpay.c index 3f0e3844bab2..e318035bfc9f 100644 --- a/plugins/xpay/xpay.c +++ b/plugins/xpay/xpay.c @@ -1888,6 +1888,9 @@ static struct command_result *handle_rpc_command(struct command *cmd, const char *maxfee = NULL; struct json_stream *response; + /* pay extra params */ + const jsmntok_t *maxfeepercent = NULL, *exemptfee = NULL; + if (!xpay->take_over_pay) goto dont_redirect; @@ -1921,7 +1924,7 @@ static struct command_result *handle_rpc_command(struct command *cmd, if (amount_msat && json_tok_is_null(buf, amount_msat)) amount_msat = NULL; } else if (params_tok->type == JSMN_OBJECT) { - const jsmntok_t *t, *maxfeepercent = NULL, *exemptfee = NULL; + const jsmntok_t *t; size_t i; json_for_each_obj(i, t, params_tok) { @@ -1947,25 +1950,25 @@ static struct command_result *handle_rpc_command(struct command *cmd, goto dont_redirect; } } - if (!bolt11) { - plugin_log(cmd->plugin, LOG_INFORM, - "Not redirecting pay (missing bolt11 parameter)"); - goto dont_redirect; - } - /* If this returns NULL, we let pay handle the weird case */ - if (!calc_maxfee(cmd, &maxfee, buf, - bolt11, amount_msat, - exemptfee, maxfeepercent)) { - plugin_log(cmd->plugin, LOG_INFORM, - "Not redirecting pay (weird maxfee params)"); - goto dont_redirect; - } } else { plugin_log(cmd->plugin, LOG_INFORM, "Not redirecting pay (unexpected params type)"); goto dont_redirect; } + if (!bolt11) { + plugin_log(cmd->plugin, LOG_INFORM, + "Not redirecting pay (missing bolt11 parameter)"); + goto dont_redirect; + } + /* If this returns NULL, we let pay handle the weird case */ + if (!calc_maxfee(cmd, &maxfee, buf, bolt11, amount_msat, exemptfee, + maxfeepercent)) { + plugin_log(cmd->plugin, LOG_INFORM, + "Not redirecting pay (weird maxfee params)"); + goto dont_redirect; + } + plugin_log(cmd->plugin, LOG_INFORM, "Redirecting pay->xpay"); response = jsonrpc_stream_success(cmd); json_object_start(response, "replace"); From 4470fa3d4caf27536487dc09a3db84cae6577395 Mon Sep 17 00:00:00 2001 From: Lagrang3 Date: Thu, 19 Dec 2024 12:03:26 +0100 Subject: [PATCH 3/3] xpay-handle-pay: test null params Changelog-None: xpay-handle-pay: test null params in json array. Signed-off-by: Lagrang3 --- tests/test_xpay.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/test_xpay.py b/tests/test_xpay.py index 3730dd256fcb..63dfe4682882 100644 --- a/tests/test_xpay.py +++ b/tests/test_xpay.py @@ -485,6 +485,29 @@ def test_xpay_takeover(node_factory, executor): l1.daemon.wait_for_log('Converted maxfeepercent=0.25, exemptfee=UNSET to maxfee 5000msat') +def test_xpay_takeover_null_parms(node_factory, executor): + """Test passing through RPC a list of parameters some of which have null + json value.""" + l1, l2, l3 = node_factory.line_graph( + 3, wait_for_announce=True, opts={"xpay-handle-pay": True} + ) + + # Amount argument is null. + inv = l3.rpc.invoice(100000, "test_xpay_takeover1", "test_xpay_takeover1")["bolt11"] + l1.rpc.call("pay", [inv, None]) + l1.daemon.wait_for_log("Redirecting pay->xpay") + + # Amount argument is given + inv = l3.rpc.invoice("any", "test_xpay_takeover2", "test_xpay_takeover2")["bolt11"] + l1.rpc.call("pay", [inv, "100sat"]) + l1.daemon.wait_for_log("Redirecting pay->xpay") + + # bolt11 invoice cannot be NULL + with pytest.raises(RpcError, match=r"missing required parameter: bolt11"): + l1.rpc.call("pay", [None, "100sat"]) + l1.daemon.wait_for_log(r"Not redirecting pay \(missing bolt11 parameter\)") + + def test_xpay_preapprove(node_factory): l1, l2 = node_factory.line_graph(2, opts={'dev-hsmd-fail-preapprove': None})