mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
plugin: Implement the ability to receive keysend payments
This still uses the experimental TLV-type, but once the type is standardized we can add detection for the new type quite easily. Changelog-Added: pay: The `keysend` plugin implements the ability to receive spontaneous payments (keysend)
This commit is contained in:
committed by
Rusty Russell
parent
5be59f4759
commit
ef0f28cd50
@@ -59,7 +59,7 @@ plugins/fundchannel: common/addr.o $(PLUGIN_FUNDCHANNEL_OBJS) $(PLUGIN_LIB_OBJS)
|
||||
|
||||
plugins/bcli: bitcoin/chainparams.o $(PLUGIN_BCLI_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS)
|
||||
|
||||
plugins/keysend: bitcoin/chainparams.o $(PLUGIN_KEYSEND_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS)
|
||||
plugins/keysend: bitcoin/chainparams.o wire/gen_onion_wire.o $(PLUGIN_KEYSEND_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS)
|
||||
|
||||
$(PLUGIN_PAY_OBJS) $(PLUGIN_AUTOCLEAN_OBJS) $(PLUGIN_FUNDCHANNEL_OBJS) $(PLUGIN_BCLI_OBJS) $(PLUGIN_LIB_OBJS): $(PLUGIN_LIB_HEADER)
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <plugins/libplugin.h>
|
||||
#include <wire/gen_onion_wire.h>
|
||||
|
||||
#define PREIMAGE_TLV_TYPE 5482373484
|
||||
|
||||
static void init(struct plugin *p, const char *buf UNUSED,
|
||||
const jsmntok_t *config UNUSED)
|
||||
@@ -9,10 +12,108 @@ static void init(struct plugin *p, const char *buf UNUSED,
|
||||
static const struct plugin_command commands[] = {
|
||||
};
|
||||
|
||||
static struct command_result *htlc_accepted_continue(struct command *cmd)
|
||||
{
|
||||
struct json_stream *response;
|
||||
response = jsonrpc_stream_success(cmd);
|
||||
json_add_string(response, "result", "continue");
|
||||
return command_finished(cmd, response);
|
||||
}
|
||||
|
||||
static struct command_result *htlc_accepted_resolve(struct command *cmd,
|
||||
char *hexpreimage)
|
||||
{
|
||||
struct json_stream *response;
|
||||
response = jsonrpc_stream_success(cmd);
|
||||
json_add_string(response, "result", "resolve");
|
||||
json_add_string(response, "payment_key", hexpreimage);
|
||||
return command_finished(cmd, response);
|
||||
}
|
||||
|
||||
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;
|
||||
size_t max;
|
||||
struct tlv_tlv_payload *payload;
|
||||
struct tlv_field *preimage_field = NULL;
|
||||
char *hexpreimage, *hexpaymenthash;
|
||||
struct sha256 payment_hash;
|
||||
bigsize_t s;
|
||||
|
||||
if (!payloadt)
|
||||
return htlc_accepted_continue(cmd);
|
||||
|
||||
rawpayload = json_tok_bin_from_hex(cmd, buf, payloadt);
|
||||
max = tal_bytelen(rawpayload);
|
||||
payload = tlv_tlv_payload_new(cmd);
|
||||
|
||||
s = fromwire_varint(&rawpayload, &max);
|
||||
if (s != max) {
|
||||
return htlc_accepted_continue(cmd);
|
||||
}
|
||||
fromwire_tlv_payload(&rawpayload, &max, payload);
|
||||
|
||||
/* Try looking for the field that contains the preimage */
|
||||
for (int i=0; i<tal_count(payload->fields); i++) {
|
||||
if (payload->fields[i].numtype == PREIMAGE_TLV_TYPE) {
|
||||
preimage_field = &payload->fields[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't have a preimage field then this is not a keysend, let
|
||||
* someone else take care of it. */
|
||||
if (preimage_field == NULL)
|
||||
return htlc_accepted_continue(cmd);
|
||||
|
||||
/* If the preimage is not 32 bytes long then we can't accept the
|
||||
* payment. */
|
||||
if (preimage_field->length != 32) {
|
||||
plugin_log(cmd->plugin, LOG_UNUSUAL,
|
||||
"Sender specified a preimage that is %zu bytes long, "
|
||||
"we expected 32 bytes. Ignoring this HTLC.",
|
||||
preimage_field->length);
|
||||
return htlc_accepted_continue(cmd);
|
||||
}
|
||||
|
||||
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(&payment_hash, preimage_field->value, preimage_field->length);
|
||||
hexpaymenthash = tal_hexstr(cmd, &payment_hash, sizeof(payment_hash));
|
||||
if (!json_tok_streq(buf, payment_hash_tok, hexpaymenthash)) {
|
||||
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);
|
||||
return htlc_accepted_continue(cmd);
|
||||
}
|
||||
|
||||
/* Finally we can resolve the payment with the preimage. */
|
||||
plugin_log(cmd->plugin, LOG_INFORM,
|
||||
"Resolving incoming HTLC with preimage for payment_hash %s "
|
||||
"provided in the onion payload.",
|
||||
hexpaymenthash);
|
||||
return htlc_accepted_resolve(cmd, hexpreimage);
|
||||
}
|
||||
|
||||
static const struct plugin_hook hooks[] = {
|
||||
{
|
||||
"htlc_accepted",
|
||||
htlc_accepted_call
|
||||
},
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
setup_locale();
|
||||
plugin_main(argv, init, PLUGIN_RESTARTABLE, commands, ARRAY_SIZE(commands),
|
||||
NULL, 0, NULL, 0, NULL);
|
||||
NULL, 0, hooks, ARRAY_SIZE(hooks), NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user