From 42277a7ad405d413a886a491013a87d6864f48ba Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 7 Nov 2019 23:14:47 +0100 Subject: [PATCH] json-rpc: Add the `sendonion` RPC command --- lightningd/pay.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/lightningd/pay.c b/lightningd/pay.c index 079c7feed..de093d6ae 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -829,7 +829,7 @@ send_payment(struct lightningd *ld, return NULL; } -UNNEEDED static struct command_result * +static struct command_result * param_route_hop(struct command *cmd, const char *name, const char *buffer, const jsmntok_t *tok, struct route_hop **hop) { @@ -905,6 +905,96 @@ param_route_hop(struct command *cmd, const char *name, const char *buffer, return NULL; } +static struct command_result *json_sendonion(struct command *cmd, + const char *buffer, + const jsmntok_t *obj UNNEEDED, + const jsmntok_t *params) +{ + u8 *onion; + struct onionpacket *packet; + enum onion_type failcode; + struct htlc_out *hout; + struct route_hop *first_hop; + struct sha256 *payment_hash; + struct channel *channel; + struct lightningd *ld = cmd->ld; + struct wallet_payment *payment; + const char *label; + + if (!param(cmd, buffer, params, + p_req("onion", param_bin_from_hex, &onion), + p_req("first_hop", param_route_hop, &first_hop), + p_req("payment_hash", param_sha256, &payment_hash), + p_opt("label", param_escaped_string, &label), + NULL)) + return command_param_failed(); + + packet = parse_onionpacket(cmd, onion, tal_bytelen(onion), &failcode); + + if (!packet) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Could not parse the onion. Parsing failed " + "with failcode=%d", + failcode); + + /* FIXME if the user specified a short_channel_id, but no peer nodeid, + * we need to resolve that first. */ + + channel = active_channel_by_id(ld, &first_hop->nodeid, NULL); + if (!channel) { + struct json_stream *data + = json_stream_fail(cmd, PAY_TRY_OTHER_ROUTE, + "No connection to first " + "peer found"); + + json_add_routefail_info(data, 0, WIRE_UNKNOWN_NEXT_PEER, + &ld->id, &first_hop->channel_id, + node_id_idx(&ld->id, &first_hop->nodeid), + NULL); + json_object_end(data); + return command_failed(cmd, data); + } + + failcode = send_onion(cmd->ld, packet, first_hop, payment_hash, channel, + &hout); + + payment = tal(hout, struct wallet_payment); + payment->id = 0; + payment->payment_hash = *payment_hash; + payment->status = PAYMENT_PENDING; + payment->msatoshi = AMOUNT_MSAT(0); + payment->msatoshi_sent = first_hop->amount; + payment->timestamp = time_now().ts.tv_sec; + + /* These are not available for sendonion payments since the onion is + * opaque and we can't extract them. Errors have to be handled + * externally, since we can't decrypt them.*/ + payment->destination = NULL; + payment->payment_preimage = NULL; + payment->path_secrets = NULL; + payment->route_nodes = NULL; + payment->route_channels = NULL; + payment->bolt11 = NULL; + + if (label != NULL) + payment->label = tal_strdup(payment, label); + else + payment->label = NULL; + + /* We write this into db when HTLC is actually sent. */ + wallet_payment_setup(ld->wallet, payment); + + add_sendpay_waiter(ld, cmd, payment_hash); + return command_still_pending(cmd); +} +static const struct json_command sendonion_command = { + "sendonion", + "payment", + json_sendonion, + "Send a payment with a pre-computed onion." +}; +AUTODATA(json_command, &sendonion_command); + /*----------------------------------------------------------------------------- JSON-RPC sendpay interface -----------------------------------------------------------------------------*/