Skip to content

Commit

Permalink
common/blindedpay: routines to construct a blinded payment.
Browse files Browse the repository at this point in the history
Don't shoehorn it into onion_nonfinal_hop() and onion_final_hop(), but
provide an explicit routine "blinded_onion_hops" and an onion helper
"onion_blinded_hop()" for it to call.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell committed Oct 26, 2022
1 parent 325fe2e commit 511e8e6
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 35 deletions.
1 change: 1 addition & 0 deletions common/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
40 changes: 40 additions & 0 deletions common/blindedpay.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "config.h"
#include <assert.h>
#include <common/blindedpay.h>
#include <common/bolt12.h>
#include <common/onion.h>

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;
}
25 changes: 25 additions & 0 deletions common/blindedpay.h
Original file line number Diff line number Diff line change
@@ -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 <ccan/tal/tal.h>
#include <common/amount.h>

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 */
28 changes: 20 additions & 8 deletions common/onion.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -60,17 +58,13 @@ 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);
}

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)
{
Expand Down Expand Up @@ -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);
}

Expand Down
14 changes: 9 additions & 5 deletions common/onion.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 0 additions & 4 deletions common/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 0 additions & 4 deletions common/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,13 @@ 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;
int direction;
struct node_id node_id;
struct amount_msat amount;
u32 delay;
struct pubkey *blinding;
u8 *enctlv;
};

/* Can c carry amount in dir? */
Expand Down
5 changes: 1 addition & 4 deletions devtools/onion.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
}
}

Expand Down
12 changes: 2 additions & 10 deletions lightningd/pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -1394,17 +1390,13 @@ 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();

(*hops)[i].amount = *amount_msat;
(*hops)[i].node_id = *id;
(*hops)[i].delay = *delay;
(*hops)[i].scid = *channel;
(*hops)[i].blinding = blinding;
(*hops)[i].enctlv = enctlv;
}

return NULL;
Expand Down

0 comments on commit 511e8e6

Please sign in to comment.