lightningd: remove support for legacy onion format.

As per proposal in https://github.com/lightning/bolts/pull/962

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Removed: protocol: support for legacy onion format removed, since everyone supports the new one.
This commit is contained in:
Rusty Russell
2022-03-09 06:52:22 +10:30
parent 072c4711ec
commit 43a833e405
18 changed files with 197 additions and 448 deletions

View File

@@ -9,34 +9,13 @@
/* BOLT #4: /* BOLT #4:
* *
* ## Legacy `hop_data` payload format * ### `tlv_payload` format
* *
* The `hop_data` format is identified by a single `0x00`-byte length, * This is a more flexible format, which avoids the redundant
* for backward compatibility. Its payload is defined as: * `short_channel_id` field for the final node. It is formatted
* * according to the Type-Length-Value format defined in [BOLT
* 1. type: `hop_data` (for `realm` 0) * #1](01-messaging.md#type-length-value-format).
* 2. data:
* * [`short_channel_id`:`short_channel_id`]
* * [`u64`:`amt_to_forward`]
* * [`u32`:`outgoing_cltv_value`]
* * [`12*byte`:`padding`]
*/ */
static u8 *make_v0_hop(const tal_t *ctx,
const struct short_channel_id *scid,
struct amount_msat forward, u32 outgoing_cltv)
{
const u8 padding[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* Prepend 0 byte for realm */
u8 *buf = tal_arrz(ctx, u8, 1);
towire_short_channel_id(&buf, scid);
towire_amount_msat(&buf, forward);
towire_u32(&buf, outgoing_cltv);
towire(&buf, padding, ARRAY_SIZE(padding));
assert(tal_bytelen(buf) == 1 + 32);
return buf;
}
static u8 *make_tlv_hop(const tal_t *ctx, static u8 *make_tlv_hop(const tal_t *ctx,
const struct tlv_tlv_payload *tlv) const struct tlv_tlv_payload *tlv)
{ {
@@ -58,14 +37,12 @@ static u8 *make_tlv_hop(const tal_t *ctx,
} }
u8 *onion_nonfinal_hop(const tal_t *ctx, u8 *onion_nonfinal_hop(const tal_t *ctx,
bool use_tlv,
const struct short_channel_id *scid, const struct short_channel_id *scid,
struct amount_msat forward, struct amount_msat forward,
u32 outgoing_cltv, u32 outgoing_cltv,
const struct pubkey *blinding, const struct pubkey *blinding,
const u8 *enctlv) const u8 *enctlv)
{ {
if (use_tlv) {
struct tlv_tlv_payload *tlv = tlv_tlv_payload_new(tmpctx); struct tlv_tlv_payload *tlv = tlv_tlv_payload_new(tmpctx);
/* BOLT #4: /* BOLT #4:
@@ -80,24 +57,15 @@ u8 *onion_nonfinal_hop(const tal_t *ctx,
*/ */
tlv->amt_to_forward = &forward.millisatoshis; /* Raw: TLV convert */ tlv->amt_to_forward = &forward.millisatoshis; /* Raw: TLV convert */
tlv->outgoing_cltv_value = &outgoing_cltv; tlv->outgoing_cltv_value = &outgoing_cltv;
tlv->short_channel_id = cast_const(struct short_channel_id *, tlv->short_channel_id = cast_const(struct short_channel_id *, scid);
scid);
#if EXPERIMENTAL_FEATURES #if EXPERIMENTAL_FEATURES
tlv->blinding_point = cast_const(struct pubkey *, blinding); tlv->blinding_point = cast_const(struct pubkey *, blinding);
tlv->encrypted_recipient_data = cast_const(u8 *, enctlv); tlv->encrypted_recipient_data = cast_const(u8 *, enctlv);
#endif #endif
return make_tlv_hop(ctx, tlv); return make_tlv_hop(ctx, tlv);
} else {
#if EXPERIMENTAL_FEATURES
if (blinding || enctlv)
return NULL;
#endif
return make_v0_hop(ctx, scid, forward, outgoing_cltv);
}
} }
u8 *onion_final_hop(const tal_t *ctx, u8 *onion_final_hop(const tal_t *ctx,
bool use_tlv,
struct amount_msat forward, struct amount_msat forward,
u32 outgoing_cltv, u32 outgoing_cltv,
struct amount_msat total_msat, struct amount_msat total_msat,
@@ -105,14 +73,13 @@ u8 *onion_final_hop(const tal_t *ctx,
const u8 *enctlv, const u8 *enctlv,
const struct secret *payment_secret) const struct secret *payment_secret)
{ {
struct tlv_tlv_payload *tlv = tlv_tlv_payload_new(tmpctx);
struct tlv_tlv_payload_payment_data tlv_pdata;
/* These go together! */ /* These go together! */
if (!payment_secret) if (!payment_secret)
assert(amount_msat_eq(total_msat, forward)); assert(amount_msat_eq(total_msat, forward));
if (use_tlv) {
struct tlv_tlv_payload *tlv = tlv_tlv_payload_new(tmpctx);
struct tlv_tlv_payload_payment_data tlv_pdata;
/* BOLT #4: /* BOLT #4:
* *
* The writer: * The writer:
@@ -140,24 +107,12 @@ u8 *onion_final_hop(const tal_t *ctx,
tlv->encrypted_recipient_data = cast_const(u8 *, enctlv); tlv->encrypted_recipient_data = cast_const(u8 *, enctlv);
#endif #endif
return make_tlv_hop(ctx, tlv); return make_tlv_hop(ctx, tlv);
} else {
static struct short_channel_id all_zero_scid;
/* No payment secrets in legacy format. */
if (payment_secret)
return NULL;
#if EXPERIMENTAL_FEATURES
if (blinding || enctlv)
return NULL;
#endif
return make_v0_hop(ctx, &all_zero_scid, forward, outgoing_cltv);
}
} }
/* Returns true if valid, and fills in type. */ /* Returns true if valid, and fills in len. */
static bool pull_payload_length(const u8 **cursor, static bool pull_payload_length(const u8 **cursor,
size_t *max, size_t *max,
bool has_realm, bool has_realm,
enum onion_payload_type *type,
size_t *len) size_t *len)
{ {
/* *len will incorporate bytes we read from cursor */ /* *len will incorporate bytes we read from cursor */
@@ -172,19 +127,6 @@ static bool pull_payload_length(const u8 **cursor,
if (!cursor) if (!cursor)
return false; return false;
/* BOLT #4:
* - Legacy `hop_data` format, identified by a single `0x00` byte for
* length. In this case the `hop_payload_length` is defined to be 32
* bytes.
*/
if (has_realm && *len == 0) {
if (type)
*type = ONION_V0_PAYLOAD;
assert(*cursor - start == 1);
*len = 1 + 32;
return true;
}
/* BOLT #4: /* BOLT #4:
* - `tlv_payload` format, identified by any length over `1`. In this * - `tlv_payload` format, identified by any length over `1`. In this
* case the `hop_payload_length` is equal to the numeric value of * case the `hop_payload_length` is equal to the numeric value of
@@ -200,8 +142,6 @@ static bool pull_payload_length(const u8 **cursor,
return false; return false;
} }
if (type)
*type = ONION_TLV_PAYLOAD;
*len += (*cursor - start); *len += (*cursor - start);
return true; return true;
} }
@@ -210,11 +150,10 @@ static bool pull_payload_length(const u8 **cursor,
} }
size_t onion_payload_length(const u8 *raw_payload, size_t len, bool has_realm, size_t onion_payload_length(const u8 *raw_payload, size_t len, bool has_realm,
bool *valid, bool *valid)
enum onion_payload_type *type)
{ {
size_t max = len, payload_len; size_t max = len, payload_len;
*valid = pull_payload_length(&raw_payload, &max, has_realm, type, &payload_len); *valid = pull_payload_length(&raw_payload, &max, has_realm, &payload_len);
/* If it's not valid, copy the entire thing. */ /* If it's not valid, copy the entire thing. */
if (!*valid) if (!*valid)
@@ -276,40 +215,9 @@ struct onion_payload *onion_decode(const tal_t *ctx,
size_t max = tal_bytelen(cursor), len; size_t max = tal_bytelen(cursor), len;
struct tlv_tlv_payload *tlv; struct tlv_tlv_payload *tlv;
if (!pull_payload_length(&cursor, &max, true, &p->type, &len)) if (!pull_payload_length(&cursor, &max, true, &len))
return tal_free(p); return tal_free(p);
switch (p->type) {
case ONION_V0_PAYLOAD:
p->type = ONION_V0_PAYLOAD;
p->forward_channel = tal(p, struct short_channel_id);
fromwire_short_channel_id(&cursor, &max, p->forward_channel);
p->amt_to_forward = fromwire_amount_msat(&cursor, &max);
p->outgoing_cltv = fromwire_u32(&cursor, &max);
p->payment_secret = NULL;
p->blinding = NULL;
/* We can't handle blinding with a legacy payload */
if (blinding)
return tal_free(p);
if (rs->nextcase == ONION_FORWARD) {
p->total_msat = NULL;
} else {
/* BOLT #4:
* - if it is the final node:
* - MUST treat `total_msat` as if it were equal to
* `amt_to_forward` if it is not present. */
p->total_msat = tal_dup(p, struct amount_msat,
&p->amt_to_forward);
}
/* If they somehow got an invalid onion this far, fail. */
if (!cursor)
return tal_free(p);
p->tlv = NULL;
return p;
case ONION_TLV_PAYLOAD:
tlv = tlv_tlv_payload_new(p); tlv = tlv_tlv_payload_new(p);
if (!fromwire_tlv_payload(&cursor, &max, tlv)) if (!fromwire_tlv_payload(&cursor, &max, tlv))
goto fail; goto fail;
@@ -404,10 +312,7 @@ struct onion_payload *onion_decode(const tal_t *ctx,
} }
p->tlv = tal_steal(p, tlv); p->tlv = tal_steal(p, tlv);
return p; return p;
}
/* You said it was a valid type! */
abort();
fail: fail:
tal_free(tlv); tal_free(tlv);
tal_free(p); tal_free(p);

View File

@@ -6,14 +6,7 @@
struct route_step; struct route_step;
enum onion_payload_type {
ONION_V0_PAYLOAD = 0,
ONION_TLV_PAYLOAD = 1,
};
struct onion_payload { struct onion_payload {
enum onion_payload_type type;
struct amount_msat amt_to_forward; struct amount_msat amt_to_forward;
u32 outgoing_cltv; u32 outgoing_cltv;
struct amount_msat *total_msat; struct amount_msat *total_msat;
@@ -29,7 +22,6 @@ struct onion_payload {
}; };
u8 *onion_nonfinal_hop(const tal_t *ctx, u8 *onion_nonfinal_hop(const tal_t *ctx,
bool use_tlv,
const struct short_channel_id *scid, const struct short_channel_id *scid,
struct amount_msat forward, struct amount_msat forward,
u32 outgoing_cltv, u32 outgoing_cltv,
@@ -38,7 +30,6 @@ u8 *onion_nonfinal_hop(const tal_t *ctx,
/* Note that this can fail if we supply payment_secret and !use_tlv! */ /* Note that this can fail if we supply payment_secret and !use_tlv! */
u8 *onion_final_hop(const tal_t *ctx, u8 *onion_final_hop(const tal_t *ctx,
bool use_tlv,
struct amount_msat forward, struct amount_msat forward,
u32 outgoing_cltv, u32 outgoing_cltv,
struct amount_msat total_msat, struct amount_msat total_msat,
@@ -52,7 +43,6 @@ u8 *onion_final_hop(const tal_t *ctx,
* @len: length of @raw_payload in bytes. * @len: length of @raw_payload in bytes.
* @has_realm: used for HTLCs, where first byte 0 is magical. * @has_realm: used for HTLCs, where first byte 0 is magical.
* @valid: set to true if it is valid, false otherwise. * @valid: set to true if it is valid, false otherwise.
* @type: if non-NULL, set to type of payload if *@valid is true.
* *
* If @valid is set, there is room for the HMAC immediately following, * If @valid is set, there is room for the HMAC immediately following,
* as the return value is <= ROUTING_INFO_SIZE - HMAC_SIZE. Otherwise, * as the return value is <= ROUTING_INFO_SIZE - HMAC_SIZE. Otherwise,
@@ -60,8 +50,7 @@ u8 *onion_final_hop(const tal_t *ctx,
*/ */
size_t onion_payload_length(const u8 *raw_payload, size_t len, size_t onion_payload_length(const u8 *raw_payload, size_t len,
bool has_realm, bool has_realm,
bool *valid, bool *valid);
enum onion_payload_type *type);
/** /**
* onion_decode: decode payload from a decrypted onion. * onion_decode: decode payload from a decrypted onion.

View File

@@ -101,12 +101,6 @@ static bool dijkstra_to_hops(struct route_hop **hops,
/* Find other end of channel. */ /* Find other end of channel. */
next = gossmap_nth_node(gossmap, c, !(*hops)[num_hops].direction); next = gossmap_nth_node(gossmap, c, !(*hops)[num_hops].direction);
gossmap_node_get_id(gossmap, next, &(*hops)[num_hops].node_id); gossmap_node_get_id(gossmap, next, &(*hops)[num_hops].node_id);
/* If we don't have a node_announcement, we *assume* modern */
if (next->nann_off == 0
|| gossmap_node_get_feature(gossmap, next, OPT_VAR_ONION) != -1)
(*hops)[num_hops].style = ROUTE_HOP_TLV;
else
(*hops)[num_hops].style = ROUTE_HOP_LEGACY;
/* These are (ab)used by others. */ /* These are (ab)used by others. */
(*hops)[num_hops].blinding = NULL; (*hops)[num_hops].blinding = NULL;

View File

@@ -11,11 +11,6 @@ struct gossmap;
struct gossmap_chan; struct gossmap_chan;
struct gossmap_node; struct gossmap_node;
enum route_hop_style {
ROUTE_HOP_LEGACY = 1,
ROUTE_HOP_TLV = 2,
};
/** /**
* struct route_hop: a hop in a route. * struct route_hop: a hop in a route.
* *
@@ -26,7 +21,6 @@ enum route_hop_style {
* @delay: total cltv delay at this hop. * @delay: total cltv delay at this hop.
* @blinding: blinding key for this hop (if any) * @blinding: blinding key for this hop (if any)
* @enctlv: encrypted TLV for this hop (if any) * @enctlv: encrypted TLV for this hop (if any)
* @style: onion encoding style for this hop.
*/ */
struct route_hop { struct route_hop {
struct short_channel_id scid; struct short_channel_id scid;
@@ -36,7 +30,6 @@ struct route_hop {
u32 delay; u32 delay;
struct pubkey *blinding; struct pubkey *blinding;
u8 *enctlv; u8 *enctlv;
enum route_hop_style style;
}; };
/* Can c carry amount in dir? */ /* Can c carry amount in dir? */

View File

@@ -627,7 +627,7 @@ struct route_step *process_onionpacket(
payload_size = onion_payload_length(paddedheader, payload_size = onion_payload_length(paddedheader,
tal_bytelen(msg->routinginfo), tal_bytelen(msg->routinginfo),
has_realm, has_realm,
&valid, NULL); &valid);
/* Can't decode? Treat it as terminal. */ /* Can't decode? Treat it as terminal. */
if (!valid) { if (!valid) {

View File

@@ -91,8 +91,7 @@ struct onionreply *new_onionreply(const tal_t *ctx UNNEEDED, const u8 *contents
/* Generated stub for onion_payload_length */ /* Generated stub for onion_payload_length */
size_t onion_payload_length(const u8 *raw_payload UNNEEDED, size_t len UNNEEDED, size_t onion_payload_length(const u8 *raw_payload UNNEEDED, size_t len UNNEEDED,
bool has_realm UNNEEDED, bool has_realm UNNEEDED,
bool *valid UNNEEDED, bool *valid UNNEEDED)
enum onion_payload_type *type UNNEEDED)
{ fprintf(stderr, "onion_payload_length called!\n"); abort(); } { fprintf(stderr, "onion_payload_length called!\n"); abort(); }
/* Generated stub for pubkey_from_node_id */ /* Generated stub for pubkey_from_node_id */
bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED) bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED)

View File

@@ -71,7 +71,6 @@ static void do_generate(int argc, char **argv,
} else { } else {
struct short_channel_id scid; struct short_channel_id scid;
struct amount_msat amt; struct amount_msat amt;
bool use_tlv = streq(argv[1 + i] + klen, "/tlv");
/* FIXME: support secret and and total_msat */ /* FIXME: support secret and and total_msat */
memset(&scid, i, sizeof(scid)); memset(&scid, i, sizeof(scid));
@@ -79,14 +78,12 @@ static void do_generate(int argc, char **argv,
if (i == num_hops - 1) if (i == num_hops - 1)
sphinx_add_hop(sp, &path[i], sphinx_add_hop(sp, &path[i],
take(onion_final_hop(NULL, take(onion_final_hop(NULL,
use_tlv,
amt, i, amt, amt, i, amt,
NULL, NULL, NULL, NULL,
NULL))); NULL)));
else else
sphinx_add_hop(sp, &path[i], sphinx_add_hop(sp, &path[i],
take(onion_nonfinal_hop(NULL, take(onion_nonfinal_hop(NULL,
use_tlv,
&scid, &scid,
amt, i, amt, i,
NULL, NULL,
@@ -273,7 +270,6 @@ static void runtest(const char *filename)
decodetok = json_get_member(buffer, toks, "decode"); decodetok = json_get_member(buffer, toks, "decode");
json_for_each_arr(i, hop, decodetok) { json_for_each_arr(i, hop, decodetok) {
enum onion_payload_type type;
bool valid; bool valid;
hexprivkey = json_strdup(ctx, buffer, hop); hexprivkey = json_strdup(ctx, buffer, hop);
@@ -284,9 +280,8 @@ static void runtest(const char *filename)
errx(1, "Error serializing message."); errx(1, "Error serializing message.");
onion_payload_length(step->raw_payload, onion_payload_length(step->raw_payload,
tal_bytelen(step->raw_payload), tal_bytelen(step->raw_payload),
true, &valid, &type); true, &valid);
assert(valid); assert(valid);
printf(" Type: %d\n", type);
printf(" Payload: %s\n", tal_hex(ctx, step->raw_payload)); printf(" Payload: %s\n", tal_hex(ctx, step->raw_payload));
printf(" Next onion: %s\n", tal_hex(ctx, serialized)); printf(" Next onion: %s\n", tal_hex(ctx, serialized));
printf(" Next HMAC: %s\n", printf(" Next HMAC: %s\n",

View File

@@ -175,14 +175,12 @@ static void invoice_payment_add_tlvs(struct json_stream *stream,
struct htlc_set *hset) struct htlc_set *hset)
{ {
struct htlc_in *hin; struct htlc_in *hin;
struct tlv_tlv_payload *tlvs; const struct tlv_tlv_payload *tlvs;
assert(tal_count(hset->htlcs) > 0); assert(tal_count(hset->htlcs) > 0);
/* Pick the first HTLC as representative for the entire set. */ /* Pick the first HTLC as representative for the entire set. */
hin = hset->htlcs[0]; hin = hset->htlcs[0];
if (hin->payload->type != ONION_TLV_PAYLOAD)
return;
tlvs = hin->payload->tlv; tlvs = hin->payload->tlv;
json_array_start(stream, "extratlvs"); json_array_start(stream, "extratlvs");

View File

@@ -751,18 +751,6 @@ static struct command_result *wait_payment(struct lightningd *ld,
abort(); abort();
} }
static bool should_use_tlv(enum route_hop_style style)
{
switch (style) {
case ROUTE_HOP_TLV:
return true;
/* Otherwise fall thru */
case ROUTE_HOP_LEGACY:
return false;
}
abort();
}
/* Returns failmsg on failure, tallocated off ctx */ /* Returns failmsg on failure, tallocated off ctx */
static const u8 *send_onion(const tal_t *ctx, struct lightningd *ld, static const u8 *send_onion(const tal_t *ctx, struct lightningd *ld,
const struct onionpacket *packet, const struct onionpacket *packet,
@@ -1126,7 +1114,7 @@ send_payment(struct lightningd *ld,
struct short_channel_id *channels; struct short_channel_id *channels;
struct sphinx_path *path; struct sphinx_path *path;
struct pubkey pubkey; struct pubkey pubkey;
bool final_tlv, ret; bool ret;
u8 *onion; u8 *onion;
/* Expiry for HTLCs is absolute. And add one to give some margin. */ /* Expiry for HTLCs is absolute. And add one to give some margin. */
@@ -1144,7 +1132,6 @@ send_payment(struct lightningd *ld,
sphinx_add_hop(path, &pubkey, sphinx_add_hop(path, &pubkey,
take(onion_nonfinal_hop(NULL, take(onion_nonfinal_hop(NULL,
should_use_tlv(route[i].style),
&route[i + 1].scid, &route[i + 1].scid,
route[i + 1].amount, route[i + 1].amount,
base_expiry + route[i + 1].delay, base_expiry + route[i + 1].delay,
@@ -1157,25 +1144,15 @@ send_payment(struct lightningd *ld,
ret = pubkey_from_node_id(&pubkey, &ids[i]); ret = pubkey_from_node_id(&pubkey, &ids[i]);
assert(ret); assert(ret);
final_tlv = should_use_tlv(route[i].style);
/* BOLT #4: /* BOLT #4:
* - Unless `node_announcement`, `init` message or the * - Unless `node_announcement`, `init` message or the
* [BOLT #11](11-payment-encoding.md#tagged-fields) offers feature * [BOLT #11](11-payment-encoding.md#tagged-fields) offers feature
* `var_onion_optin`: * `var_onion_optin`:
* - MUST use the legacy payload format instead. * - MUST use the legacy payload format instead.
*/ */
/* In our case, we don't use it unless we also have a payment_secret; /* FIXME: This requirement is now obsolete, and we should remove it! */
* everyone should support this eventually */
if (!final_tlv && payment_secret)
final_tlv = true;
/* Parallel payments are invalid for legacy. */
if (partid && !final_tlv)
return command_fail(cmd, PAY_DESTINATION_PERM_FAIL,
"Cannot do parallel payments to legacy node");
onion = onion_final_hop(cmd, onion = onion_final_hop(cmd,
final_tlv,
route[i].amount, route[i].amount,
base_expiry + route[i].delay, base_expiry + route[i].delay,
total_msat, route[i].blinding, route[i].enctlv, total_msat, route[i].blinding, route[i].enctlv,
@@ -1326,23 +1303,19 @@ AUTODATA(json_command, &sendonion_command);
JSON-RPC sendpay interface JSON-RPC sendpay interface
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
/* FIXME: We accept his parameter for now, will deprecate eventually */
static struct command_result *param_route_hop_style(struct command *cmd, static struct command_result *param_route_hop_style(struct command *cmd,
const char *name, const char *name,
const char *buffer, const char *buffer,
const jsmntok_t *tok, const jsmntok_t *tok,
enum route_hop_style **style) int **unused)
{ {
*style = tal(cmd, enum route_hop_style); if (json_tok_streq(buffer, tok, "tlv")) {
if (json_tok_streq(buffer, tok, "legacy")) {
**style = ROUTE_HOP_LEGACY;
return NULL;
} else if (json_tok_streq(buffer, tok, "tlv")) {
**style = ROUTE_HOP_TLV;
return NULL; return NULL;
} }
return command_fail_badparam(cmd, name, buffer, tok, return command_fail_badparam(cmd, name, buffer, tok,
"should be 'legacy' or 'tlv'"); "should be 'tlv' ('legacy' not supported)");
} }
static struct command_result *param_route_hops(struct command *cmd, static struct command_result *param_route_hops(struct command *cmd,
@@ -1366,7 +1339,7 @@ static struct command_result *param_route_hops(struct command *cmd,
unsigned *delay, *direction; unsigned *delay, *direction;
struct pubkey *blinding; struct pubkey *blinding;
u8 *enctlv; u8 *enctlv;
enum route_hop_style *style, default_style; int *ignored;
if (!param(cmd, buffer, t, if (!param(cmd, buffer, t,
/* Only *one* of these is required */ /* Only *one* of these is required */
@@ -1378,7 +1351,7 @@ static struct command_result *param_route_hops(struct command *cmd,
p_opt("channel", param_short_channel_id, &channel), p_opt("channel", param_short_channel_id, &channel),
/* Allowed (getroute supplies it) but ignored */ /* Allowed (getroute supplies it) but ignored */
p_opt("direction", param_number, &direction), p_opt("direction", param_number, &direction),
p_opt("style", param_route_hop_style, &style), p_opt("style", param_route_hop_style, &ignored),
p_opt("blinding", param_pubkey, &blinding), p_opt("blinding", param_pubkey, &blinding),
p_opt("encrypted_recipient_data", param_bin_from_hex, &enctlv), p_opt("encrypted_recipient_data", param_bin_from_hex, &enctlv),
NULL)) NULL))
@@ -1405,21 +1378,12 @@ static struct command_result *param_route_hops(struct command *cmd,
if (!msat) if (!msat)
msat = amount_msat; msat = amount_msat;
if (blinding || enctlv) {
if (style && *style == ROUTE_HOP_LEGACY)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%s[%zi]: Can't have blinding or enctlv with legacy", name, i);
default_style = ROUTE_HOP_TLV;
} else
default_style = ROUTE_HOP_LEGACY;
(*hops)[i].amount = *msat; (*hops)[i].amount = *msat;
(*hops)[i].node_id = *id; (*hops)[i].node_id = *id;
(*hops)[i].delay = *delay; (*hops)[i].delay = *delay;
(*hops)[i].scid = *channel; (*hops)[i].scid = *channel;
(*hops)[i].blinding = blinding; (*hops)[i].blinding = blinding;
(*hops)[i].enctlv = enctlv; (*hops)[i].enctlv = enctlv;
(*hops)[i].style = style ? *style : default_style;
} }
return NULL; return NULL;

View File

@@ -945,15 +945,7 @@ static void htlc_accepted_hook_serialize(struct htlc_accepted_hook_payload *p,
json_add_hex_talarr(s, "payload", rs->raw_payload); json_add_hex_talarr(s, "payload", rs->raw_payload);
if (p->payload) { if (p->payload) {
switch (p->payload->type) {
case ONION_V0_PAYLOAD:
json_add_string(s, "type", "legacy");
break;
case ONION_TLV_PAYLOAD:
json_add_string(s, "type", "tlv"); json_add_string(s, "type", "tlv");
break;
}
if (p->payload->forward_channel) if (p->payload->forward_channel)
json_add_short_channel_id(s, "short_channel_id", json_add_short_channel_id(s, "short_channel_id",

View File

@@ -63,14 +63,7 @@ static void keysend_cb(struct keysend_data *d, struct payment *p) {
size_t hopcount; size_t hopcount;
/* On the root payment we perform the featurebit check. */ /* On the root payment we perform the featurebit check. */
if (p->parent == NULL && p->step == PAYMENT_STEP_INITIALIZED) { if (p->step == PAYMENT_STEP_FAILED) {
if (!payment_root(p)->destination_has_tlv)
return payment_fail(
p,
"Recipient %s does not support keysend payments "
"(no TLV support)",
node_id_to_hexstr(tmpctx, p->destination));
} else if (p->step == PAYMENT_STEP_FAILED) {
/* Now we can look at the error, and the failing node, /* Now we can look at the error, and the failing node,
and determine whether they didn't like our and determine whether they didn't like our
attempt. This is required since most nodes don't attempt. This is required since most nodes don't
@@ -184,7 +177,6 @@ static struct command_result *json_keysend(struct command *cmd, const char *buf,
p->json_buffer = tal_dup_talarr(p, const char, buf); p->json_buffer = tal_dup_talarr(p, const char, buf);
p->json_toks = params; p->json_toks = params;
p->destination = tal_steal(p, destination); p->destination = tal_steal(p, destination);
p->destination_has_tlv = true;
p->payment_secret = NULL; p->payment_secret = NULL;
p->amount = *msat; p->amount = *msat;
p->routes = tal_steal(p, hints); p->routes = tal_steal(p, hints);

View File

@@ -76,7 +76,6 @@ struct payment *payment_new(tal_t *ctx, struct command *cmd,
assert(cmd == NULL); assert(cmd == NULL);
tal_arr_expand(&parent->children, p); tal_arr_expand(&parent->children, p);
p->destination = parent->destination; p->destination = parent->destination;
p->destination_has_tlv = parent->destination_has_tlv;
p->amount = parent->amount; p->amount = parent->amount;
p->label = parent->label; p->label = parent->label;
p->payment_hash = parent->payment_hash; p->payment_hash = parent->payment_hash;
@@ -885,20 +884,6 @@ static struct command_result *payment_getroute(struct payment *p)
return command_still_pending(p->cmd); return command_still_pending(p->cmd);
} }
static u8 *tal_towire_legacy_payload(const tal_t *ctx, const struct legacy_payload *payload)
{
const u8 padding[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* Prepend 0 byte for realm */
u8 *buf = tal_arrz(ctx, u8, 1);
towire_short_channel_id(&buf, &payload->scid);
towire_amount_msat(&buf, payload->forward_amt);
towire_u32(&buf, payload->outgoing_cltv);
towire(&buf, padding, ARRAY_SIZE(padding));
assert(tal_bytelen(buf) == 1 + 32);
return buf;
}
static struct payment_result *tal_sendpay_result_from_json(const tal_t *ctx, static struct payment_result *tal_sendpay_result_from_json(const tal_t *ctx,
const char *buffer, const char *buffer,
const jsmntok_t *toks) const jsmntok_t *toks)
@@ -1611,7 +1596,6 @@ static void payment_add_hop_onion_payload(struct payment *p,
struct route_hop *node, struct route_hop *node,
struct route_hop *next, struct route_hop *next,
bool final, bool final,
bool force_tlv,
struct secret *payment_secret) struct secret *payment_secret)
{ {
struct createonion_request *cr = p->createonion_request; struct createonion_request *cr = p->createonion_request;
@@ -1619,29 +1603,12 @@ static void payment_add_hop_onion_payload(struct payment *p,
u64 msat = next->amount.millisatoshis; /* Raw: TLV payload generation*/ u64 msat = next->amount.millisatoshis; /* Raw: TLV payload generation*/
struct tlv_field **fields; struct tlv_field **fields;
struct payment *root = payment_root(p); struct payment *root = payment_root(p);
static struct short_channel_id all_zero_scid = {.u64 = 0};
/* This is the information of the node processing this payload, while /* This is the information of the node processing this payload, while
* `next` are the instructions to include in the payload, which is * `next` are the instructions to include in the payload, which is
* basically the channel going to the next node. */ * basically the channel going to the next node. */
dst->style = node->style;
if (force_tlv)
dst->style = ROUTE_HOP_TLV;
dst->pubkey = node->node_id; dst->pubkey = node->node_id;
switch (dst->style) {
case ROUTE_HOP_LEGACY:
dst->legacy_payload = tal(cr->hops, struct legacy_payload);
dst->legacy_payload->forward_amt = next->amount;
if (!final)
dst->legacy_payload->scid = next->scid;
else
dst->legacy_payload->scid = all_zero_scid;
dst->legacy_payload->outgoing_cltv = cltv;
break;
case ROUTE_HOP_TLV:
dst->tlv_payload = tlv_tlv_payload_new(cr->hops); dst->tlv_payload = tlv_tlv_payload_new(cr->hops);
fields = &dst->tlv_payload->fields; fields = &dst->tlv_payload->fields;
tlvstream_set_tu64(fields, TLV_TLV_PAYLOAD_AMT_TO_FORWARD, tlvstream_set_tu64(fields, TLV_TLV_PAYLOAD_AMT_TO_FORWARD,
@@ -1660,8 +1627,6 @@ static void payment_add_hop_onion_payload(struct payment *p,
fields, payment_secret, fields, payment_secret,
root->amount.millisatoshis); /* Raw: TLV payload generation*/ root->amount.millisatoshis); /* Raw: TLV payload generation*/
} }
break;
}
} }
static void payment_compute_onion_payloads(struct payment *p) static void payment_compute_onion_payloads(struct payment *p)
@@ -1699,7 +1664,7 @@ static void payment_compute_onion_payloads(struct payment *p)
/* The message is destined for hop i, but contains fields for /* The message is destined for hop i, but contains fields for
* i+1 */ * i+1 */
payment_add_hop_onion_payload(p, &cr->hops[i], &p->route[i], payment_add_hop_onion_payload(p, &cr->hops[i], &p->route[i],
&p->route[i + 1], false, false, &p->route[i + 1], false,
NULL); NULL);
tal_append_fmt(&routetxt, "%s -> ", tal_append_fmt(&routetxt, "%s -> ",
type_to_string(tmpctx, struct short_channel_id, type_to_string(tmpctx, struct short_channel_id,
@@ -1709,7 +1674,7 @@ static void payment_compute_onion_payloads(struct payment *p)
/* Final hop */ /* Final hop */
payment_add_hop_onion_payload( payment_add_hop_onion_payload(
p, &cr->hops[hopcount - 1], &p->route[hopcount - 1], p, &cr->hops[hopcount - 1], &p->route[hopcount - 1],
&p->route[hopcount - 1], true, root->destination_has_tlv, &p->route[hopcount - 1], true,
root->payment_secret); root->payment_secret);
tal_append_fmt(&routetxt, "%s", tal_append_fmt(&routetxt, "%s",
type_to_string(tmpctx, struct short_channel_id, type_to_string(tmpctx, struct short_channel_id,
@@ -1738,10 +1703,7 @@ static void payment_sendonion(struct payment *p)
json_object_start(req->js, NULL); json_object_start(req->js, NULL);
struct createonion_hop *hop = &p->createonion_request->hops[i]; struct createonion_hop *hop = &p->createonion_request->hops[i];
json_add_node_id(req->js, "pubkey", &hop->pubkey); json_add_node_id(req->js, "pubkey", &hop->pubkey);
if (hop->style == ROUTE_HOP_LEGACY) {
payload = tal_towire_legacy_payload(tmpctx, hop->legacy_payload);
json_add_hex_talarr(req->js, "payload", payload);
}else {
tlv = tal_arr(tmpctx, u8, 0); tlv = tal_arr(tmpctx, u8, 0);
towire_tlvstream_raw(&tlv, hop->tlv_payload->fields); towire_tlvstream_raw(&tlv, hop->tlv_payload->fields);
payload = tal_arr(tmpctx, u8, 0); payload = tal_arr(tmpctx, u8, 0);
@@ -1749,7 +1711,6 @@ static void payment_sendonion(struct payment *p)
towire(&payload, tlv, tal_bytelen(tlv)); towire(&payload, tlv, tal_bytelen(tlv));
json_add_hex_talarr(req->js, "payload", payload); json_add_hex_talarr(req->js, "payload", payload);
tal_free(tlv); tal_free(tlv);
}
tal_free(payload); tal_free(payload);
json_object_end(req->js); json_object_end(req->js);
} }
@@ -2832,7 +2793,6 @@ static void routehint_step_cb(struct routehints_data *d, struct payment *p)
} }
hop.node_id = *route_pubkey(p, routehint, i + 1); hop.node_id = *route_pubkey(p, routehint, i + 1);
hop.style = ROUTE_HOP_LEGACY;
hop.scid = routehint[i].short_channel_id; hop.scid = routehint[i].short_channel_id;
hop.amount = dest_amount; hop.amount = dest_amount;
hop.delay = route_cltv(d->final_cltv, routehint + i + 1, hop.delay = route_cltv(d->final_cltv, routehint + i + 1,
@@ -3216,7 +3176,6 @@ static void direct_pay_override(struct payment *p) {
p->route[0].scid = hint->scid.scid; p->route[0].scid = hint->scid.scid;
p->route[0].direction = hint->scid.dir; p->route[0].direction = hint->scid.dir;
p->route[0].node_id = *p->destination; p->route[0].node_id = *p->destination;
p->route[0].style = p->destination_has_tlv ? ROUTE_HOP_TLV : ROUTE_HOP_LEGACY;
paymod_log(p, LOG_DBG, paymod_log(p, LOG_DBG,
"Found a direct channel (%s) with sufficient " "Found a direct channel (%s) with sufficient "
"capacity, skipping route computation.", "capacity, skipping route computation.",
@@ -3523,12 +3482,10 @@ static void presplit_cb(struct presplit_mod_data *d, struct payment *p)
* get the exact value through. */ * get the exact value through. */
size_t lastidx = tal_count(p->createonion_request->hops) - 1; size_t lastidx = tal_count(p->createonion_request->hops) - 1;
struct createonion_hop *hop = &p->createonion_request->hops[lastidx]; struct createonion_hop *hop = &p->createonion_request->hops[lastidx];
if (hop->style == ROUTE_HOP_TLV) {
struct tlv_field **fields = &hop->tlv_payload->fields; struct tlv_field **fields = &hop->tlv_payload->fields;
tlvstream_set_tlv_payload_data( tlvstream_set_tlv_payload_data(
fields, root->payment_secret, fields, root->payment_secret,
root->amount.millisatoshis); /* Raw: onion payload */ root->amount.millisatoshis); /* Raw: onion payload */
}
} else if (p->step == PAYMENT_STEP_INITIALIZED) { } else if (p->step == PAYMENT_STEP_INITIALIZED) {
/* The presplitter only acts on the root and only in the first /* The presplitter only acts on the root and only in the first
* step. */ * step. */
@@ -3708,12 +3665,10 @@ static void adaptive_splitter_cb(struct adaptive_split_mod_data *d, struct payme
* get the exact value through. */ * get the exact value through. */
size_t lastidx = tal_count(p->createonion_request->hops) - 1; size_t lastidx = tal_count(p->createonion_request->hops) - 1;
struct createonion_hop *hop = &p->createonion_request->hops[lastidx]; struct createonion_hop *hop = &p->createonion_request->hops[lastidx];
if (hop->style == ROUTE_HOP_TLV) {
struct tlv_field **fields = &hop->tlv_payload->fields; struct tlv_field **fields = &hop->tlv_payload->fields;
tlvstream_set_tlv_payload_data( tlvstream_set_tlv_payload_data(
fields, root->payment_secret, fields, root->payment_secret,
root->amount.millisatoshis); /* Raw: onion payload */ root->amount.millisatoshis); /* Raw: onion payload */
}
} else if (p->step == PAYMENT_STEP_FAILED && !p->abort) { } else if (p->step == PAYMENT_STEP_FAILED && !p->abort) {
if (amount_msat_greater(p->amount, MPP_ADAPTIVE_LOWER_LIMIT)) { if (amount_msat_greater(p->amount, MPP_ADAPTIVE_LOWER_LIMIT)) {
struct payment *a, *b; struct payment *a, *b;

View File

@@ -16,10 +16,7 @@ struct legacy_payload {
/* struct holding the information necessary to call createonion */ /* struct holding the information necessary to call createonion */
struct createonion_hop { struct createonion_hop {
struct node_id pubkey; struct node_id pubkey;
enum route_hop_style style;
struct tlv_tlv_payload *tlv_payload; struct tlv_tlv_payload *tlv_payload;
struct legacy_payload *legacy_payload;
}; };
struct createonion_request { struct createonion_request {
@@ -176,8 +173,6 @@ struct payment {
/* Real destination we want to route to */ /* Real destination we want to route to */
struct node_id *destination; struct node_id *destination;
/* Do we know for sure that this supports OPT_VAR_ONION? */
bool destination_has_tlv;
/* Payment hash extracted from the invoice if any. */ /* Payment hash extracted from the invoice if any. */
struct sha256 *payment_hash; struct sha256 *payment_hash;

View File

@@ -1735,9 +1735,6 @@ static bool json_to_route_hop_inplace(struct route_hop *dst, const char *buffer,
json_to_int(buffer, directiontok, &dst->direction); json_to_int(buffer, directiontok, &dst->direction);
json_to_msat(buffer, amounttok, &dst->amount); json_to_msat(buffer, amounttok, &dst->amount);
json_to_number(buffer, delaytok, &dst->delay); json_to_number(buffer, delaytok, &dst->delay);
dst->style = json_tok_streq(buffer, styletok, "legacy")
? ROUTE_HOP_LEGACY
: ROUTE_HOP_TLV;
return true; return true;
} }

View File

@@ -2371,8 +2371,6 @@ static struct command_result *json_paymod(struct command *cmd,
invexpiry = b11->timestamp + b11->expiry; invexpiry = b11->timestamp + b11->expiry;
p->destination = tal_dup(p, struct node_id, &b11->receiver_id); p->destination = tal_dup(p, struct node_id, &b11->receiver_id);
p->destination_has_tlv =
feature_offered(b11->features, OPT_VAR_ONION);
p->payment_hash = tal_dup(p, struct sha256, &b11->payment_hash); p->payment_hash = tal_dup(p, struct sha256, &b11->payment_hash);
p->payment_secret = p->payment_secret =
tal_dup_or_null(p, struct secret, b11->payment_secret); tal_dup_or_null(p, struct secret, b11->payment_secret);
@@ -2420,7 +2418,6 @@ static struct command_result *json_paymod(struct command *cmd,
p->destination = tal(p, struct node_id); p->destination = tal(p, struct node_id);
gossmap_guess_node_id(get_gossmap(cmd->plugin), b12->node_id, gossmap_guess_node_id(get_gossmap(cmd->plugin), b12->node_id,
p->destination); p->destination);
p->destination_has_tlv = true;
p->payment_hash = tal_dup(p, struct sha256, b12->payment_hash); p->payment_hash = tal_dup(p, struct sha256, b12->payment_hash);
if (b12->recurrence_counter && !label) if (b12->recurrence_counter && !label)
return command_fail( return command_fail(

View File

@@ -94,21 +94,6 @@ static bool can_carry(const struct gossmap *map,
return true; return true;
} }
static void json_add_route_hop_style(struct json_stream *response,
const char *fieldname,
enum route_hop_style style)
{
switch (style) {
case ROUTE_HOP_LEGACY:
json_add_string(response, fieldname, "legacy");
return;
case ROUTE_HOP_TLV:
json_add_string(response, fieldname, "tlv");
return;
}
abort();
}
/* Output a route hop */ /* Output a route hop */
static void json_add_route_hop(struct json_stream *js, static void json_add_route_hop(struct json_stream *js,
const char *fieldname, const char *fieldname,
@@ -121,7 +106,7 @@ static void json_add_route_hop(struct json_stream *js,
json_add_num(js, "direction", r->direction); json_add_num(js, "direction", r->direction);
json_add_amount_msat_compat(js, r->amount, "msatoshi", "amount_msat"); json_add_amount_msat_compat(js, r->amount, "msatoshi", "amount_msat");
json_add_num(js, "delay", r->delay); json_add_num(js, "delay", r->delay);
json_add_route_hop_style(js, "style", r->style); json_add_string(js, "style", "tlv");
json_object_end(js); json_object_end(js);
} }

View File

@@ -46,7 +46,9 @@ def test_onion(directory, oniontool):
out = subprocess.check_output([oniontool, 'decode', tempfile, pk]).decode('ASCII').strip().split('\n') out = subprocess.check_output([oniontool, 'decode', tempfile, pk]).decode('ASCII').strip().split('\n')
store_onion(out[-1][5:]) store_onion(out[-1][5:])
assert(out == ['payload=000000000000000000000000000000000400000004000000000000000000000000']) # Final payload:
# amt_to_forward=4,outgoing_cltv_value=4
assert(out == ['payload=06020104040104'])
def test_rendezvous_onion(directory, oniontool): def test_rendezvous_onion(directory, oniontool):
@@ -82,4 +84,6 @@ def test_rendezvous_onion(directory, oniontool):
out = subprocess.check_output([oniontool, 'decode', tempfile, pk]).decode('ASCII').strip().split('\n') out = subprocess.check_output([oniontool, 'decode', tempfile, pk]).decode('ASCII').strip().split('\n')
store_onion(out[-1][5:]) store_onion(out[-1][5:])
assert(out == ['payload=000000000000000000000000000000000400000004000000000000000000000000']) # Final payload:
# amt_to_forward=4,outgoing_cltv_value=4
assert(out == ['payload=06020104040104'])

View File

@@ -40,11 +40,6 @@ void get_channel_basepoints(struct lightningd *ld UNNEEDED,
struct basepoints *local_basepoints UNNEEDED, struct basepoints *local_basepoints UNNEEDED,
struct pubkey *local_funding_pubkey UNNEEDED) struct pubkey *local_funding_pubkey UNNEEDED)
{ fprintf(stderr, "get_channel_basepoints called!\n"); abort(); } { fprintf(stderr, "get_channel_basepoints called!\n"); abort(); }
/* Generated stub for new_log */
struct log *new_log(const tal_t *ctx UNNEEDED, struct log_book *record UNNEEDED,
const struct node_id *default_node_id UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "new_log called!\n"); abort(); }
/* Generated stub for towire_hsmd_get_channel_basepoints */ /* Generated stub for towire_hsmd_get_channel_basepoints */
u8 *towire_hsmd_get_channel_basepoints(const tal_t *ctx UNNEEDED, const struct node_id *peerid UNNEEDED, u64 dbid UNNEEDED) u8 *towire_hsmd_get_channel_basepoints(const tal_t *ctx UNNEEDED, const struct node_id *peerid UNNEEDED, u64 dbid UNNEEDED)
{ fprintf(stderr, "towire_hsmd_get_channel_basepoints called!\n"); abort(); } { fprintf(stderr, "towire_hsmd_get_channel_basepoints called!\n"); abort(); }