From 4334d3680d04b4684419064d5857066125642eac Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 9 Mar 2022 06:52:22 +1030 Subject: [PATCH] lightningd: remove support for legacy onion format. As per proposal in https://github.com/lightning/bolts/pull/962 Signed-off-by: Rusty Russell Changelog-Removed: protocol: support for legacy onion format removed, since everyone supports the new one. --- common/onion.c | 357 ++++++++------------- common/onion.h | 13 +- common/route.c | 6 - common/route.h | 7 - common/sphinx.c | 2 +- common/test/run-sphinx-xor_cipher_stream.c | 3 +- devtools/onion.c | 7 +- lightningd/invoice.c | 4 +- lightningd/pay.c | 52 +-- lightningd/peer_htlcs.c | 10 +- plugins/keysend.c | 10 +- plugins/libplugin-pay.c | 103 ++---- plugins/libplugin-pay.h | 5 - plugins/libplugin.c | 3 - plugins/pay.c | 3 - plugins/topology.c | 17 +- tests/test_onion.py | 8 +- wallet/test/run-db.c | 5 - 18 files changed, 182 insertions(+), 433 deletions(-) diff --git a/common/onion.c b/common/onion.c index f8b09511eaad..37afa9ab69c8 100644 --- a/common/onion.c +++ b/common/onion.c @@ -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); -#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 { + /* 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 - if (blinding || enctlv) - return NULL; + tlv->blinding_point = cast_const(struct pubkey *, blinding); + tlv->encrypted_recipient_data = cast_const(u8 *, enctlv); #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 (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 - if (blinding || enctlv) - return NULL; + tlv->blinding_point = cast_const(struct pubkey *, blinding); + tlv->encrypted_recipient_data = cast_const(u8 *, enctlv); #endif - return make_v0_hop(ctx, &all_zero_scid, forward, outgoing_cltv); - } + 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 (!tlv_fields_valid(tlv->fields, accepted_extra_tlvs, failtlvpos)) { + *failtlvtype = tlv->fields[*failtlvpos].numtype; + 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); - } + /* 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; - /* If they somehow got an invalid onion this far, fail. */ - if (!cursor) - return tal_free(p); - p->tlv = NULL; - return p; + p->amt_to_forward = amount_msat(*tlv->amt_to_forward); + p->outgoing_cltv = *tlv->outgoing_cltv_value; - case ONION_TLV_PAYLOAD: - tlv = tlv_tlv_payload_new(p); - if (!fromwire_tlv_payload(&cursor, &max, tlv)) + /* 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); + } - if (!tlv_fields_valid(tlv->fields, accepted_extra_tlvs, failtlvpos)) { - *failtlvtype = tlv->fields[*failtlvpos].numtype; - goto fail; + 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; - /* 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; + 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; - p->amt_to_forward = amount_msat(*tlv->amt_to_forward); - p->outgoing_cltv = *tlv->outgoing_cltv_value; + if (!tlv->encrypted_recipient_data) + goto fail; - /* BOLT #4: - * - * The writer: - *... - * - For every non-final node: - * - MUST include `short_channel_id` - */ - if (rs->nextcase == ONION_FORWARD) { - if (!tlv->short_channel_id) + ntlv = decrypt_tlv(tmpctx, + &p->blinding_ss, + tlv->encrypted_recipient_data); + if (!ntlv) 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); + /* Must override short_channel_id */ + if (!ntlv->short_channel_id) + goto fail; -#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; - } + *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->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; - /* You said it was a valid type! */ - abort(); fail: tal_free(tlv); tal_free(p); diff --git a/common/onion.h b/common/onion.h index 44b10ab268bb..bf8c3c430b78 100644 --- a/common/onion.h +++ b/common/onion.h @@ -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. diff --git a/common/route.c b/common/route.c index f204518b7e3c..04d590643882 100644 --- a/common/route.c +++ b/common/route.c @@ -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; diff --git a/common/route.h b/common/route.h index 11963fdab231..f28b0d0730be 100644 --- a/common/route.h +++ b/common/route.h @@ -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? */ diff --git a/common/sphinx.c b/common/sphinx.c index 1eb4496ea77e..9c0064db48c6 100644 --- a/common/sphinx.c +++ b/common/sphinx.c @@ -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) { diff --git a/common/test/run-sphinx-xor_cipher_stream.c b/common/test/run-sphinx-xor_cipher_stream.c index dc1bd585c504..26781985b255 100644 --- a/common/test/run-sphinx-xor_cipher_stream.c +++ b/common/test/run-sphinx-xor_cipher_stream.c @@ -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) diff --git a/devtools/onion.c b/devtools/onion.c index d486ccbb4588..7b81a4f9ac57 100644 --- a/devtools/onion.c +++ b/devtools/onion.c @@ -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", diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 365826521799..45cc4922a813 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -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"); diff --git a/lightningd/pay.c b/lightningd/pay.c index 6889945c50bb..41f47f42c828 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -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; diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index cf910dfa2ba3..b95746590267 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -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", diff --git a/plugins/keysend.c b/plugins/keysend.c index 6fe37e76f3a7..5f1f80ad896b 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -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); diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 9595dc6092cb..dafa5b7669bd 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -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; diff --git a/plugins/libplugin-pay.h b/plugins/libplugin-pay.h index 4f045e252488..e1f14da44f73 100644 --- a/plugins/libplugin-pay.h +++ b/plugins/libplugin-pay.h @@ -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; diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 942c91822786..2e728f159c67 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -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; } diff --git a/plugins/pay.c b/plugins/pay.c index 95a3ee2ae596..56e05792de0d 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -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( diff --git a/plugins/topology.c b/plugins/topology.c index cca6f0cd9c16..12be328e57b1 100644 --- a/plugins/topology.c +++ b/plugins/topology.c @@ -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); } diff --git a/tests/test_onion.py b/tests/test_onion.py index dcafbbacdc16..9abff56698f0 100644 --- a/tests/test_onion.py +++ b/tests/test_onion.py @@ -46,7 +46,9 @@ def store_onion(o): 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 store_onion(o): 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']) diff --git a/wallet/test/run-db.c b/wallet/test/run-db.c index 966a0a9c8142..54d1a107b92e 100644 --- a/wallet/test/run-db.c +++ b/wallet/test/run-db.c @@ -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(); }