Browse Source

param: Encapsulate hops parsing in a param_hops_array helper

Suggested-by: Rusty Russell <@rustyrussell>
Signed-off-by: Christian Decker <@cdecker>
travis-debug
Christian Decker 5 years ago
parent
commit
55d8dcc907
  1. 68
      common/json_tok.c
  2. 5
      common/json_tok.h
  3. 4
      common/test/run-param.c
  4. 56
      lightningd/pay.c

68
common/json_tok.c

@ -256,3 +256,71 @@ struct command_result *param_bin_from_hex(struct command *cmd, const char *name,
"'%s' should be a hex value, not '%.*s'",
name, tok->end - tok->start, buffer + tok->start);
}
struct command_result *param_hops_array(struct command *cmd, const char *name,
const char *buffer, const jsmntok_t *tok,
struct sphinx_hop **hops)
{
const jsmntok_t *hop, *payloadtok, *typetok, *pubkeytok;
struct sphinx_hop h;
size_t i;
if (tok->type != JSMN_ARRAY) {
return command_fail(
cmd, JSONRPC2_INVALID_PARAMS,
"'%s' should be an array of hops, got '%.*s'", name,
tok->end - tok->start, buffer + tok->start);
}
*hops = tal_arr(cmd, struct sphinx_hop, 0);
json_for_each_arr(i, hop, tok) {
payloadtok = json_get_member(buffer, hop, "payload");
typetok = json_get_member(buffer, hop, "type");
pubkeytok = json_get_member(buffer, hop, "pubkey");
if (!pubkeytok)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Hop %zu does not have a pubkey", i);
if (!payloadtok)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Hop %zu does not have a payload", i);
h.payload = json_tok_bin_from_hex(*hops, buffer, payloadtok);
if (!json_to_pubkey(buffer, pubkeytok, &h.pubkey))
return command_fail(
cmd, JSONRPC2_INVALID_PARAMS,
"'pubkey' should be a pubkey, not '%.*s'",
pubkeytok->end - pubkeytok->start,
buffer + pubkeytok->start);
if (!h.payload)
return command_fail(
cmd, JSONRPC2_INVALID_PARAMS,
"'payload' should be a hex encoded binary, not '%.*s'",
pubkeytok->end - pubkeytok->start,
buffer + pubkeytok->start);
if (!typetok || json_tok_streq(buffer, typetok, "tlv")) {
h.type = SPHINX_TLV_PAYLOAD;
} else if (json_tok_streq(buffer, typetok, "legacy")) {
h.type = SPHINX_V0_PAYLOAD;
} else {
return command_fail(
cmd, JSONRPC2_INVALID_PARAMS,
"Unknown payload type for hop %zu: '%.*s'", i,
pubkeytok->end - pubkeytok->start,
buffer + pubkeytok->start);
}
tal_arr_expand(hops, h);
}
if (tal_count(*hops) == 0) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"At least one hop must be specified.");
}
return NULL;
}

5
common/json_tok.h

@ -5,6 +5,7 @@
#include <ccan/short_types/short_types.h>
#include <common/json.h>
#include <common/node_id.h>
#include <common/sphinx.h>
#include <wire/wire.h>
struct amount_msat;
@ -121,4 +122,8 @@ struct command_result *param_bin_from_hex(struct command *cmd, const char *name,
const char *buffer, const jsmntok_t *tok,
u8 **bin);
struct command_result *param_hops_array(struct command *cmd, const char *name,
const char *buffer, const jsmntok_t *tok,
struct sphinx_hop **hops);
#endif /* LIGHTNING_COMMON_JSON_TOK_H */

4
common/test/run-param.c

@ -50,6 +50,10 @@ bool json_to_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEED
bool json_to_node_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct node_id *id UNNEEDED)
{ fprintf(stderr, "json_to_node_id called!\n"); abort(); }
/* Generated stub for json_to_pubkey */
bool json_to_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct pubkey *pubkey UNNEEDED)
{ fprintf(stderr, "json_to_pubkey called!\n"); abort(); }
/* AUTOGENERATED MOCKS END */
/* We do this lightningd-style: */

56
lightningd/pay.c

@ -1370,18 +1370,15 @@ static struct command_result *json_createonion(struct command *cmd,
const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
{
const jsmntok_t *hopstok, *hop, *payloadtok, *typetok, *pubkeytok;
enum sphinx_payload_type type;
size_t i, hop_count = 0;
struct json_stream *response;
struct pubkey pubkey;
struct secret *session_key, *shared_secrets;
struct sphinx_path *sp;
u8 *assocdata, *payload, *serialized;
u8 *assocdata, *serialized;
struct onionpacket *packet;
struct sphinx_hop *hops;
if (!param(cmd, buffer, params,
p_req("hops", param_array, &hopstok),
p_req("hops", param_hops_array, &hops),
p_req("assocdata", param_bin_from_hex, &assocdata),
p_opt("session_key", param_secret, &session_key),
NULL)) {
@ -1393,48 +1390,9 @@ static struct command_result *json_createonion(struct command *cmd,
else
sp = sphinx_path_new_with_key(cmd, assocdata, session_key);
json_for_each_arr(i, hop, hopstok) {
payloadtok = json_get_member(buffer, hop, "payload");
typetok = json_get_member(buffer, hop, "type");
pubkeytok = json_get_member(buffer, hop, "pubkey");
if (!pubkeytok)
return command_fail(cmd, JSONRPC2_INVALID_REQUEST,
"Hop %zu does not have a pubkey", i);
if (!payloadtok)
return command_fail(cmd, JSONRPC2_INVALID_REQUEST,
"Hop %zu does not have a payload", i);
payload = json_tok_bin_from_hex(cmd, buffer, payloadtok);
if (!json_to_pubkey(buffer, pubkeytok, &pubkey))
return command_fail(
cmd, JSONRPC2_INVALID_PARAMS,
"'pubkey' should be a pubkey, not '%.*s'",
pubkeytok->end - pubkeytok->start,
buffer + pubkeytok->start);
if (!payload)
return command_fail(
cmd, JSONRPC2_INVALID_PARAMS,
"'payload' should be a hex encoded binary, not '%.*s'",
pubkeytok->end - pubkeytok->start,
buffer + pubkeytok->start);
if (!typetok || !json_tok_streq(buffer, typetok, "legacy")) {
type = SPHINX_RAW_PAYLOAD;
} else {
type = SPHINX_V0_PAYLOAD;
}
sphinx_add_raw_hop(sp, &pubkey, type, payload);
hop_count++;
}
if (hop_count == 0)
return command_fail(cmd, JSONRPC2_INVALID_REQUEST,
"Cannot create an onion without hops.");
for (size_t i=0; i<tal_count(hops); i++)
sphinx_add_raw_hop(sp, &hops[i].pubkey, hops[i].type,
hops[i].payload);
packet = create_onionpacket(cmd, sp, &shared_secrets);
if (!packet)
@ -1446,7 +1404,7 @@ static struct command_result *json_createonion(struct command *cmd,
response = json_stream_success(cmd);
json_add_hex(response, "onion", serialized, tal_bytelen(serialized));
json_array_start(response, "shared_secrets");
for (size_t i=0; i<hop_count; i++) {
for (size_t i=0; i<tal_count(hops); i++) {
json_add_secret(response, NULL, &shared_secrets[i]);
}
json_array_end(response);

Loading…
Cancel
Save