mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-21 22:31:48 +01:00
plugins/libplugin-pay: hack in blinded path support.
We simply take the first one, and route to the start of that. Then we append the blinded path to the onion construction. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
8720bbedae
commit
01a47720c3
6 changed files with 114 additions and 15 deletions
|
@ -172,7 +172,7 @@ ALL_PROGRAMS += $(C_PLUGINS)
|
|||
# Make all plugins depend on all plugin headers, for simplicity.
|
||||
$(PLUGIN_ALL_OBJS): $(PLUGIN_ALL_HEADER)
|
||||
|
||||
plugins/pay: $(PLUGIN_PAY_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_PAY_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) common/gossmap.o common/fp16.o common/route.o common/dijkstra.o common/bolt12.o common/bolt12_merkle.o wire/bolt12$(EXP)_wiregen.o bitcoin/block.o
|
||||
plugins/pay: $(PLUGIN_PAY_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_PAY_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) common/gossmap.o common/fp16.o common/route.o common/dijkstra.o common/bolt12.o common/bolt12_merkle.o wire/bolt12$(EXP)_wiregen.o bitcoin/block.o common/blindedpay.o common/blindedpath.o common/hmac.o common/blinding.o common/onion_encode.o
|
||||
|
||||
plugins/autoclean: $(PLUGIN_AUTOCLEAN_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS)
|
||||
|
||||
|
@ -188,7 +188,7 @@ plugins/txprepare: $(PLUGIN_TXPREPARE_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_O
|
|||
|
||||
plugins/bcli: $(PLUGIN_BCLI_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS)
|
||||
|
||||
plugins/keysend: wire/tlvstream.o wire/onion$(EXP)_wiregen.o $(PLUGIN_KEYSEND_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_PAY_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) common/gossmap.o common/fp16.o common/route.o common/dijkstra.o
|
||||
plugins/keysend: wire/tlvstream.o wire/onion$(EXP)_wiregen.o $(PLUGIN_KEYSEND_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_PAY_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) common/gossmap.o common/fp16.o common/route.o common/dijkstra.o common/blindedpay.o common/blindedpath.o common/hmac.o common/blinding.o common/onion_encode.o
|
||||
$(PLUGIN_KEYSEND_OBJS): $(PLUGIN_PAY_LIB_HEADER)
|
||||
|
||||
plugins/spenderp: bitcoin/block.o bitcoin/preimage.o bitcoin/psbt.o common/psbt_open.o wire/peer${EXP}_wiregen.o $(PLUGIN_SPENDER_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS)
|
||||
|
|
|
@ -174,6 +174,8 @@ static struct command_result *json_keysend(struct command *cmd, const char *buf,
|
|||
p->destination = tal_steal(p, destination);
|
||||
p->payment_secret = NULL;
|
||||
p->payment_metadata = NULL;
|
||||
p->blindedpath = NULL;
|
||||
p->blindedpay = NULL;
|
||||
p->amount = *msat;
|
||||
p->routes = tal_steal(p, hints);
|
||||
// 22 is the Rust-Lightning default and the highest minimum we know of.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "config.h"
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/blindedpay.h>
|
||||
#include <common/dijkstra.h>
|
||||
#include <common/gossmap.h>
|
||||
#include <common/json_stream.h>
|
||||
|
@ -1662,6 +1663,33 @@ static void payment_add_hop_onion_payload(struct payment *p,
|
|||
}
|
||||
}
|
||||
|
||||
static void payment_add_blindedpath(const tal_t *ctx,
|
||||
struct createonion_hop *hops,
|
||||
const struct blinded_path *bpath,
|
||||
struct amount_msat final_amt,
|
||||
u32 final_cltv)
|
||||
{
|
||||
/* It's a bit of a weird API for us, so we convert it back to
|
||||
* the struct tlv_tlv_payload */
|
||||
u8 **tlvs = blinded_onion_hops(tmpctx, final_amt, final_cltv, bpath);
|
||||
|
||||
for (size_t i = 0; i < tal_count(tlvs); i++) {
|
||||
const u8 *cursor = tlvs[i];
|
||||
size_t max = tal_bytelen(tlvs[i]);
|
||||
/* First one has to use real node_id */
|
||||
if (i == 0)
|
||||
node_id_from_pubkey(&hops[i].pubkey,
|
||||
&bpath->first_node_id);
|
||||
else
|
||||
node_id_from_pubkey(&hops[i].pubkey,
|
||||
&bpath->path[i]->blinded_node_id);
|
||||
|
||||
/* Length is prepended, discard that first! */
|
||||
fromwire_bigsize(&cursor, &max);
|
||||
hops[i].tlv_payload = fromwire_tlv_tlv_payload(ctx, &cursor, &max);
|
||||
}
|
||||
}
|
||||
|
||||
static void payment_compute_onion_payloads(struct payment *p)
|
||||
{
|
||||
struct createonion_request *cr;
|
||||
|
@ -1690,7 +1718,9 @@ static void payment_compute_onion_payloads(struct payment *p)
|
|||
cr->assocdata = tal_arr(cr, u8, 0);
|
||||
towire_sha256(&cr->assocdata, p->payment_hash);
|
||||
cr->session_key = NULL;
|
||||
cr->hops = tal_arr(cr, struct createonion_hop, tal_count(p->route));
|
||||
cr->hops = tal_arr(cr, struct createonion_hop,
|
||||
tal_count(p->route)
|
||||
+ (root->blindedpath ? tal_count(root->blindedpath->path) - 1: 0));
|
||||
|
||||
/* Non-final hops */
|
||||
for (size_t i = 0; i < hopcount - 1; i++) {
|
||||
|
@ -1704,14 +1734,27 @@ static void payment_compute_onion_payloads(struct payment *p)
|
|||
&p->route[i].scid));
|
||||
}
|
||||
|
||||
/* Final hop */
|
||||
payment_add_hop_onion_payload(
|
||||
p, &cr->hops[hopcount - 1], &p->route[hopcount - 1],
|
||||
&p->route[hopcount - 1], true,
|
||||
root->payment_secret, root->payment_metadata);
|
||||
tal_append_fmt(&routetxt, "%s",
|
||||
type_to_string(tmpctx, struct short_channel_id,
|
||||
&p->route[hopcount - 1].scid));
|
||||
/* If we're headed to a blinded path, connect that now. */
|
||||
if (root->blindedpath) {
|
||||
payment_add_blindedpath(cr->hops, cr->hops + hopcount - 1,
|
||||
root->blindedpath,
|
||||
root->blindedfinalamount,
|
||||
root->blindedfinalcltv);
|
||||
tal_append_fmt(&routetxt, "%s -> blinded path (%zu hops)",
|
||||
type_to_string(tmpctx, struct short_channel_id,
|
||||
&p->route[hopcount-1].scid),
|
||||
tal_count(root->blindedpath->path));
|
||||
} else {
|
||||
/* Final hop */
|
||||
payment_add_hop_onion_payload(
|
||||
p, &cr->hops[hopcount - 1], &p->route[hopcount - 1],
|
||||
&p->route[hopcount - 1], true,
|
||||
root->payment_secret,
|
||||
root->payment_metadata);
|
||||
tal_append_fmt(&routetxt, "%s",
|
||||
type_to_string(tmpctx, struct short_channel_id,
|
||||
&p->route[hopcount - 1].scid));
|
||||
}
|
||||
|
||||
paymod_log(p, LOG_DBG,
|
||||
"Created outgoing onion for route: %s", routetxt);
|
||||
|
|
|
@ -188,6 +188,12 @@ struct payment {
|
|||
/* Payment metadata, from the invoice if any. */
|
||||
u8 *payment_metadata;
|
||||
|
||||
/* Blinded path (for bolt12) */
|
||||
struct blinded_path *blindedpath;
|
||||
struct blinded_payinfo *blindedpay;
|
||||
struct amount_msat blindedfinalamount;
|
||||
u32 blindedfinalcltv;
|
||||
|
||||
u64 groupid;
|
||||
u32 partid;
|
||||
u32 next_partid;
|
||||
|
|
|
@ -1024,6 +1024,9 @@ static struct command_result *json_pay(struct command *cmd,
|
|||
p = payment_new(cmd, cmd, NULL /* No parent */, paymod_mods);
|
||||
p->invstring = tal_steal(p, b11str);
|
||||
p->description = tal_steal(p, description);
|
||||
/* Overridded by bolt12 if present */
|
||||
p->blindedpath = NULL;
|
||||
p->blindedpay = NULL;
|
||||
|
||||
if (!bolt12_has_prefix(b11str)) {
|
||||
b11 =
|
||||
|
@ -1085,7 +1088,9 @@ static struct command_result *json_pay(struct command *cmd,
|
|||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"experimental-offers disabled");
|
||||
|
||||
p->features = tal_steal(p, b12->features);
|
||||
/* FIXME: We disable MPP for now */
|
||||
/* p->features = tal_steal(p, b12->features); */
|
||||
p->features = NULL;
|
||||
|
||||
if (!b12->node_id)
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
|
@ -1109,8 +1114,33 @@ static struct command_result *json_pay(struct command *cmd,
|
|||
return command_fail(
|
||||
cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"recurring invoice requires a label");
|
||||
/* FIXME payment_secret should be signature! */
|
||||
{
|
||||
|
||||
/* BOLT-offers #12:
|
||||
* - MUST reject the invoice if `blindedpay` is not present.
|
||||
*/
|
||||
/* FIXME: We allow this for now. */
|
||||
|
||||
if (tal_count(b12->paths) != 0) {
|
||||
/* BOLT-offers #12: - MUST reject the invoice if
|
||||
* `blindedpay` does not contain exactly one
|
||||
* `blinded_payinfo` per `blinded_path`.
|
||||
*/
|
||||
if (tal_count(b12->paths) != tal_count(b12->blindedpay)) {
|
||||
return command_fail(
|
||||
cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"Wrong blinding info: %zu paths, %zu payinfo",
|
||||
tal_count(b12->paths),
|
||||
tal_count(b12->blindedpay));
|
||||
}
|
||||
|
||||
/* FIXME: do MPP across these! We choose first one. */
|
||||
p->blindedpath = tal_steal(p, b12->paths[0]);
|
||||
p->blindedpay = tal_steal(p, b12->blindedpay[0]);
|
||||
|
||||
/* Set destination to introduction point */
|
||||
node_id_from_pubkey(p->destination, &p->blindedpath->first_node_id);
|
||||
} else {
|
||||
/* FIXME payment_secret should be signature! */
|
||||
struct sha256 merkle;
|
||||
|
||||
p->payment_secret = tal(p, struct secret);
|
||||
|
@ -1121,7 +1151,6 @@ static struct command_result *json_pay(struct command *cmd,
|
|||
}
|
||||
p->payment_metadata = NULL;
|
||||
p->routes = NULL;
|
||||
/* FIXME: paths! */
|
||||
if (b12->cltv)
|
||||
p->min_final_cltv_expiry = *b12->cltv;
|
||||
else
|
||||
|
@ -1161,6 +1190,19 @@ static struct command_result *json_pay(struct command *cmd,
|
|||
p->amount = *msat;
|
||||
}
|
||||
|
||||
/* We replace real final values if we're using a blinded path */
|
||||
if (p->blindedpath) {
|
||||
p->blindedfinalcltv = p->min_final_cltv_expiry;
|
||||
p->blindedfinalamount = p->amount;
|
||||
|
||||
p->min_final_cltv_expiry += p->blindedpay->cltv_expiry_delta;
|
||||
if (!amount_msat_add_fee(&p->amount,
|
||||
p->blindedpay->fee_base_msat,
|
||||
p->blindedpay->fee_proportional_millionths))
|
||||
return command_fail(cmd, PAY_ROUTE_TOO_EXPENSIVE,
|
||||
"This payment blinded path fee overflows!");
|
||||
}
|
||||
|
||||
if (node_id_eq(&my_id, p->destination))
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"This payment is destined for ourselves. "
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
#include <unistd.h>
|
||||
|
||||
/* AUTOGENERATED MOCKS START */
|
||||
/* Generated stub for blinded_onion_hops */
|
||||
u8 **blinded_onion_hops(const tal_t *ctx UNNEEDED,
|
||||
struct amount_msat final_amount UNNEEDED,
|
||||
u32 final_cltv UNNEEDED,
|
||||
const struct blinded_path *path UNNEEDED)
|
||||
{ fprintf(stderr, "blinded_onion_hops called!\n"); abort(); }
|
||||
/* Generated stub for command_finished */
|
||||
struct command_result *command_finished(struct command *cmd UNNEEDED, struct json_stream *response UNNEEDED)
|
||||
{ fprintf(stderr, "command_finished called!\n"); abort(); }
|
||||
|
|
Loading…
Add table
Reference in a new issue