diff --git a/plugins/keysend.c b/plugins/keysend.c index db5a57bb7..b95f93f24 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -244,13 +245,11 @@ static struct command_result *htlc_accepted_call(struct command *cmd, const char *buf, const jsmntok_t *params) { - const jsmntok_t *payloadt = json_delve(buf, params, ".onion.payload"); - const jsmntok_t *payment_hash_tok = json_delve(buf, params, ".htlc.payment_hash"); const u8 *rawpayload; + struct sha256 payment_hash; size_t max; struct tlv_tlv_payload *payload; struct tlv_field *preimage_field = NULL; - char *hexpreimage, *hexpaymenthash; bigsize_t s; bool unknown_even_type = false; struct tlv_field *field; @@ -258,10 +257,11 @@ static struct command_result *htlc_accepted_call(struct command *cmd, struct out_req *req; struct timeabs now = time_now(); - if (!payloadt) + if (!json_scan(buf, params, "{onion:{payload:%},htlc:{payment_hash:%}}", + JSON_SCAN_TAL(cmd, json_tok_bin_from_hex, &rawpayload), + JSON_SCAN(json_to_sha256, &payment_hash))) return htlc_accepted_continue(cmd, NULL); - rawpayload = json_tok_bin_from_hex(cmd, buf, payloadt); max = tal_bytelen(rawpayload); payload = tlv_tlv_payload_new(cmd); @@ -272,7 +272,8 @@ static struct command_result *htlc_accepted_call(struct command *cmd, if (!fromwire_tlv_payload(&rawpayload, &max, payload)) { plugin_log( cmd->plugin, LOG_UNUSUAL, "Malformed TLV payload %.*s", - payloadt->end - payloadt->start, buf + payloadt->start); + json_tok_full_len(params), + json_tok_full(buf, params)); return htlc_accepted_continue(cmd, NULL); } @@ -318,20 +319,18 @@ static struct command_result *htlc_accepted_call(struct command *cmd, ki->payload = tal_steal(ki, payload); ki->preimage_field = preimage_field; - hexpreimage = tal_hex(cmd, preimage_field->value); - /* If the preimage doesn't hash to the payment_hash we must continue, * maybe someone else knows how to handle these. */ sha256(&ki->payment_hash, preimage_field->value, preimage_field->length); - hexpaymenthash = tal_hexstr(cmd, &ki->payment_hash, sizeof(ki->payment_hash)); - if (!json_tok_streq(buf, payment_hash_tok, hexpaymenthash)) { + if (!sha256_eq(&ki->payment_hash, &payment_hash)) { plugin_log( cmd->plugin, LOG_UNUSUAL, "Preimage provided by the sender does not match the " - "payment_hash: SHA256(%s)=%s != %.*s. Ignoring keysend.", - hexpreimage, hexpaymenthash, - payment_hash_tok->end - payment_hash_tok->start, - buf + payment_hash_tok->start); + "payment_hash: SHA256(%s)=%s != %s. Ignoring keysend.", + tal_hexstr(tmpctx, + preimage_field->value, preimage_field->length), + type_to_string(tmpctx, struct sha256, &ki->payment_hash), + type_to_string(tmpctx, struct sha256, &payment_hash)); tal_free(ki); return htlc_accepted_continue(cmd, NULL); } @@ -348,7 +347,7 @@ static struct command_result *htlc_accepted_call(struct command *cmd, &htlc_accepted_invoice_created, ki); - plugin_log(cmd->plugin, LOG_INFORM, "Inserting a new invoice for keysend with payment_hash %s", hexpaymenthash); + plugin_log(cmd->plugin, LOG_INFORM, "Inserting a new invoice for keysend with payment_hash %s", type_to_string(tmpctx, struct sha256, &payment_hash)); json_add_string(req->js, "msatoshi", "any"); json_add_string(req->js, "label", ki->label); json_add_string(req->js, "description", "Spontaneous incoming payment through keysend"); diff --git a/plugins/libplugin.c b/plugins/libplugin.c index f82930bb5..814e088b1 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -802,34 +802,36 @@ static struct command_result *handle_init(struct command *cmd, const char *buf, const jsmntok_t *params) { - const jsmntok_t *configtok, *rpctok, *dirtok, *opttok, *nettok, *fsettok, - *t; + const jsmntok_t *configtok, *opttok, *t; struct sockaddr_un addr; size_t i; char *dir, *network; struct plugin *p = cmd->plugin; bool with_rpc = p->rpc_conn != NULL; - configtok = json_delve(buf, params, ".configuration"); + configtok = json_get_member(buf, params, "configuration"); + if (!json_scan(buf, configtok, + "{lightning-dir:%" + ",network:%" + ",feature_set:%" + ",rpc-file:%}", + JSON_SCAN_TAL(tmpctx, json_strdup, &dir), + JSON_SCAN_TAL(tmpctx, json_strdup, &network), + JSON_SCAN_TAL(p, json_to_feature_set, &p->our_features), + JSON_SCAN_TAL(p, json_strdup, &p->rpc_location))) + plugin_err(p, "cannot scan init params: %.*s", + json_tok_full_len(params), + json_tok_full(buf, params)); /* Move into lightning directory: other files are relative */ - dirtok = json_delve(buf, configtok, ".lightning-dir"); - dir = json_strdup(tmpctx, buf, dirtok); if (chdir(dir) != 0) plugin_err(p, "chdir to %s: %s", dir, strerror(errno)); - nettok = json_delve(buf, configtok, ".network"); - network = json_strdup(tmpctx, buf, nettok); chainparams = chainparams_for_network(network); - fsettok = json_delve(buf, configtok, ".feature_set"); - p->our_features = json_to_feature_set(p, buf, fsettok); - /* Only attempt to connect if the plugin has configured the rpc_conn * already, if that's not the case we were told to run without an RPC * connection, so don't even log an error. */ - rpctok = json_delve(buf, configtok, ".rpc-file"); - p->rpc_location = json_strdup(p, buf, rpctok); /* FIXME: Move this to its own function so we can initialize at a * later point in time. */ if (p->rpc_conn != NULL) { @@ -837,9 +839,7 @@ static struct command_result *handle_init(struct command *cmd, if (strlen(p->rpc_location) + 1 > sizeof(addr.sun_path)) plugin_err(p, "rpc filename '%s' too long", p->rpc_location); - memcpy(addr.sun_path, buf + rpctok->start, - rpctok->end - rpctok->start); - addr.sun_path[rpctok->end - rpctok->start] = '\0'; + strcpy(addr.sun_path, p->rpc_location); addr.sun_family = AF_UNIX; if (connect(p->rpc_conn->fd, (struct sockaddr *)&addr, diff --git a/plugins/pay.c b/plugins/pay.c index bc1004983..363f77703 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -394,20 +394,14 @@ execute_waitblockheight(struct command *cmd, static u32 get_remote_block_height(const char *buf, const jsmntok_t *error) { - const jsmntok_t *raw_message_tok; const u8 *raw_message; size_t raw_message_len; u16 type; /* Is there even a raw_message? */ - raw_message_tok = json_delve(buf, error, ".data.raw_message"); - if (!raw_message_tok) - return 0; - if (raw_message_tok->type != JSMN_STRING) - return 0; - - raw_message = json_tok_bin_from_hex(tmpctx, buf, raw_message_tok); - if (!raw_message) + if (!json_scan(buf, error, "{data:{raw_message:%}}", + JSON_SCAN_TAL(tmpctx, json_tok_bin_from_hex, + &raw_message))) return 0; /* BOLT #4: @@ -435,21 +429,19 @@ static struct command_result *waitsendpay_error(struct command *cmd, struct pay_command *pc) { struct pay_attempt *attempt = current_attempt(pc); - const jsmntok_t *codetok, *failcodetok, *nodeidtok, *scidtok, *dirtok; errcode_t code; int failcode; - bool node_err = false; attempt_failed_tok(pc, "waitsendpay", buf, error); - codetok = json_get_member(buf, error, "code"); - if (!json_to_errcode(buf, codetok, &code)) + if (!json_scan(buf, error, "{code:%}", + JSON_SCAN(json_to_errcode, &code))) plugin_err(cmd->plugin, "waitsendpay error gave no 'code'? '%.*s'", error->end - error->start, buf + error->start); if (code != PAY_UNPARSEABLE_ONION) { - failcodetok = json_delve(buf, error, ".data.failcode"); - if (!json_to_int(buf, failcodetok, &failcode)) + if (!json_scan(buf, error, "{data:{failcode:%}}", + JSON_SCAN(json_to_int, &failcode))) plugin_err(cmd->plugin, "waitsendpay error gave no 'failcode'? '%.*s'", error->end - error->start, buf + error->start); } @@ -512,57 +504,54 @@ static struct command_result *waitsendpay_error(struct command *cmd, return forward_error(cmd, buf, error, pc); } + if (time_after(time_now(), pc->stoptime)) { + return waitsendpay_expired(cmd, pc); + } + if (failcode & NODE) { - nodeidtok = json_delve(buf, error, ".data.erring_node"); - if (!nodeidtok) + struct node_id id; + const char *idstr; + + if (!json_scan(buf, error, "{data:{erring_node:%}}", + JSON_SCAN(json_to_node_id, &id))) plugin_err(cmd->plugin, "waitsendpay error no erring_node '%.*s'", error->end - error->start, buf + error->start); - node_err = true; - } else { - scidtok = json_delve(buf, error, ".data.erring_channel"); - if (!scidtok) - plugin_err(cmd->plugin, "waitsendpay error no erring_channel '%.*s'", - error->end - error->start, buf + error->start); - dirtok = json_delve(buf, error, ".data.erring_direction"); - if (!dirtok) - plugin_err(cmd->plugin, "waitsendpay error no erring_direction '%.*s'", - error->end - error->start, buf + error->start); - } - if (time_after(time_now(), pc->stoptime)) { - return waitsendpay_expired(cmd, pc); - } + /* FIXME: Keep as node_id, don't use strings. */ + idstr = node_id_to_hexstr(tmpctx, &id); - if (node_err) { /* If failure is in routehint part, try next one */ if (node_or_channel_in_routehint(pc->plugin, pc->current_routehint, - buf + nodeidtok->start, - nodeidtok->end - nodeidtok->start)) + idstr, strlen(idstr))) return next_routehint(cmd, pc); /* Otherwise, add erring channel to exclusion list. */ - tal_arr_expand(&pc->excludes, - tal_fmt(pc->excludes, "%.*s", - nodeidtok->end - nodeidtok->start, - buf + nodeidtok->start)); + tal_arr_expand(&pc->excludes, tal_steal(pc->excludes, idstr)); } else { + struct short_channel_id scid; + u32 dir; + const char *scidstr; + + if (!json_scan(buf, error, "{data:{erring_channel:%,erring_direction:%}}", + JSON_SCAN(json_to_short_channel_id, &scid), + JSON_SCAN(json_to_number, &dir))) + plugin_err(cmd->plugin, "waitsendpay error no erring_channel/direction '%.*s'", + error->end - error->start, buf + error->start); + + scidstr = short_channel_id_to_str(tmpctx, &scid); /* If failure is in routehint part, try next one */ if (node_or_channel_in_routehint(pc->plugin, pc->current_routehint, - buf + scidtok->start, - scidtok->end - scidtok->start)) + scidstr, strlen(scidstr))) return next_routehint(cmd, pc); /* Otherwise, add erring channel to exclusion list. */ tal_arr_expand(&pc->excludes, - tal_fmt(pc->excludes, "%.*s/%c", - scidtok->end - scidtok->start, - buf + scidtok->start, - buf[dirtok->start])); + tal_fmt(pc->excludes, "%s/%u", scidstr, dir)); } /* Try again. */ return start_pay_attempt(cmd, pc, "Excluded %s %s", - node_err ? "node" : "channel", + failcode & NODE ? "node" : "channel", pc->excludes[tal_count(pc->excludes)-1]); } @@ -765,16 +754,10 @@ static struct command_result *getroute_done(struct command *cmd, } else attempt->route = json_strdup(pc->ps->attempts, buf, t); - if (!json_to_msat(buf, json_delve(buf, t, "[0].msatoshi"), &fee)) - plugin_err(cmd->plugin, "getroute with invalid msatoshi? %.*s", - result->end - result->start, buf); - if (!amount_msat_sub(&fee, fee, pc->msat)) - plugin_err(cmd->plugin, "final amount %s less than paid %s", - type_to_string(tmpctx, struct amount_msat, &fee), - type_to_string(tmpctx, struct amount_msat, &pc->msat)); - - if (!json_to_number(buf, json_delve(buf, t, "[0].delay"), &delay)) - plugin_err(cmd->plugin, "getroute with invalid delay? %.*s", + if (!json_scan(buf, t, "[0:{msatoshi:%,delay:%}]", + JSON_SCAN(json_to_msat, &fee), + JSON_SCAN(json_to_number, &delay))) + plugin_err(cmd->plugin, "getroute with invalid msatoshi/delay? %.*s", result->end - result->start, buf); if (pc->maxfee_pct_millionths / 100 > UINT32_MAX) diff --git a/plugins/spender/openchannel.c b/plugins/spender/openchannel.c index 72884e3f2..a6f8c33bc 100644 --- a/plugins/spender/openchannel.c +++ b/plugins/spender/openchannel.c @@ -544,38 +544,17 @@ static void json_peer_sigs(struct command *cmd, const char *buf, const jsmntok_t *params) { - const jsmntok_t *cid_tok, *psbt_tok; struct channel_id cid; const struct wally_psbt *psbt; struct multifundchannel_destination *dest; - cid_tok = json_delve(buf, params, ".openchannel_peer_sigs.channel_id"); - if (!cid_tok) + if (!json_scan(buf, params, + "{openchannel_peer_sigs:" + "{channel_id:%,signed_psbt:%}}", + JSON_SCAN(json_to_channel_id, &cid), + JSON_SCAN_TAL(cmd, json_to_psbt, &psbt))) plugin_err(cmd->plugin, - "`openchannel_peer_sigs` notification did not " - "send 'channel_id'? %.*s", - json_tok_full_len(params), - json_tok_full(buf, params)); - if (!json_to_channel_id(buf, cid_tok, &cid)) - plugin_err(cmd->plugin, - "Unable to parse openchannel_peer_sigs.channel_id " - "%.*s", - json_tok_full_len(params), - json_tok_full(buf, params)); - - psbt_tok= json_delve(buf, params, ".openchannel_peer_sigs.signed_psbt"); - if (!psbt_tok) - plugin_err(cmd->plugin, - "`openchannel_peer_sigs` notification did not " - "include 'signed_psbt'? %.*s", - json_tok_full_len(params), - json_tok_full(buf, params)); - - psbt = json_to_psbt(cmd, buf, psbt_tok); - if (!psbt) - plugin_err(cmd->plugin, - "Unable to parse openchannel_peer_sigs.signed_psbt " - "%.*s", + "`openchannel_peer_sigs` did not scan", json_tok_full_len(params), json_tok_full(buf, params));