diff --git a/plugins/xpay/xpay.c b/plugins/xpay/xpay.c index e5fd9266f45d..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; @@ -1914,8 +1917,14 @@ 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; + const jsmntok_t *t; size_t i; json_for_each_obj(i, t, params_tok) { @@ -1941,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"); 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})