mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-21 14:24:09 +01:00
libplugin: use json_stream helpers for RPC calls
This adds helpers to start and send a jsonrpc request using json_stream in order to benefit from the helpers. This then simplifies existing plugins RPC requests by using json_stream helpers.
This commit is contained in:
parent
0546728819
commit
2bff80e3de
5 changed files with 226 additions and 281 deletions
|
@ -23,16 +23,13 @@ static struct command_result *ignore(struct command *timer,
|
|||
|
||||
static struct command_result *do_clean(struct plugin *p)
|
||||
{
|
||||
struct json_out *params = json_out_new(NULL);
|
||||
json_out_start(params, NULL, '{');
|
||||
json_out_add(params, "maxexpirytime", false, "%"PRIu64,
|
||||
time_now().ts.tv_sec - expired_by);
|
||||
json_out_end(params, '}');
|
||||
json_out_finished(params);
|
||||
|
||||
/* FIXME: delexpiredinvoice should be in our plugin too! */
|
||||
return send_outreq(p, NULL, "delexpiredinvoice", ignore, ignore, p,
|
||||
take(params));
|
||||
struct out_req *req = jsonrpc_request_start(p, NULL, "delexpiredinvoice",
|
||||
ignore, ignore, p);
|
||||
json_add_u64(req->js, "maxexpirytime",
|
||||
time_now().ts.tv_sec - expired_by);
|
||||
|
||||
return send_outreq(p, req);
|
||||
}
|
||||
|
||||
static struct command_result *json_autocleaninvoice(struct command *cmd,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <ccan/tal/str/str.h>
|
||||
#include <common/addr.h>
|
||||
#include <common/amount.h>
|
||||
#include <common/json_stream.h>
|
||||
#include <common/json_tok.h>
|
||||
#include <common/type_to_string.h>
|
||||
#include <common/utils.h>
|
||||
|
@ -50,32 +51,6 @@ static void json_out_add_raw_len(struct json_out *jout,
|
|||
memcpy(p, jsonstr, len);
|
||||
}
|
||||
|
||||
/* Helper to add a boolean to a json_out */
|
||||
static void json_out_addbool(struct json_out *jout,
|
||||
const char *fieldname,
|
||||
const bool val)
|
||||
{
|
||||
if (val)
|
||||
json_out_add(jout, fieldname, false, "true");
|
||||
else
|
||||
json_out_add(jout, fieldname, false, "false");
|
||||
}
|
||||
|
||||
/* Copy field and member to output, if it exists: return member */
|
||||
static const jsmntok_t *copy_member(struct json_out *ret,
|
||||
const char *buf, const jsmntok_t *obj,
|
||||
const char *membername)
|
||||
{
|
||||
const jsmntok_t *m = json_get_member(buf, obj, membername);
|
||||
if (!m)
|
||||
return NULL;
|
||||
|
||||
/* Literal copy: it's already JSON escaped, and may be a string. */
|
||||
json_out_add_raw_len(ret, membername,
|
||||
json_tok_full(buf, m), json_tok_full_len(m));
|
||||
return m;
|
||||
}
|
||||
|
||||
static struct command_result *send_prior(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *error,
|
||||
|
@ -89,23 +64,20 @@ static struct command_result *tx_abort(struct command *cmd,
|
|||
const jsmntok_t *error,
|
||||
struct funding_req *fr)
|
||||
{
|
||||
struct json_out *ret;
|
||||
struct out_req *req;
|
||||
|
||||
/* We stash the error so we can return it after we've cleaned up */
|
||||
fr->error = json_strdup(fr, buf, error);
|
||||
|
||||
ret = json_out_new(NULL);
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_addstr(ret, "txid",
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "txdiscard",
|
||||
send_prior, send_prior, fr);
|
||||
json_add_string(req->js, "txid",
|
||||
type_to_string(tmpctx, struct bitcoin_txid, &fr->tx_id));
|
||||
json_out_end(ret, '}');
|
||||
|
||||
/* We need to call txdiscard, and forward the actual cause for the
|
||||
* error after we've cleaned up. We swallow any errors returned by
|
||||
* this call, as we don't really care if it succeeds or not */
|
||||
return send_outreq(cmd->plugin, cmd, "txdiscard",
|
||||
send_prior, send_prior,
|
||||
fr, take(ret));
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
/* We're basically done, we just need to format the output to match
|
||||
|
@ -135,7 +107,7 @@ static struct command_result *send_tx(struct command *cmd,
|
|||
struct funding_req *fr)
|
||||
{
|
||||
|
||||
struct json_out *ret;
|
||||
struct out_req *req;
|
||||
const jsmntok_t *tok;
|
||||
bool commitments_secured;
|
||||
|
||||
|
@ -149,15 +121,12 @@ static struct command_result *send_tx(struct command *cmd,
|
|||
tok = json_get_member(buf, result, "channel_id");
|
||||
fr->chanstr = json_strdup(fr, buf, tok);
|
||||
|
||||
ret = json_out_new(NULL);
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_addstr(ret, "txid",
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "txsend",
|
||||
finish, tx_abort, fr);
|
||||
json_add_string(req->js, "txid",
|
||||
type_to_string(tmpctx, struct bitcoin_txid, &fr->tx_id));
|
||||
json_out_end(ret, '}');
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "txsend",
|
||||
finish, tx_abort,
|
||||
fr, take(ret));
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
static struct command_result *tx_prepare_done(struct command *cmd,
|
||||
|
@ -167,7 +136,7 @@ static struct command_result *tx_prepare_done(struct command *cmd,
|
|||
{
|
||||
const jsmntok_t *txid_tok;
|
||||
const jsmntok_t *tx_tok;
|
||||
struct json_out *ret;
|
||||
struct out_req *req;
|
||||
const struct bitcoin_tx *tx;
|
||||
const char *hex;
|
||||
u32 outnum;
|
||||
|
@ -206,17 +175,14 @@ static struct command_result *tx_prepare_done(struct command *cmd,
|
|||
if (!bitcoin_txid_from_hex(hex, strlen(hex), &fr->tx_id))
|
||||
plugin_err(cmd->plugin, "Unable to parse txid %s", hex);
|
||||
|
||||
ret = json_out_new(NULL);
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_addstr(ret, "id", node_id_to_hexstr(tmpctx, fr->id));
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "fundchannel_complete",
|
||||
send_tx, tx_abort, fr);
|
||||
json_add_string(req->js, "id", node_id_to_hexstr(tmpctx, fr->id));
|
||||
/* Note that hex is reused from above */
|
||||
json_out_addstr(ret, "txid", hex);
|
||||
json_out_add(ret, "txout", false, "%u", outnum);
|
||||
json_out_end(ret, '}');
|
||||
json_add_string(req->js, "txid", hex);
|
||||
json_add_u32(req->js, "txout", outnum);
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "fundchannel_complete",
|
||||
send_tx, tx_abort,
|
||||
fr, take(ret));
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
static struct command_result *cancel_start(struct command *cmd,
|
||||
|
@ -224,59 +190,51 @@ static struct command_result *cancel_start(struct command *cmd,
|
|||
const jsmntok_t *error,
|
||||
struct funding_req *fr)
|
||||
{
|
||||
struct json_out *ret;
|
||||
struct out_req *req;
|
||||
|
||||
/* We stash the error so we can return it after we've cleaned up */
|
||||
fr->error = json_strdup(fr, buf, error);
|
||||
|
||||
ret = json_out_new(NULL);
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_addstr(ret, "id", node_id_to_hexstr(tmpctx, fr->id));
|
||||
json_out_end(ret, '}');
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "fundchannel_cancel",
|
||||
send_prior, send_prior, fr);
|
||||
json_add_string(req->js, "id", node_id_to_hexstr(tmpctx, fr->id));
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "fundchannel_cancel",
|
||||
send_prior, send_prior,
|
||||
fr, take(ret));
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
static struct json_out *txprepare(struct command *cmd,
|
||||
struct funding_req *fr,
|
||||
const char *destination)
|
||||
static void txprepare(struct json_stream *js,
|
||||
struct funding_req *fr,
|
||||
const char *destination)
|
||||
{
|
||||
struct json_out *ret;
|
||||
ret = json_out_new(NULL);
|
||||
json_out_start(ret, NULL, '{');
|
||||
|
||||
/* Add the 'outputs' */
|
||||
json_out_start(ret, "outputs", '[');
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_addstr(ret, destination, fr->funding_str);
|
||||
json_out_end(ret, '}');
|
||||
json_out_end(ret, ']');
|
||||
json_array_start(js, "outputs");
|
||||
json_object_start(js, NULL);
|
||||
json_add_string(js, destination, fr->funding_str);
|
||||
json_object_end(js);
|
||||
json_array_end(js);
|
||||
|
||||
if (fr->feerate_str)
|
||||
json_out_addstr(ret, "feerate", fr->feerate_str);
|
||||
json_add_string(js, "feerate", fr->feerate_str);
|
||||
if (fr->minconf)
|
||||
json_out_add(ret, "minconf", false, "%u", *fr->minconf);
|
||||
json_add_u32(js, "minconf", *fr->minconf);
|
||||
if (fr->utxo_str)
|
||||
json_out_add_raw_len(ret, "utxos", fr->utxo_str, strlen(fr->utxo_str));
|
||||
json_out_end(ret, '}');
|
||||
|
||||
return ret;
|
||||
json_out_add_raw_len(js->jout, "utxos", fr->utxo_str,
|
||||
strlen(fr->utxo_str));
|
||||
}
|
||||
|
||||
static struct command_result *prepare_actual(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
struct funding_req *fr)
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
struct funding_req *fr)
|
||||
{
|
||||
struct json_out *ret;
|
||||
struct out_req *req;
|
||||
|
||||
ret = txprepare(cmd, fr, fr->funding_addr);
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "txprepare",
|
||||
tx_prepare_done, cancel_start,
|
||||
fr);
|
||||
txprepare(req->js, fr, fr->funding_addr);
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "txprepare",
|
||||
tx_prepare_done, cancel_start,
|
||||
fr, take(ret));
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
static struct command_result *fundchannel_start_done(struct command *cmd,
|
||||
|
@ -284,7 +242,7 @@ static struct command_result *fundchannel_start_done(struct command *cmd,
|
|||
const jsmntok_t *result,
|
||||
struct funding_req *fr)
|
||||
{
|
||||
struct json_out *ret;
|
||||
struct out_req *req;
|
||||
|
||||
/* Save the outscript so we can fund the outnum later */
|
||||
fr->out_script = json_tok_bin_from_hex(fr, buf,
|
||||
|
@ -295,44 +253,39 @@ static struct command_result *fundchannel_start_done(struct command *cmd,
|
|||
json_get_member(buf, result, "funding_address"));
|
||||
|
||||
/* Now that we're ready to go, cancel the reserved tx */
|
||||
ret = json_out_new(NULL);
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_addstr(ret, "txid",
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "txdiscard",
|
||||
prepare_actual, cancel_start,
|
||||
fr);
|
||||
json_add_string(req->js, "txid",
|
||||
type_to_string(tmpctx, struct bitcoin_txid, &fr->tx_id));
|
||||
json_out_end(ret, '}');
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "txdiscard",
|
||||
prepare_actual, cancel_start,
|
||||
fr, take(ret));
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
static struct command_result *fundchannel_start(struct command *cmd,
|
||||
struct funding_req *fr)
|
||||
{
|
||||
struct json_out *ret = json_out_new(NULL);
|
||||
struct out_req *req = jsonrpc_request_start(cmd->plugin, cmd,
|
||||
"fundchannel_start",
|
||||
fundchannel_start_done,
|
||||
tx_abort, fr);
|
||||
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_addstr(ret, "id", node_id_to_hexstr(tmpctx, fr->id));
|
||||
json_add_string(req->js, "id", node_id_to_hexstr(tmpctx, fr->id));
|
||||
|
||||
if (deprecated_apis)
|
||||
json_out_addstr(ret, "satoshi", fr->funding_str);
|
||||
json_add_string(req->js, "satoshi", fr->funding_str);
|
||||
else
|
||||
json_out_addstr(ret, "amount", fr->funding_str);
|
||||
json_add_string(req->js, "amount", fr->funding_str);
|
||||
|
||||
if (fr->feerate_str)
|
||||
json_out_addstr(ret, "feerate", fr->feerate_str);
|
||||
json_add_string(req->js, "feerate", fr->feerate_str);
|
||||
if (fr->announce_channel)
|
||||
json_out_addbool(ret, "announce", *fr->announce_channel);
|
||||
json_add_bool(req->js, "announce", *fr->announce_channel);
|
||||
if (fr->push_msat)
|
||||
json_out_addstr(ret, "push_msat",
|
||||
json_add_string(req->js, "push_msat",
|
||||
type_to_string(tmpctx, struct amount_msat, fr->push_msat));
|
||||
|
||||
json_out_end(ret, '}');
|
||||
json_out_finished(ret);
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "fundchannel_start",
|
||||
fundchannel_start_done, tx_abort,
|
||||
fr, take(ret));
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
static struct command_result *post_dryrun(struct command *cmd,
|
||||
|
@ -391,31 +344,28 @@ static struct command_result *exec_dryrun(struct command *cmd,
|
|||
const jsmntok_t *result,
|
||||
struct funding_req *fr)
|
||||
{
|
||||
struct json_out *ret;
|
||||
struct out_req *req = jsonrpc_request_start(cmd->plugin, cmd, "txprepare",
|
||||
post_dryrun, forward_error,
|
||||
fr);
|
||||
|
||||
/* Now that we've tried connecting, we do a 'dry-run' of txprepare,
|
||||
* so we can get an accurate idea of the funding amount */
|
||||
ret = txprepare(cmd, fr, placeholder_funding_addr);
|
||||
txprepare(req->js, fr, placeholder_funding_addr);
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "txprepare",
|
||||
post_dryrun, forward_error,
|
||||
fr, take(ret));
|
||||
return send_outreq(cmd->plugin, req);
|
||||
|
||||
}
|
||||
|
||||
static struct command_result *connect_to_peer(struct command *cmd,
|
||||
struct funding_req *fr)
|
||||
{
|
||||
struct json_out *ret = json_out_new(NULL);
|
||||
struct out_req *req = jsonrpc_request_start(cmd->plugin, cmd, "connect",
|
||||
exec_dryrun, forward_error,
|
||||
fr);
|
||||
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_addstr(ret, "id", node_id_to_hexstr(tmpctx, fr->id));
|
||||
json_out_end(ret, '}');
|
||||
json_out_finished(ret);
|
||||
json_add_string(req->js, "id", node_id_to_hexstr(tmpctx, fr->id));
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "connect",
|
||||
exec_dryrun, forward_error,
|
||||
fr, take(ret));
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
/* We will use 'id' and 'amount' to build a output: {id: amount}.
|
||||
|
|
|
@ -28,24 +28,6 @@ struct plugin_timer {
|
|||
struct command_result *(*cb)(struct plugin *p);
|
||||
};
|
||||
|
||||
struct out_req {
|
||||
/* The unique id of this request. */
|
||||
u64 id;
|
||||
/* The command which is why we're calling this rpc. */
|
||||
struct command *cmd;
|
||||
/* The callback when we get a response. */
|
||||
struct command_result *(*cb)(struct command *command,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
void *arg);
|
||||
/* The callback when we get an error. */
|
||||
struct command_result *(*errcb)(struct command *command,
|
||||
const char *buf,
|
||||
const jsmntok_t *error,
|
||||
void *arg);
|
||||
void *arg;
|
||||
};
|
||||
|
||||
struct rpc_conn {
|
||||
int fd;
|
||||
MEMBUF(char) mb;
|
||||
|
@ -132,6 +114,39 @@ static void ld_rpc_send(struct plugin *plugin, struct json_stream *stream)
|
|||
|
||||
/* FIXME: Move lightningd/jsonrpc to common/ ? */
|
||||
|
||||
struct out_req *
|
||||
jsonrpc_request_start_(struct plugin *plugin, struct command *cmd,
|
||||
const char *method,
|
||||
struct command_result *(*cb)(struct command *command,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
void *arg),
|
||||
struct command_result *(*errcb)(struct command *command,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
void *arg),
|
||||
void *arg)
|
||||
{
|
||||
struct out_req *out;
|
||||
|
||||
out = tal(plugin, struct out_req);
|
||||
out->id = plugin->next_outreq_id++;
|
||||
out->cmd = cmd;
|
||||
out->cb = cb;
|
||||
out->errcb = errcb;
|
||||
out->arg = arg;
|
||||
uintmap_add(&plugin->out_reqs, out->id, out);
|
||||
|
||||
out->js = new_json_stream(NULL, cmd, NULL);
|
||||
json_object_start(out->js, NULL);
|
||||
json_add_string(out->js, "jsonrpc", "2.0");
|
||||
json_add_u64(out->js, "id", out->id);
|
||||
json_add_string(out->js, "method", method);
|
||||
json_object_start(out->js, "params");
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static void jsonrpc_finish_and_send(struct plugin *p, struct json_stream *js)
|
||||
{
|
||||
json_object_compat_end(js);
|
||||
|
@ -524,43 +539,14 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks)
|
|||
}
|
||||
|
||||
struct command_result *
|
||||
send_outreq_(struct plugin *plugin,
|
||||
struct command *cmd,
|
||||
const char *method,
|
||||
struct command_result *(*cb)(struct command *command,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
void *arg),
|
||||
struct command_result *(*errcb)(struct command *command,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
void *arg),
|
||||
void *arg,
|
||||
const struct json_out *params TAKES)
|
||||
send_outreq(struct plugin *plugin, const struct out_req *req)
|
||||
{
|
||||
struct json_stream *js;
|
||||
struct out_req *out;
|
||||
/* The "param" object. */
|
||||
json_object_end(req->js);
|
||||
json_object_compat_end(req->js);
|
||||
json_stream_close(req->js, req->cmd);
|
||||
|
||||
out = tal(plugin, struct out_req);
|
||||
out->id = plugin->next_outreq_id++;
|
||||
out->cmd = cmd;
|
||||
out->cb = cb;
|
||||
out->errcb = errcb;
|
||||
out->arg = arg;
|
||||
uintmap_add(&plugin->out_reqs, out->id, out);
|
||||
|
||||
js = new_json_stream(NULL, NULL, NULL);
|
||||
json_object_start(js, NULL);
|
||||
json_add_string(js, "jsonrpc", "2.0");
|
||||
json_add_u64(js, "id", out->id);
|
||||
json_add_string(js, "method", method);
|
||||
json_out_add_splice(js->jout, "params", params);
|
||||
json_object_compat_end(js);
|
||||
json_stream_close(js, NULL);
|
||||
ld_rpc_send(plugin, js);
|
||||
|
||||
if (taken(params))
|
||||
tal_free(params);
|
||||
ld_rpc_send(plugin, req->js);
|
||||
|
||||
return &pending;
|
||||
}
|
||||
|
@ -581,7 +567,7 @@ handle_getmanifest(struct command *getmanifest_cmd)
|
|||
}
|
||||
json_array_end(params);
|
||||
|
||||
json_object_start(params, "rpcmethods");
|
||||
json_array_start(params, "rpcmethods");
|
||||
for (size_t i = 0; i < p->num_commands; i++) {
|
||||
json_object_start(params, NULL);
|
||||
json_add_string(params, "name", p->commands[i].name);
|
||||
|
|
|
@ -27,6 +27,26 @@ enum plugin_restartability {
|
|||
PLUGIN_RESTARTABLE
|
||||
};
|
||||
|
||||
struct out_req {
|
||||
/* The unique id of this request. */
|
||||
u64 id;
|
||||
/* The command which is why we're calling this rpc. */
|
||||
struct command *cmd;
|
||||
/* The request stream. */
|
||||
struct json_stream *js;
|
||||
/* The callback when we get a response. */
|
||||
struct command_result *(*cb)(struct command *command,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
void *arg);
|
||||
/* The callback when we get an error. */
|
||||
struct command_result *(*errcb)(struct command *command,
|
||||
const char *buf,
|
||||
const jsmntok_t *error,
|
||||
void *arg);
|
||||
void *arg;
|
||||
};
|
||||
|
||||
struct command {
|
||||
u64 *id;
|
||||
const char *methodname;
|
||||
|
@ -70,6 +90,35 @@ struct plugin_hook {
|
|||
const jsmntok_t *params);
|
||||
};
|
||||
|
||||
/* Helper to create a JSONRPC2 request stream. Send it with `send_outreq`. */
|
||||
struct out_req *
|
||||
jsonrpc_request_start_(struct plugin *plugin, struct command *cmd,
|
||||
const char *method,
|
||||
struct command_result *(*cb)(struct command *command,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
void *arg),
|
||||
struct command_result *(*errcb)(struct command *command,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
void *arg),
|
||||
void *arg);
|
||||
|
||||
#define jsonrpc_request_start(plugin, cmd, method, cb, errcb, arg) \
|
||||
jsonrpc_request_start_((plugin), (cmd), (method), \
|
||||
typesafe_cb_preargs(struct command_result *, void *, \
|
||||
(cb), (arg), \
|
||||
struct command *command, \
|
||||
const char *buf, \
|
||||
const jsmntok_t *result), \
|
||||
typesafe_cb_preargs(struct command_result *, void *, \
|
||||
(errcb), (arg), \
|
||||
struct command *command, \
|
||||
const char *buf, \
|
||||
const jsmntok_t *result), \
|
||||
(arg))
|
||||
|
||||
|
||||
/* Helper to create a JSONRPC2 response stream with a "result" object. */
|
||||
struct json_stream *jsonrpc_stream_success(struct command *cmd);
|
||||
|
||||
|
@ -131,38 +180,9 @@ const char *rpc_delve(const tal_t *ctx,
|
|||
const struct json_out *params TAKES,
|
||||
const char *guide);
|
||||
|
||||
/* Async rpc request.
|
||||
* @cmd can be NULL if we're coming from a timer callback.
|
||||
* @params can be NULL, otherwise it's an array or object.
|
||||
*/
|
||||
/* Send an async rpc request to lightningd. */
|
||||
struct command_result *
|
||||
send_outreq_(struct plugin *plugin,
|
||||
struct command *cmd,
|
||||
const char *method,
|
||||
struct command_result *(*cb)(struct command *command,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
void *arg),
|
||||
struct command_result *(*errcb)(struct command *command,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
void *arg),
|
||||
void *arg,
|
||||
const struct json_out *params TAKES);
|
||||
|
||||
#define send_outreq(plugin, cmd, method, cb, errcb, arg, params) \
|
||||
send_outreq_((plugin), (cmd), (method), \
|
||||
typesafe_cb_preargs(struct command_result *, void *, \
|
||||
(cb), (arg), \
|
||||
struct command *command, \
|
||||
const char *buf, \
|
||||
const jsmntok_t *result), \
|
||||
typesafe_cb_preargs(struct command_result *, void *, \
|
||||
(errcb), (arg), \
|
||||
struct command *command, \
|
||||
const char *buf, \
|
||||
const jsmntok_t *result), \
|
||||
(arg), (params))
|
||||
send_outreq(struct plugin *plugin, const struct out_req *req);
|
||||
|
||||
/* Callback to just forward error and close request; @cmd cannot be NULL */
|
||||
struct command_result *forward_error(struct command *cmd,
|
||||
|
|
124
plugins/pay.c
124
plugins/pay.c
|
@ -10,6 +10,7 @@
|
|||
#include <common/errcode.h>
|
||||
#include <common/features.h>
|
||||
#include <common/gossip_constants.h>
|
||||
#include <common/json_stream.h>
|
||||
#include <common/pseudorand.h>
|
||||
#include <common/type_to_string.h>
|
||||
#include <plugins/libplugin.h>
|
||||
|
@ -197,14 +198,6 @@ static void attempt_failed_tok(struct pay_command *pc, const char *method,
|
|||
failed_end(failed);
|
||||
}
|
||||
|
||||
/* Helper to add a u32. */
|
||||
static void json_out_add_u32(struct json_out *jout,
|
||||
const char *fieldname,
|
||||
u32 val)
|
||||
{
|
||||
json_out_add(jout, fieldname, false, "%"PRIu32, val);
|
||||
}
|
||||
|
||||
/* Helper to add a u64. */
|
||||
static void json_out_add_u64(struct json_out *jout,
|
||||
const char *fieldname,
|
||||
|
@ -360,7 +353,7 @@ execute_waitblockheight(struct command *cmd,
|
|||
u32 blockheight,
|
||||
struct pay_command *pc)
|
||||
{
|
||||
struct json_out *params;
|
||||
struct out_req *req;
|
||||
struct timeabs now = time_now();
|
||||
struct timerel remaining;
|
||||
|
||||
|
@ -369,18 +362,14 @@ execute_waitblockheight(struct command *cmd,
|
|||
|
||||
remaining = time_between(pc->stoptime, now);
|
||||
|
||||
params = json_out_new(tmpctx);
|
||||
json_out_start(params, NULL, '{');
|
||||
json_out_add_u32(params, "blockheight", blockheight);
|
||||
json_out_add_u64(params, "timeout", time_to_sec(remaining));
|
||||
json_out_end(params, '}');
|
||||
json_out_finished(params);
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "waitblockheight",
|
||||
&waitblockheight_done,
|
||||
&waitblockheight_error,
|
||||
pc);
|
||||
json_add_u32(req->js, "blockheight", blockheight);
|
||||
json_add_u32(req->js, "timeout", time_to_sec(remaining));
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "waitblockheight",
|
||||
&waitblockheight_done,
|
||||
&waitblockheight_error,
|
||||
pc,
|
||||
params);
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
/* Gets the remote height from a
|
||||
|
@ -581,10 +570,13 @@ static struct command_result *sendpay_done(struct command *cmd,
|
|||
const jsmntok_t *result,
|
||||
struct pay_command *pc)
|
||||
{
|
||||
return send_outreq(cmd->plugin, cmd, "waitsendpay",
|
||||
waitsendpay_done, waitsendpay_error, pc,
|
||||
take(json_out_obj(NULL, "payment_hash",
|
||||
pc->payment_hash)));
|
||||
struct out_req *req = jsonrpc_request_start(cmd->plugin, cmd,
|
||||
"waitsendpay",
|
||||
waitsendpay_done,
|
||||
waitsendpay_error, pc);
|
||||
json_add_string(req->js, "payment_hash", pc->payment_hash);
|
||||
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
/* Calculate how many millisatoshi we need at the start of this route
|
||||
|
@ -737,7 +729,7 @@ static struct command_result *getroute_done(struct command *cmd,
|
|||
struct amount_msat fee;
|
||||
u32 delay;
|
||||
double feepercent;
|
||||
struct json_out *params;
|
||||
struct out_req *req;
|
||||
|
||||
if (!t)
|
||||
plugin_err(cmd->plugin, "getroute gave no 'route'? '%.*s'",
|
||||
|
@ -837,21 +829,17 @@ static struct command_result *getroute_done(struct command *cmd,
|
|||
}
|
||||
|
||||
attempt->sendpay = true;
|
||||
params = json_out_new(NULL);
|
||||
json_out_start(params, NULL, '{');
|
||||
json_out_add_raw(params, "route", attempt->route);
|
||||
json_out_add(params, "payment_hash", true, "%s", pc->payment_hash);
|
||||
json_out_add(params, "bolt11", true, "%s", pc->ps->bolt11);
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "sendpay",
|
||||
sendpay_done, sendpay_error, pc);
|
||||
json_out_add_raw(req->js->jout, "route", attempt->route);
|
||||
json_add_string(req->js, "payment_hash", pc->payment_hash);
|
||||
json_add_string(req->js, "bolt11", pc->ps->bolt11);
|
||||
if (pc->label)
|
||||
json_out_add(params, "label", true, "%s", pc->label);
|
||||
json_add_string(req->js, "label", pc->label);
|
||||
if (pc->payment_secret)
|
||||
json_out_add(params, "payment_secret", true, "%s",
|
||||
pc->payment_secret);
|
||||
json_out_end(params, '}');
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "sendpay", sendpay_done, sendpay_error, pc,
|
||||
take(params));
|
||||
json_add_string(req->js, "payment_secret", pc->payment_secret);
|
||||
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
static struct command_result *getroute_error(struct command *cmd,
|
||||
|
@ -896,7 +884,7 @@ static struct command_result *execute_getroute(struct command *cmd,
|
|||
struct amount_msat msat;
|
||||
const char *dest;
|
||||
u32 cltv;
|
||||
struct json_out *params;
|
||||
struct out_req *req;
|
||||
|
||||
/* routehint set below. */
|
||||
|
||||
|
@ -929,24 +917,22 @@ static struct command_result *execute_getroute(struct command *cmd,
|
|||
}
|
||||
|
||||
/* OK, ask for route to destination */
|
||||
params = json_out_new(NULL);
|
||||
json_out_start(params, NULL, '{');
|
||||
json_out_addstr(params, "id", dest);
|
||||
json_out_addstr(params, "msatoshi",
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "getroute",
|
||||
getroute_done, getroute_error, pc);
|
||||
json_add_string(req->js, "id", dest);
|
||||
json_add_string(req->js, "msatoshi",
|
||||
type_to_string(tmpctx, struct amount_msat, &msat));
|
||||
json_out_add_u32(params, "cltv", cltv);
|
||||
json_out_add_u32(params, "maxhops", max_hops);
|
||||
json_out_add(params, "riskfactor", false, "%f", pc->riskfactor);
|
||||
json_add_u32(req->js, "cltv", cltv);
|
||||
json_add_u32(req->js, "maxhops", max_hops);
|
||||
json_add_member(req->js, "riskfactor", false, "%f", pc->riskfactor);
|
||||
if (tal_count(pc->excludes) != 0) {
|
||||
json_out_start(params, "exclude", '[');
|
||||
json_array_start(req->js, "exclude");
|
||||
for (size_t i = 0; i < tal_count(pc->excludes); i++)
|
||||
json_out_addstr(params, NULL, pc->excludes[i]);
|
||||
json_out_end(params, ']');
|
||||
json_add_string(req->js, NULL, pc->excludes[i]);
|
||||
json_array_end(req->js);
|
||||
}
|
||||
json_out_end(params, '}');
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "getroute", getroute_done, getroute_error, pc,
|
||||
take(params));
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
|
@ -989,11 +975,11 @@ static struct command_result *
|
|||
execute_getstartblockheight(struct command *cmd,
|
||||
struct pay_command *pc)
|
||||
{
|
||||
return send_outreq(cmd->plugin, cmd, "getinfo",
|
||||
&getstartblockheight_done,
|
||||
&getstartblockheight_error,
|
||||
pc,
|
||||
take(json_out_obj(NULL, NULL, NULL)));
|
||||
struct out_req *req = jsonrpc_request_start(cmd->plugin, cmd, "getinfo",
|
||||
&getstartblockheight_done,
|
||||
&getstartblockheight_error,
|
||||
pc);
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
static struct command_result *start_pay_attempt(struct command *cmd,
|
||||
|
@ -1106,6 +1092,8 @@ static struct command_result *add_shadow_route(struct command *cmd,
|
|||
static struct command_result *shadow_route(struct command *cmd,
|
||||
struct pay_command *pc)
|
||||
{
|
||||
struct out_req *req;
|
||||
|
||||
#if DEVELOPER
|
||||
if (!pc->use_shadow)
|
||||
return start_pay_attempt(cmd, pc, "Initial attempt");
|
||||
|
@ -1113,9 +1101,9 @@ static struct command_result *shadow_route(struct command *cmd,
|
|||
if (pseudorand(2) == 0)
|
||||
return start_pay_attempt(cmd, pc, "Initial attempt");
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "listchannels",
|
||||
add_shadow_route, forward_error, pc,
|
||||
take(json_out_obj(NULL, "source", pc->shadow_dest)));
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "listchannels",
|
||||
add_shadow_route, forward_error, pc);
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
/* gossipd doesn't know much about the current state of channels; here we
|
||||
|
@ -1271,6 +1259,7 @@ static struct command_result *json_pay(struct command *cmd,
|
|||
double *maxfeepercent;
|
||||
unsigned int *maxdelay;
|
||||
struct amount_msat *exemptfee;
|
||||
struct out_req *req;
|
||||
#if DEVELOPER
|
||||
bool *use_shadow;
|
||||
#endif
|
||||
|
@ -1357,8 +1346,9 @@ static struct command_result *json_pay(struct command *cmd,
|
|||
#endif
|
||||
|
||||
/* Get capacities of local channels (no parameters) */
|
||||
return send_outreq(cmd->plugin, cmd, "listpeers", listpeers_done, forward_error, pc,
|
||||
take(json_out_obj(NULL, NULL, NULL)));
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "listpeers",
|
||||
listpeers_done, forward_error, pc);
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
/* FIXME: Add this to ccan/time? */
|
||||
|
@ -1663,6 +1653,7 @@ static struct command_result *json_listpays(struct command *cmd,
|
|||
const jsmntok_t *params)
|
||||
{
|
||||
const char *b11str;
|
||||
struct out_req *req;
|
||||
|
||||
/* FIXME: would be nice to parse as a bolt11 so check worked in future */
|
||||
if (!param(cmd, buf, params,
|
||||
|
@ -1670,11 +1661,12 @@ static struct command_result *json_listpays(struct command *cmd,
|
|||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
return send_outreq(cmd->plugin, cmd, "listsendpays",
|
||||
listsendpays_done, forward_error,
|
||||
cast_const(char *, b11str),
|
||||
/* Neatly returns empty object if b11str is NULL */
|
||||
take(json_out_obj(NULL, "bolt11", b11str)));
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "listsendpays",
|
||||
listsendpays_done, forward_error,
|
||||
cast_const(char *, b11str));
|
||||
if (b11str)
|
||||
json_add_string(req->js, "bolt11", b11str);
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
static void init(struct plugin *p,
|
||||
|
|
Loading…
Add table
Reference in a new issue