diff --git a/common/Makefile b/common/Makefile index acadda6f6..2e078dc39 100644 --- a/common/Makefile +++ b/common/Makefile @@ -10,6 +10,7 @@ COMMON_SRC_NOGEN := \ common/billboard.c \ common/bip32.c \ common/blindedpath.c \ + common/blindedpay.c \ common/blinding.c \ common/blockheight_states.c \ common/bolt11.c \ diff --git a/common/blindedpay.c b/common/blindedpay.c new file mode 100644 index 000000000..1d4aa2502 --- /dev/null +++ b/common/blindedpay.c @@ -0,0 +1,40 @@ +#include "config.h" +#include +#include +#include +#include + +u8 **blinded_onion_hops(const tal_t *ctx, + struct amount_msat final_amount, + u32 final_cltv, + const struct blinded_path *path) +{ + u8 **onions = tal_arr(ctx, u8 *, tal_count(path->path)); + + assert(tal_count(onions) > 0); + + for (size_t i = 0; i < tal_count(onions); i++) { + bool first = (i == 0); + bool final = (i == tal_count(onions) - 1); + + /* BOLT-route-blinding #4: + * - For every node inside a blinded route: + * - MUST include the `encrypted_data` provided by the + * recipient + * - For the first node in the blinded route: + * - MUST include the `blinding_point` provided by the + * recipient + * - If it is the final node: + * - MUST include `amt_to_forward` and `outgoing_cltv_value`. + * - Otherwise: + * - MUST NOT include `amt_to_forward` and + * `outgoing_cltv_value`. + */ + onions[i] = onion_blinded_hop(onions, + final ? &final_amount : NULL, + final ? &final_cltv : NULL, + path->path[i]->encrypted_recipient_data, + first ? &path->blinding : NULL); + } + return onions; +} diff --git a/common/blindedpay.h b/common/blindedpay.h new file mode 100644 index 000000000..5ef1b0ddf --- /dev/null +++ b/common/blindedpay.h @@ -0,0 +1,25 @@ +/* Code to create onion fragments to make payment down this struct blinded_path */ +#ifndef LIGHTNING_COMMON_BLINDEDPAY_H +#define LIGHTNING_COMMON_BLINDEDPAY_H +#include "config.h" +#include +#include + +struct blinded_path; + +/** + * blinded_onion_hops - turn this path into a series of onion hops + * @ctx: context to allocate from + * @final_amount: amount we want to reach the end + * @final_cltv: cltv we want to at end + * @payinfo: fee and other restriction info + * + * This calls onion_nonfinal_hop and onion_final_hop to create onion + * blobs. + */ +u8 **blinded_onion_hops(const tal_t *ctx, + struct amount_msat final_amount, + u32 final_cltv, + const struct blinded_path *path); + +#endif /* LIGHTNING_COMMON_BLINDEDPAY_H */ diff --git a/common/onion.c b/common/onion.c index d7095621e..0875adc18 100644 --- a/common/onion.c +++ b/common/onion.c @@ -41,9 +41,7 @@ static u8 *make_tlv_hop(const tal_t *ctx, u8 *onion_nonfinal_hop(const tal_t *ctx, const struct short_channel_id *scid, struct amount_msat forward, - u32 outgoing_cltv, - const struct pubkey *blinding, - const u8 *enctlv) + u32 outgoing_cltv) { struct tlv_tlv_payload *tlv = tlv_tlv_payload_new(tmpctx); @@ -60,8 +58,6 @@ u8 *onion_nonfinal_hop(const tal_t *ctx, tlv->amt_to_forward = &forward.millisatoshis; /* Raw: TLV convert */ tlv->outgoing_cltv_value = &outgoing_cltv; tlv->short_channel_id = cast_const(struct short_channel_id *, scid); - tlv->blinding_point = cast_const(struct pubkey *, blinding); - tlv->encrypted_recipient_data = cast_const(u8 *, enctlv); return make_tlv_hop(ctx, tlv); } @@ -69,8 +65,6 @@ u8 *onion_final_hop(const tal_t *ctx, struct amount_msat forward, u32 outgoing_cltv, struct amount_msat total_msat, - const struct pubkey *blinding, - const u8 *enctlv, const struct secret *payment_secret, const u8 *payment_metadata) { @@ -104,8 +98,26 @@ u8 *onion_final_hop(const tal_t *ctx, tlv->payment_data = &tlv_pdata; } tlv->payment_metadata = cast_const(u8 *, payment_metadata); - tlv->blinding_point = cast_const(struct pubkey *, blinding); + return make_tlv_hop(ctx, tlv); +} + +u8 *onion_blinded_hop(const tal_t *ctx, + const struct amount_msat *amt_to_forward, + const u32 *outgoing_cltv_value, + const u8 *enctlv, + const struct pubkey *blinding) +{ + struct tlv_tlv_payload *tlv = tlv_tlv_payload_new(tmpctx); + + if (amt_to_forward) { + tlv->amt_to_forward + = cast_const(u64 *, + &amt_to_forward->millisatoshis); /* Raw: TLV convert */ + } + tlv->outgoing_cltv_value = cast_const(u32 *, outgoing_cltv_value); tlv->encrypted_recipient_data = cast_const(u8 *, enctlv); + tlv->blinding_point = cast_const(struct pubkey *, blinding); + return make_tlv_hop(ctx, tlv); } diff --git a/common/onion.h b/common/onion.h index d20059a99..6bd4bf234 100644 --- a/common/onion.h +++ b/common/onion.h @@ -26,20 +26,24 @@ struct onion_payload { u8 *onion_nonfinal_hop(const tal_t *ctx, const struct short_channel_id *scid, struct amount_msat forward, - u32 outgoing_cltv, - const struct pubkey *blinding, - const u8 *enctlv); + u32 outgoing_cltv); /* Note that this can fail if we supply payment_secret or payment_metadata and !use_tlv! */ u8 *onion_final_hop(const tal_t *ctx, struct amount_msat forward, u32 outgoing_cltv, struct amount_msat total_msat, - const struct pubkey *blinding, - const u8 *enctlv, const struct secret *payment_secret, const u8 *payment_metadata); +/* Blinding has more complex rules on what fields are encoded: this is the + * generic interface, as used by blindedpay.h */ +u8 *onion_blinded_hop(const tal_t *ctx, + const struct amount_msat *amt_to_forward, + const u32 *outgoing_cltv_value, + const u8 *enctlv, + const struct pubkey *blinding) + NON_NULL_ARGS(4); /** * onion_decode: decode payload from a decrypted onion. diff --git a/common/route.c b/common/route.c index 3ad9b4e96..f88cb0082 100644 --- a/common/route.c +++ b/common/route.c @@ -102,10 +102,6 @@ static bool dijkstra_to_hops(struct route_hop **hops, next = gossmap_nth_node(gossmap, c, !(*hops)[num_hops].direction); gossmap_node_get_id(gossmap, next, &(*hops)[num_hops].node_id); - /* These are (ab)used by others. */ - (*hops)[num_hops].blinding = NULL; - (*hops)[num_hops].enctlv = NULL; - if (!dijkstra_to_hops(hops, gossmap, dij, next, amount, cltv)) return false; diff --git a/common/route.h b/common/route.h index f28b0d073..1bdb7f0f9 100644 --- a/common/route.h +++ b/common/route.h @@ -19,8 +19,6 @@ struct gossmap_node; * @node_id: the node_id of the destination of this hop. * @amount: amount to send through this hop. * @delay: total cltv delay at this hop. - * @blinding: blinding key for this hop (if any) - * @enctlv: encrypted TLV for this hop (if any) */ struct route_hop { struct short_channel_id scid; @@ -28,8 +26,6 @@ struct route_hop { struct node_id node_id; struct amount_msat amount; u32 delay; - struct pubkey *blinding; - u8 *enctlv; }; /* Can c carry amount in dir? */ diff --git a/devtools/onion.c b/devtools/onion.c index 58c76c851..e19360ae5 100644 --- a/devtools/onion.c +++ b/devtools/onion.c @@ -79,15 +79,12 @@ static void do_generate(int argc, char **argv, sphinx_add_hop_has_length(sp, &path[i], take(onion_final_hop(NULL, amt, i, amt, - NULL, NULL, NULL, NULL))); else sphinx_add_hop_has_length(sp, &path[i], take(onion_nonfinal_hop(NULL, &scid, - amt, i, - NULL, - NULL))); + amt, i))); } } diff --git a/lightningd/pay.c b/lightningd/pay.c index e8fe8abee..b3bfec8f1 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -1172,9 +1172,7 @@ send_payment(struct lightningd *ld, take(onion_nonfinal_hop(NULL, &route[i + 1].scid, route[i + 1].amount, - base_expiry + route[i + 1].delay, - route[i].blinding, - route[i].enctlv))); + base_expiry + route[i + 1].delay))); } /* And finally set the final hop to the special values in @@ -1193,7 +1191,7 @@ send_payment(struct lightningd *ld, onion = onion_final_hop(cmd, route[i].amount, base_expiry + route[i].delay, - total_msat, route[i].blinding, route[i].enctlv, + total_msat, payment_secret, payment_metadata); if (!onion) { return command_fail(cmd, PAY_DESTINATION_PERM_FAIL, @@ -1381,8 +1379,6 @@ static struct command_result *param_route_hops(struct command *cmd, struct node_id *id; struct short_channel_id *channel; unsigned *delay, *direction; - struct pubkey *blinding; - u8 *enctlv; int *ignored; if (!param(cmd, buffer, t, @@ -1394,8 +1390,6 @@ static struct command_result *param_route_hops(struct command *cmd, /* Allowed (getroute supplies it) but ignored */ p_opt("direction", param_number, &direction), p_opt("style", param_route_hop_style, &ignored), - p_opt("blinding", param_pubkey, &blinding), - p_opt("encrypted_recipient_data", param_bin_from_hex, &enctlv), NULL)) return command_param_failed(); @@ -1403,8 +1397,6 @@ static struct command_result *param_route_hops(struct command *cmd, (*hops)[i].node_id = *id; (*hops)[i].delay = *delay; (*hops)[i].scid = *channel; - (*hops)[i].blinding = blinding; - (*hops)[i].enctlv = enctlv; } return NULL;