#include #include #include #include #include #include #include #include #define PREIMAGE_TLV_TYPE 5482373484 #define KEYSEND_FEATUREBIT 55 static unsigned int maxdelay_default; static struct node_id my_id; /***************************************************************************** * Keysend modifier * ================ * * The keysend modifier adds the payment preimage to the TLV payload. This * enables the recipient to accept the payment despite it not correspondin to * an invoice that the recipient created. Keysend does not provide any proof * or payment, but does not require an out-of-band communication round to get * an invoice first. */ /* FIXME: If we have more than one plugin using keysend we can move this to * libplugin-pay.c */ struct keysend_data { struct preimage preimage; }; REGISTER_PAYMENT_MODIFIER_HEADER(keysend, struct keysend_data); static struct keysend_data *keysend_init(struct payment *p) { struct keysend_data *d; struct sha256 payment_hash; if (p->parent == NULL) { /* If we are the root payment we generate a random preimage * and populate the preimage field in the keysend_data and the * payment_hash in the payment. */ d = tal(p, struct keysend_data); randombytes_buf(&d->preimage, sizeof(d->preimage)); ccan_sha256(&payment_hash, &d->preimage, sizeof(d->preimage)); p->payment_hash = tal_dup(p, struct sha256, &payment_hash); return d; } else { /* If we are a child payment (retry or split) we copy the * parent's information, since the payment_hash needs to match * in order to be collated at the recipient. */ return payment_mod_keysend_get_data(p->parent); } } static void keysend_cb(struct keysend_data *d, struct payment *p) { struct createonion_hop *last_payload; size_t hopcount; struct gossmap_node *node; bool enabled; const struct gossmap *gossmap = get_gossmap(p->plugin); /* On the root payment we perform the featurebit check. */ if (p->parent == NULL && p->step == PAYMENT_STEP_INITIALIZED) { node = gossmap_find_node(gossmap, p->destination); enabled = gossmap_node_get_feature(gossmap, node, KEYSEND_FEATUREBIT) != -1; if (!enabled) return payment_fail( p, "Recipient %s does not support keysend payments " "(feature bit %d missing in node announcement)", node_id_to_hexstr(tmpctx, p->destination), KEYSEND_FEATUREBIT); } if (p->step != PAYMENT_STEP_ONION_PAYLOAD) return payment_continue(p); hopcount = tal_count(p->createonion_request->hops); last_payload = &p->createonion_request->hops[hopcount - 1]; tlvstream_set_raw(&last_payload->tlv_payload->fields, PREIMAGE_TLV_TYPE, &d->preimage, sizeof(struct preimage)); return payment_continue(p); } REGISTER_PAYMENT_MODIFIER(keysend, struct keysend_data *, keysend_init, keysend_cb); /* * End of keysend modifier *****************************************************************************/ static void init(struct plugin *p, const char *buf UNUSED, const jsmntok_t *config UNUSED) { rpc_scan(p, "getinfo", take(json_out_obj(NULL, NULL, NULL)), "{id:%}", JSON_SCAN(json_to_node_id, &my_id)); rpc_scan(p, "listconfigs", take(json_out_obj(NULL, "config", "max-locktime-blocks")), "{max-locktime-blocks:%}", JSON_SCAN(json_to_number, &maxdelay_default)); } struct payment_modifier *pay_mods[8] = { &keysend_pay_mod, &local_channel_hints_pay_mod, &directpay_pay_mod, &shadowroute_pay_mod, &exemptfee_pay_mod, &waitblockheight_pay_mod, &retry_pay_mod, NULL, }; static struct command_result *json_keysend(struct command *cmd, const char *buf, const jsmntok_t *params) { struct payment *p; const char *label; struct amount_msat *exemptfee, *msat; struct node_id *destination; u64 *maxfee_pct_millionths; u32 *maxdelay; unsigned int *retryfor; #if DEVELOPER bool *use_shadow; #endif if (!param(cmd, buf, params, p_req("destination", param_node_id, &destination), p_req("msatoshi", param_msat, &msat), p_opt("label", param_string, &label), p_opt_def("maxfeepercent", param_millionths, &maxfee_pct_millionths, 500000), p_opt_def("retry_for", param_number, &retryfor, 60), p_opt_def("maxdelay", param_number, &maxdelay, maxdelay_default), p_opt_def("exemptfee", param_msat, &exemptfee, AMOUNT_MSAT(5000)), #if DEVELOPER p_opt_def("use_shadow", param_bool, &use_shadow, true), #endif NULL)) return command_param_failed(); p = payment_new(cmd, cmd, NULL /* No parent */, pay_mods); p->local_id = &my_id; p->json_buffer = tal_steal(p, buf); p->json_toks = params; p->destination = tal_steal(p, destination); p->destination_has_tlv = true; p->payment_secret = NULL; p->amount = *msat; p->routes = NULL; p->min_final_cltv_expiry = DEFAULT_FINAL_CLTV_DELTA; p->features = NULL; p->invstring = NULL; p->why = "Initial attempt"; p->constraints.cltv_budget = *maxdelay; p->deadline = timeabs_add(time_now(), time_from_sec(*retryfor)); p->getroute->riskfactorppm = 10000000; if (!amount_msat_fee(&p->constraints.fee_budget, p->amount, 0, *maxfee_pct_millionths / 100)) { tal_free(p); return command_fail( cmd, JSONRPC2_INVALID_PARAMS, "Overflow when computing fee budget, fee rate too high."); } p->constraints.cltv_budget = *maxdelay; payment_mod_exemptfee_get_data(p)->amount = *exemptfee; #if DEVELOPER payment_mod_shadowroute_get_data(p)->use_shadow = *use_shadow; #endif p->label = tal_steal(p, label); payment_start(p); /* We're keeping this around now */ tal_steal(cmd->plugin, p); return command_still_pending(cmd); } static const struct plugin_command commands[] = { { "keysend", "payment", "Send a payment without an invoice to a node", "Send an unsolicited payment of {amount} to {destination}, by providing the recipient the necessary information to claim the payment", json_keysend }, }; static struct command_result * htlc_accepted_continue(struct command *cmd, struct tlv_tlv_payload *payload) { struct json_stream *response; response = jsonrpc_stream_success(cmd); json_add_string(response, "result", "continue"); if (payload) { u8 *binpayload = tal_arr(cmd, u8, 0); towire_tlvstream_raw(&binpayload, payload->fields); json_add_string(response, "payload", tal_hex(cmd, binpayload)); } return command_finished(cmd, response); } /* Struct wrapping the information we extract from an incoming keysend * payment */ struct keysend_in { struct sha256 payment_hash; struct preimage payment_preimage; char *label; struct tlv_tlv_payload *payload; struct tlv_field *preimage_field; }; static struct command_result * htlc_accepted_invoice_created(struct command *cmd, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct keysend_in *ki) { int preimage_field_idx = ki->preimage_field - ki->payload->fields; /* Remove the preimage field so `lightningd` knows how to handle * this. */ tal_arr_remove(&ki->payload->fields, preimage_field_idx); /* 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.", tal_hexstr(tmpctx, &ki->payment_hash, sizeof(struct sha256))); return htlc_accepted_continue(cmd, ki->payload); } static struct command_result *htlc_accepted_call(struct command *cmd, const char *buf, const jsmntok_t *params) { const u8 *rawpayload; struct sha256 payment_hash; size_t max; struct tlv_tlv_payload *payload; struct tlv_field *preimage_field = NULL; bigsize_t s; bool unknown_even_type = false; struct tlv_field *field; struct keysend_in *ki; struct out_req *req; struct timeabs now = time_now(); const char *err; err = json_scan(tmpctx, buf, params, "{onion:{payload:%},htlc:{payment_hash:%}}", JSON_SCAN_TAL(cmd, json_tok_bin_from_hex, &rawpayload), JSON_SCAN(json_to_sha256, &payment_hash)); if (err) return htlc_accepted_continue(cmd, NULL); max = tal_bytelen(rawpayload); payload = tlv_tlv_payload_new(cmd); s = fromwire_bigsize(&rawpayload, &max); if (s != max) { return htlc_accepted_continue(cmd, NULL); } if (!fromwire_tlv_payload(&rawpayload, &max, payload)) { plugin_log( cmd->plugin, LOG_UNUSUAL, "Malformed TLV payload %.*s", json_tok_full_len(params), json_tok_full(buf, params)); return htlc_accepted_continue(cmd, NULL); } /* Try looking for the field that contains the preimage */ for (int i=0; ifields); i++) { field = &payload->fields[i]; if (field->numtype == PREIMAGE_TLV_TYPE) { preimage_field = field; break; } else if (field->numtype % 2 == 0 && field->meta == NULL) { unknown_even_type = true; 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, NULL); if (unknown_even_type) { plugin_log(cmd->plugin, LOG_UNUSUAL, "Payload contains unknown even TLV-type %" PRIu64 ", can't safely accept the keysend. Deferring to " "other plugins.", preimage_field->numtype); return htlc_accepted_continue(cmd, NULL); } /* 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, NULL); } ki = tal(cmd, struct keysend_in); memcpy(&ki->payment_preimage, preimage_field->value, 32); ki->label = tal_fmt(ki, "keysend-%lu.%09lu", (unsigned long)now.ts.tv_sec, now.ts.tv_nsec); ki->payload = tal_steal(ki, payload); ki->preimage_field = preimage_field; /* 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); 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.", 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); } /* Now we can call `invoice` RPC to backfill an invoce matching this * spontaneous payment, thus leaving us with an accounting * trace. Creating the invoice is best effort: it may fail if the * `payment_hash` is already attached to an existing invoice, and the * label could collide (unlikely since we use the nanosecond time). If * the call to `invoice` fails we will just continue, and `lightningd` * will be nice and reject the payment. */ req = jsonrpc_request_start(cmd->plugin, cmd, "invoice", &htlc_accepted_invoice_created, &htlc_accepted_invoice_created, ki); 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"); json_add_preimage(req->js, "preimage", &ki->payment_preimage); return send_outreq(cmd->plugin, req); } static const struct plugin_hook hooks[] = { { "htlc_accepted", htlc_accepted_call }, }; int main(int argc, char *argv[]) { struct feature_set features; setup_locale(); for (int i=0; i