mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
paymod: Add a simple test-command to test the paymod state-machine
This commit can be reverted/skipped once we have implemented all the logic and have feature parity with the normal `pay`. It's main purpose is to expose the unfinished functionality to test it, without completely breaking the existing `pay` command.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include <plugins/libplugin-pay.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct payment *payment_new(tal_t *ctx, struct command *cmd,
|
||||
struct payment *parent,
|
||||
@@ -144,3 +145,19 @@ void payment_continue(struct payment *p)
|
||||
* `payment_continue` after the final state. */
|
||||
abort();
|
||||
}
|
||||
|
||||
static inline struct dummy_data *
|
||||
dummy_data_init(struct payment *p)
|
||||
{
|
||||
return tal(p, struct dummy_data);
|
||||
}
|
||||
|
||||
static inline void dummy_step_cb(struct dummy_data *dd,
|
||||
struct payment *p)
|
||||
{
|
||||
fprintf(stderr, "dummy_step_cb called for payment %p at step %d\n", p, p->step);
|
||||
payment_continue(p);
|
||||
}
|
||||
|
||||
REGISTER_PAYMENT_MODIFIER(dummy, struct dummy_data *, dummy_data_init,
|
||||
dummy_step_cb);
|
||||
|
||||
@@ -129,6 +129,10 @@ struct payment_modifier {
|
||||
void (*)(data_type, struct payment *), step_cb), \
|
||||
};
|
||||
|
||||
struct dummy_data {
|
||||
unsigned int *dummy_param;
|
||||
};
|
||||
|
||||
/* List of globally available payment modifiers. */
|
||||
extern struct payment_modifier dummy_pay_mod;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <common/pseudorand.h>
|
||||
#include <common/type_to_string.h>
|
||||
#include <inttypes.h>
|
||||
#include <plugins/libplugin-pay.h>
|
||||
#include <plugins/libplugin.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -1702,6 +1703,70 @@ static void init(struct plugin *p,
|
||||
maxdelay_default = atoi(field);
|
||||
}
|
||||
|
||||
#if DEVELOPER
|
||||
struct payment_modifier *paymod_mods[2] = {
|
||||
&dummy_pay_mod,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct command_result *json_paymod(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
struct payment *p;
|
||||
const char *b11str;
|
||||
struct bolt11 *b11;
|
||||
char *fail;
|
||||
struct dummy_data *ddata;
|
||||
p = payment_new(cmd, cmd, NULL /* No parent */, paymod_mods);
|
||||
|
||||
ddata = (struct dummy_data*)p->modifier_data[0];
|
||||
|
||||
/* If any of the modifiers need to add params to the JSON-RPC call we
|
||||
* would add them to the `param()` call below, and have them be
|
||||
* initialized directly that way. */
|
||||
if (!param(cmd, buf, params, p_req("bolt11", param_string, &b11str),
|
||||
p_opt_def("dummy", param_number, &ddata->dummy_param, 42),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
b11 = bolt11_decode(cmd, b11str, plugin_feature_set(cmd->plugin),
|
||||
NULL, &fail);
|
||||
if (!b11)
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"Invalid bolt11: %s", fail);
|
||||
|
||||
if (!b11->chain)
|
||||
return command_fail(cmd, PAY_ROUTE_NOT_FOUND, "Invoice is for an unknown network");
|
||||
|
||||
if (b11->chain != chainparams)
|
||||
return command_fail(cmd, PAY_ROUTE_NOT_FOUND, "Invoice is for another network %s", b11->chain->network_name);
|
||||
|
||||
if (time_now().ts.tv_sec > b11->timestamp + b11->expiry)
|
||||
return command_fail(cmd, PAY_INVOICE_EXPIRED, "Invoice expired");
|
||||
|
||||
if (b11->msat)
|
||||
p->amount = *b11->msat;
|
||||
else
|
||||
abort();
|
||||
|
||||
/* Sanity check */
|
||||
if (feature_offered(b11->features, OPT_VAR_ONION)
|
||||
&& !b11->payment_secret)
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"Invalid bolt11:"
|
||||
" sets feature var_onion with no secret");
|
||||
|
||||
p->json_buffer = tal_steal(p, buf);
|
||||
p->json_toks = params;
|
||||
p->destination = p->getroute_destination = &b11->receiver_id;
|
||||
p->payment_hash = tal_dup(p, struct sha256, &b11->payment_hash);
|
||||
payment_start(p);
|
||||
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct plugin_command commands[] = { {
|
||||
"pay",
|
||||
"payment",
|
||||
@@ -1720,7 +1785,16 @@ static const struct plugin_command commands[] = { {
|
||||
"List result of payment {bolt11}, or all",
|
||||
"Covers old payments (failed and succeeded) and current ones.",
|
||||
json_listpays
|
||||
}
|
||||
},
|
||||
#if DEVELOPER
|
||||
{
|
||||
"paymod",
|
||||
"payment",
|
||||
"Send payment specified by {bolt11}",
|
||||
"Experimental implementation of pay using modifiers",
|
||||
json_paymod
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
||||
@@ -3043,3 +3043,17 @@ def test_invalid_onion_channel_update(node_factory):
|
||||
|
||||
# l1 should still be alive afterwards.
|
||||
assert l1.rpc.getinfo()['id'] == l1id
|
||||
|
||||
|
||||
@unittest.skipIf(not DEVELOPER, "paymod is only available to developers for now.")
|
||||
def test_pay_modifiers(node_factory):
|
||||
l1, l2 = node_factory.line_graph(2, opts=[{}, {}])
|
||||
|
||||
# Make sure that the dummy param is in the help (and therefore assigned to
|
||||
# the modifier data).
|
||||
hlp = l1.rpc.help("paymod")['help'][0]
|
||||
assert(hlp['command'] == 'paymod bolt11 [dummy]')
|
||||
|
||||
inv = l2.rpc.invoice(123, 'lbl', 'desc')['bolt11']
|
||||
with pytest.raises(RpcError, match="Not functional yet"):
|
||||
l1.rpc.paymod(inv)
|
||||
|
||||
Reference in New Issue
Block a user