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:
*
* ## Legacy `hop_data` payload format
* ### `tlv_payload` format
*
* The `hop_data` format is identified by a single `0x00`-byte length,
* for backward compatibility. Its payload is defined as:
*
* 1. type: `hop_data` (for `realm` 0)
* 2. data:
* * [`short_channel_id`:`short_channel_id`]
* * [`u64`:`amt_to_forward`]
* * [`u32`:`outgoing_cltv_value`]
* * [`12*byte`:`padding`]
* This is a more flexible format, which avoids the redundant
* `short_channel_id` field for the final node. It is formatted
* according to the Type-Length-Value format defined in [BOLT
* #1](01-messaging.md#type-length-value-format).
*/
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,
const struct tlv_tlv_payload *tlv)
{
@@ -58,46 +37,35 @@ static u8 *make_tlv_hop(const tal_t *ctx,
}
u8 *onion_nonfinal_hop(const tal_t *ctx,
bool use_tlv,
const struct short_channel_id *scid,
struct amount_msat forward,
u32 outgoing_cltv,
const struct pubkey *blinding,
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:
*
* The writer:
*...
* - For every node:
* - MUST include `amt_to_forward` and `outgoing_cltv_value`.
* - For every non-final node:
* - MUST include `short_channel_id`
* - MUST NOT include `payment_data`
*/
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);
/* BOLT #4:
*
* The writer:
*...
* - For every node:
* - MUST include `amt_to_forward` and `outgoing_cltv_value`.
* - For every non-final node:
* - MUST include `short_channel_id`
* - MUST NOT include `payment_data`
*/
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);
#if EXPERIMENTAL_FEATURES
tlv->blinding_point = cast_const(struct pubkey *, blinding);
tlv->encrypted_recipient_data = cast_const(u8 *, enctlv);
tlv->blinding_point = cast_const(struct pubkey *, blinding);
tlv->encrypted_recipient_data = cast_const(u8 *, enctlv);
#endif
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);
}
return make_tlv_hop(ctx, tlv);
}
u8 *onion_final_hop(const tal_t *ctx,
bool use_tlv,
struct amount_msat forward,
u32 outgoing_cltv,
struct amount_msat total_msat,
@@ -105,59 +73,46 @@ u8 *onion_final_hop(const tal_t *ctx,
const u8 *enctlv,
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! */
if (!payment_secret)
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:
*
* The writer:
*...
* - For every node:
* - MUST include `amt_to_forward` and `outgoing_cltv_value`.
*...
* - For the final node:
* - MUST NOT include `short_channel_id`
* - if the recipient provided `payment_secret`:
* - MUST include `payment_data`
* - MUST set `payment_secret` to the one provided
* - MUST set `total_msat` to the total amount it will send
*/
tlv->amt_to_forward = &forward.millisatoshis; /* Raw: TLV convert */
tlv->outgoing_cltv_value = &outgoing_cltv;
/* BOLT #4:
*
* The writer:
*...
* - For every node:
* - MUST include `amt_to_forward` and `outgoing_cltv_value`.
*...
* - For the final node:
* - MUST NOT include `short_channel_id`
* - if the recipient provided `payment_secret`:
* - MUST include `payment_data`
* - MUST set `payment_secret` to the one provided
* - MUST set `total_msat` to the total amount it will send
*/
tlv->amt_to_forward = &forward.millisatoshis; /* Raw: TLV convert */
tlv->outgoing_cltv_value = &outgoing_cltv;
if (payment_secret) {
tlv_pdata.payment_secret = *payment_secret;
tlv_pdata.total_msat = total_msat.millisatoshis; /* Raw: TLV convert */
tlv->payment_data = &tlv_pdata;
}
#if EXPERIMENTAL_FEATURES
tlv->blinding_point = cast_const(struct pubkey *, blinding);
tlv->encrypted_recipient_data = cast_const(u8 *, enctlv);
#endif
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);
if (payment_secret) {
tlv_pdata.payment_secret = *payment_secret;
tlv_pdata.total_msat = total_msat.millisatoshis; /* Raw: TLV convert */
tlv->payment_data = &tlv_pdata;
}
#if EXPERIMENTAL_FEATURES
tlv->blinding_point = cast_const(struct pubkey *, blinding);
tlv->encrypted_recipient_data = cast_const(u8 *, enctlv);
#endif
return make_tlv_hop(ctx, tlv);
}
/* Returns true if valid, and fills in type. */
/* Returns true if valid, and fills in len. */
static bool pull_payload_length(const u8 **cursor,
size_t *max,
bool has_realm,
enum onion_payload_type *type,
size_t *len)
{
/* *len will incorporate bytes we read from cursor */
@@ -172,19 +127,6 @@ static bool pull_payload_length(const u8 **cursor,
if (!cursor)
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:
* - `tlv_payload` format, identified by any length over `1`. In this
* 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;
}
if (type)
*type = ONION_TLV_PAYLOAD;
*len += (*cursor - start);
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,
bool *valid,
enum onion_payload_type *type)
bool *valid)
{
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 (!*valid)
@@ -276,138 +215,104 @@ struct onion_payload *onion_decode(const tal_t *ctx,
size_t max = tal_bytelen(cursor), len;
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);
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);
tlv = tlv_tlv_payload_new(p);
if (!fromwire_tlv_payload(&cursor, &max, tlv))
goto fail;
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);
if (!fromwire_tlv_payload(&cursor, &max, tlv))
goto fail;
if (!tlv_fields_valid(tlv->fields, accepted_extra_tlvs, failtlvpos)) {
*failtlvtype = tlv->fields[*failtlvpos].numtype;
goto fail;
}
/* BOLT #4:
*
* The reader:
* - MUST return an error if `amt_to_forward` or
* `outgoing_cltv_value` are not present.
*/
if (!tlv->amt_to_forward || !tlv->outgoing_cltv_value)
goto fail;
p->amt_to_forward = amount_msat(*tlv->amt_to_forward);
p->outgoing_cltv = *tlv->outgoing_cltv_value;
/* BOLT #4:
*
* The writer:
*...
* - For every non-final node:
* - MUST include `short_channel_id`
*/
if (rs->nextcase == ONION_FORWARD) {
if (!tlv->short_channel_id)
goto fail;
p->forward_channel = tal_dup(p, struct short_channel_id,
tlv->short_channel_id);
p->total_msat = NULL;
} else {
p->forward_channel = NULL;
/* 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);
}
p->payment_secret = NULL;
p->blinding = tal_dup_or_null(p, struct pubkey, blinding);
#if EXPERIMENTAL_FEATURES
if (!p->blinding) {
/* If we have no blinding, it could be in TLV. */
if (tlv->blinding_point) {
p->blinding =
tal_dup(p, struct pubkey,
tlv->blinding_point);
ecdh(p->blinding, &p->blinding_ss);
}
} else
p->blinding_ss = *blinding_ss;
if (p->blinding) {
/* If they give us a blinding and we're not terminal,
* we must have an enctlv. */
if (rs->nextcase == ONION_FORWARD) {
struct tlv_tlv_payload *ntlv;
if (!tlv->encrypted_recipient_data)
goto fail;
ntlv = decrypt_tlv(tmpctx,
&p->blinding_ss,
tlv->encrypted_recipient_data);
if (!ntlv)
goto fail;
/* Must override short_channel_id */
if (!ntlv->short_channel_id)
goto fail;
*p->forward_channel
= *ntlv->short_channel_id;
}
}
#endif /* EXPERIMENTAL_FEATURES */
if (tlv->payment_data) {
p->payment_secret = tal_dup(p, struct secret,
&tlv->payment_data->payment_secret);
tal_free(p->total_msat);
p->total_msat = tal(p, struct amount_msat);
*p->total_msat
= amount_msat(tlv->payment_data->total_msat);
}
p->tlv = tal_steal(p, tlv);
return p;
if (!tlv_fields_valid(tlv->fields, accepted_extra_tlvs, failtlvpos)) {
*failtlvtype = tlv->fields[*failtlvpos].numtype;
goto fail;
}
/* You said it was a valid type! */
abort();
/* BOLT #4:
*
* The reader:
* - MUST return an error if `amt_to_forward` or
* `outgoing_cltv_value` are not present.
*/
if (!tlv->amt_to_forward || !tlv->outgoing_cltv_value)
goto fail;
p->amt_to_forward = amount_msat(*tlv->amt_to_forward);
p->outgoing_cltv = *tlv->outgoing_cltv_value;
/* BOLT #4:
*
* The writer:
*...
* - For every non-final node:
* - MUST include `short_channel_id`
*/
if (rs->nextcase == ONION_FORWARD) {
if (!tlv->short_channel_id)
goto fail;
p->forward_channel = tal_dup(p, struct short_channel_id,
tlv->short_channel_id);
p->total_msat = NULL;
} else {
p->forward_channel = NULL;
/* 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);
}
p->payment_secret = NULL;
p->blinding = tal_dup_or_null(p, struct pubkey, blinding);
#if EXPERIMENTAL_FEATURES
if (!p->blinding) {
/* If we have no blinding, it could be in TLV. */
if (tlv->blinding_point) {
p->blinding =
tal_dup(p, struct pubkey,
tlv->blinding_point);
ecdh(p->blinding, &p->blinding_ss);
}
} else
p->blinding_ss = *blinding_ss;
if (p->blinding) {
/* If they give us a blinding and we're not terminal,
* we must have an enctlv. */
if (rs->nextcase == ONION_FORWARD) {
struct tlv_tlv_payload *ntlv;
if (!tlv->encrypted_recipient_data)
goto fail;
ntlv = decrypt_tlv(tmpctx,
&p->blinding_ss,
tlv->encrypted_recipient_data);
if (!ntlv)
goto fail;
/* Must override short_channel_id */
if (!ntlv->short_channel_id)
goto fail;
*p->forward_channel
= *ntlv->short_channel_id;
}
}
#endif /* EXPERIMENTAL_FEATURES */
if (tlv->payment_data) {
p->payment_secret = tal_dup(p, struct secret,
&tlv->payment_data->payment_secret);
tal_free(p->total_msat);
p->total_msat = tal(p, struct amount_msat);
*p->total_msat
= amount_msat(tlv->payment_data->total_msat);
}
p->tlv = tal_steal(p, tlv);
return p;
fail:
tal_free(tlv);
tal_free(p);

View File

@@ -6,14 +6,7 @@
struct route_step;
enum onion_payload_type {
ONION_V0_PAYLOAD = 0,
ONION_TLV_PAYLOAD = 1,
};
struct onion_payload {
enum onion_payload_type type;
struct amount_msat amt_to_forward;
u32 outgoing_cltv;
struct amount_msat *total_msat;
@@ -29,7 +22,6 @@ struct onion_payload {
};
u8 *onion_nonfinal_hop(const tal_t *ctx,
bool use_tlv,
const struct short_channel_id *scid,
struct amount_msat forward,
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! */
u8 *onion_final_hop(const tal_t *ctx,
bool use_tlv,
struct amount_msat forward,
u32 outgoing_cltv,
struct amount_msat total_msat,
@@ -52,7 +43,6 @@ u8 *onion_final_hop(const tal_t *ctx,
* @len: length of @raw_payload in bytes.
* @has_realm: used for HTLCs, where first byte 0 is magical.
* @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,
* 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,
bool has_realm,
bool *valid,
enum onion_payload_type *type);
bool *valid);
/**
* 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. */
next = gossmap_nth_node(gossmap, c, !(*hops)[num_hops].direction);
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. */
(*hops)[num_hops].blinding = NULL;

View File

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

View File

@@ -627,7 +627,7 @@ struct route_step *process_onionpacket(
payload_size = onion_payload_length(paddedheader,
tal_bytelen(msg->routinginfo),
has_realm,
&valid, NULL);
&valid);
/* Can't decode? Treat it as terminal. */
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 */
size_t onion_payload_length(const u8 *raw_payload UNNEEDED, size_t len UNNEEDED,
bool has_realm UNNEEDED,
bool *valid UNNEEDED,
enum onion_payload_type *type UNNEEDED)
bool *valid UNNEEDED)
{ fprintf(stderr, "onion_payload_length called!\n"); abort(); }
/* Generated stub for pubkey_from_node_id */
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 {
struct short_channel_id scid;
struct amount_msat amt;
bool use_tlv = streq(argv[1 + i] + klen, "/tlv");
/* FIXME: support secret and and total_msat */
memset(&scid, i, sizeof(scid));
@@ -79,14 +78,12 @@ static void do_generate(int argc, char **argv,
if (i == num_hops - 1)
sphinx_add_hop(sp, &path[i],
take(onion_final_hop(NULL,
use_tlv,
amt, i, amt,
NULL, NULL,
NULL)));
else
sphinx_add_hop(sp, &path[i],
take(onion_nonfinal_hop(NULL,
use_tlv,
&scid,
amt, i,
NULL,
@@ -273,7 +270,6 @@ static void runtest(const char *filename)
decodetok = json_get_member(buffer, toks, "decode");
json_for_each_arr(i, hop, decodetok) {
enum onion_payload_type type;
bool valid;
hexprivkey = json_strdup(ctx, buffer, hop);
@@ -284,9 +280,8 @@ static void runtest(const char *filename)
errx(1, "Error serializing message.");
onion_payload_length(step->raw_payload,
tal_bytelen(step->raw_payload),
true, &valid, &type);
true, &valid);
assert(valid);
printf(" Type: %d\n", type);
printf(" Payload: %s\n", tal_hex(ctx, step->raw_payload));
printf(" Next onion: %s\n", tal_hex(ctx, serialized));
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_in *hin;
struct tlv_tlv_payload *tlvs;
const struct tlv_tlv_payload *tlvs;
assert(tal_count(hset->htlcs) > 0);
/* Pick the first HTLC as representative for the entire set. */
hin = hset->htlcs[0];
if (hin->payload->type != ONION_TLV_PAYLOAD)
return;
tlvs = hin->payload->tlv;
json_array_start(stream, "extratlvs");

View File

@@ -751,18 +751,6 @@ static struct command_result *wait_payment(struct lightningd *ld,
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 */
static const u8 *send_onion(const tal_t *ctx, struct lightningd *ld,
const struct onionpacket *packet,
@@ -1126,7 +1114,7 @@ send_payment(struct lightningd *ld,
struct short_channel_id *channels;
struct sphinx_path *path;
struct pubkey pubkey;
bool final_tlv, ret;
bool ret;
u8 *onion;
/* 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,
take(onion_nonfinal_hop(NULL,
should_use_tlv(route[i].style),
&route[i + 1].scid,
route[i + 1].amount,
base_expiry + route[i + 1].delay,
@@ -1157,25 +1144,15 @@ send_payment(struct lightningd *ld,
ret = pubkey_from_node_id(&pubkey, &ids[i]);
assert(ret);
final_tlv = should_use_tlv(route[i].style);
/* BOLT #4:
* - Unless `node_announcement`, `init` message or the
* [BOLT #11](11-payment-encoding.md#tagged-fields) offers feature
* `var_onion_optin`:
* - MUST use the legacy payload format instead.
*/
/* In our case, we don't use it unless we also have a payment_secret;
* 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");
/* FIXME: This requirement is now obsolete, and we should remove it! */
onion = onion_final_hop(cmd,
final_tlv,
route[i].amount,
base_expiry + route[i].delay,
total_msat, route[i].blinding, route[i].enctlv,
@@ -1326,23 +1303,19 @@ AUTODATA(json_command, &sendonion_command);
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,
const char *name,
const char *buffer,
const jsmntok_t *tok,
enum route_hop_style **style)
int **unused)
{
*style = tal(cmd, enum route_hop_style);
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;
if (json_tok_streq(buffer, tok, "tlv")) {
return NULL;
}
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,
@@ -1366,7 +1339,7 @@ static struct command_result *param_route_hops(struct command *cmd,
unsigned *delay, *direction;
struct pubkey *blinding;
u8 *enctlv;
enum route_hop_style *style, default_style;
int *ignored;
if (!param(cmd, buffer, t,
/* 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),
/* Allowed (getroute supplies it) but ignored */
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("encrypted_recipient_data", param_bin_from_hex, &enctlv),
NULL))
@@ -1405,21 +1378,12 @@ static struct command_result *param_route_hops(struct command *cmd,
if (!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].node_id = *id;
(*hops)[i].delay = *delay;
(*hops)[i].scid = *channel;
(*hops)[i].blinding = blinding;
(*hops)[i].enctlv = enctlv;
(*hops)[i].style = style ? *style : default_style;
}
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);
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");
break;
}
json_add_string(s, "type", "tlv");
if (p->payload->forward_channel)
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;
/* On the root payment we perform the featurebit check. */
if (p->parent == NULL && p->step == PAYMENT_STEP_INITIALIZED) {
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) {
if (p->step == PAYMENT_STEP_FAILED) {
/* Now we can look at the error, and the failing node,
and determine whether they didn't like our
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_toks = params;
p->destination = tal_steal(p, destination);
p->destination_has_tlv = true;
p->payment_secret = NULL;
p->amount = *msat;
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);
tal_arr_expand(&parent->children, p);
p->destination = parent->destination;
p->destination_has_tlv = parent->destination_has_tlv;
p->amount = parent->amount;
p->label = parent->label;
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);
}
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,
const char *buffer,
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 *next,
bool final,
bool force_tlv,
struct secret *payment_secret)
{
struct createonion_request *cr = p->createonion_request;
@@ -1619,48 +1603,29 @@ static void payment_add_hop_onion_payload(struct payment *p,
u64 msat = next->amount.millisatoshis; /* Raw: TLV payload generation*/
struct tlv_field **fields;
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
* `next` are the instructions to include in the payload, which is
* 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;
switch (dst->style) {
case ROUTE_HOP_LEGACY:
dst->legacy_payload = tal(cr->hops, struct legacy_payload);
dst->legacy_payload->forward_amt = next->amount;
dst->tlv_payload = tlv_tlv_payload_new(cr->hops);
fields = &dst->tlv_payload->fields;
tlvstream_set_tu64(fields, TLV_TLV_PAYLOAD_AMT_TO_FORWARD,
msat);
tlvstream_set_tu32(fields, TLV_TLV_PAYLOAD_OUTGOING_CLTV_VALUE,
cltv);
if (!final)
dst->legacy_payload->scid = next->scid;
else
dst->legacy_payload->scid = all_zero_scid;
if (!final)
tlvstream_set_short_channel_id(fields,
TLV_TLV_PAYLOAD_SHORT_CHANNEL_ID,
&next->scid);
dst->legacy_payload->outgoing_cltv = cltv;
break;
case ROUTE_HOP_TLV:
dst->tlv_payload = tlv_tlv_payload_new(cr->hops);
fields = &dst->tlv_payload->fields;
tlvstream_set_tu64(fields, TLV_TLV_PAYLOAD_AMT_TO_FORWARD,
msat);
tlvstream_set_tu32(fields, TLV_TLV_PAYLOAD_OUTGOING_CLTV_VALUE,
cltv);
if (!final)
tlvstream_set_short_channel_id(fields,
TLV_TLV_PAYLOAD_SHORT_CHANNEL_ID,
&next->scid);
if (payment_secret != NULL) {
assert(final);
tlvstream_set_tlv_payload_data(
fields, payment_secret,
root->amount.millisatoshis); /* Raw: TLV payload generation*/
}
break;
if (payment_secret != NULL) {
assert(final);
tlvstream_set_tlv_payload_data(
fields, payment_secret,
root->amount.millisatoshis); /* Raw: TLV payload generation*/
}
}
@@ -1699,7 +1664,7 @@ static void payment_compute_onion_payloads(struct payment *p)
/* The message is destined for hop i, but contains fields for
* i+1 */
payment_add_hop_onion_payload(p, &cr->hops[i], &p->route[i],
&p->route[i + 1], false, false,
&p->route[i + 1], false,
NULL);
tal_append_fmt(&routetxt, "%s -> ",
type_to_string(tmpctx, struct short_channel_id,
@@ -1709,7 +1674,7 @@ static void payment_compute_onion_payloads(struct payment *p)
/* Final hop */
payment_add_hop_onion_payload(
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);
tal_append_fmt(&routetxt, "%s",
type_to_string(tmpctx, struct short_channel_id,
@@ -1738,18 +1703,14 @@ static void payment_sendonion(struct payment *p)
json_object_start(req->js, NULL);
struct createonion_hop *hop = &p->createonion_request->hops[i];
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);
towire_tlvstream_raw(&tlv, hop->tlv_payload->fields);
payload = tal_arr(tmpctx, u8, 0);
towire_bigsize(&payload, tal_bytelen(tlv));
towire(&payload, tlv, tal_bytelen(tlv));
json_add_hex_talarr(req->js, "payload", payload);
tal_free(tlv);
}
tlv = tal_arr(tmpctx, u8, 0);
towire_tlvstream_raw(&tlv, hop->tlv_payload->fields);
payload = tal_arr(tmpctx, u8, 0);
towire_bigsize(&payload, tal_bytelen(tlv));
towire(&payload, tlv, tal_bytelen(tlv));
json_add_hex_talarr(req->js, "payload", payload);
tal_free(tlv);
tal_free(payload);
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.style = ROUTE_HOP_LEGACY;
hop.scid = routehint[i].short_channel_id;
hop.amount = dest_amount;
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].direction = hint->scid.dir;
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,
"Found a direct channel (%s) with sufficient "
"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. */
size_t lastidx = tal_count(p->createonion_request->hops) - 1;
struct createonion_hop *hop = &p->createonion_request->hops[lastidx];
if (hop->style == ROUTE_HOP_TLV) {
struct tlv_field **fields = &hop->tlv_payload->fields;
tlvstream_set_tlv_payload_data(
struct tlv_field **fields = &hop->tlv_payload->fields;
tlvstream_set_tlv_payload_data(
fields, root->payment_secret,
root->amount.millisatoshis); /* Raw: onion payload */
}
} else if (p->step == PAYMENT_STEP_INITIALIZED) {
/* The presplitter only acts on the root and only in the first
* step. */
@@ -3708,12 +3665,10 @@ static void adaptive_splitter_cb(struct adaptive_split_mod_data *d, struct payme
* get the exact value through. */
size_t lastidx = tal_count(p->createonion_request->hops) - 1;
struct createonion_hop *hop = &p->createonion_request->hops[lastidx];
if (hop->style == ROUTE_HOP_TLV) {
struct tlv_field **fields = &hop->tlv_payload->fields;
tlvstream_set_tlv_payload_data(
struct tlv_field **fields = &hop->tlv_payload->fields;
tlvstream_set_tlv_payload_data(
fields, root->payment_secret,
root->amount.millisatoshis); /* Raw: onion payload */
}
} else if (p->step == PAYMENT_STEP_FAILED && !p->abort) {
if (amount_msat_greater(p->amount, MPP_ADAPTIVE_LOWER_LIMIT)) {
struct payment *a, *b;

View File

@@ -16,10 +16,7 @@ struct legacy_payload {
/* struct holding the information necessary to call createonion */
struct createonion_hop {
struct node_id pubkey;
enum route_hop_style style;
struct tlv_tlv_payload *tlv_payload;
struct legacy_payload *legacy_payload;
};
struct createonion_request {
@@ -176,8 +173,6 @@ struct payment {
/* Real destination we want to route to */
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. */
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_msat(buffer, amounttok, &dst->amount);
json_to_number(buffer, delaytok, &dst->delay);
dst->style = json_tok_streq(buffer, styletok, "legacy")
? ROUTE_HOP_LEGACY
: ROUTE_HOP_TLV;
return true;
}

View File

@@ -2371,8 +2371,6 @@ static struct command_result *json_paymod(struct command *cmd,
invexpiry = b11->timestamp + b11->expiry;
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_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);
gossmap_guess_node_id(get_gossmap(cmd->plugin), b12->node_id,
p->destination);
p->destination_has_tlv = true;
p->payment_hash = tal_dup(p, struct sha256, b12->payment_hash);
if (b12->recurrence_counter && !label)
return command_fail(

View File

@@ -94,21 +94,6 @@ static bool can_carry(const struct gossmap *map,
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 */
static void json_add_route_hop(struct json_stream *js,
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_amount_msat_compat(js, r->amount, "msatoshi", "amount_msat");
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);
}

View File

@@ -46,7 +46,9 @@ def test_onion(directory, oniontool):
out = subprocess.check_output([oniontool, 'decode', tempfile, pk]).decode('ASCII').strip().split('\n')
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):
@@ -82,4 +84,6 @@ def test_rendezvous_onion(directory, oniontool):
out = subprocess.check_output([oniontool, 'decode', tempfile, pk]).decode('ASCII').strip().split('\n')
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 pubkey *local_funding_pubkey UNNEEDED)
{ 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 */
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(); }