mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +01:00
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:
387
common/onion.c
387
common/onion.c
@@ -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,46 +37,35 @@ 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:
|
||||||
*
|
*
|
||||||
* The writer:
|
* The writer:
|
||||||
*...
|
*...
|
||||||
* - For every node:
|
* - For every node:
|
||||||
* - MUST include `amt_to_forward` and `outgoing_cltv_value`.
|
* - MUST include `amt_to_forward` and `outgoing_cltv_value`.
|
||||||
* - For every non-final node:
|
* - For every non-final node:
|
||||||
* - MUST include `short_channel_id`
|
* - MUST include `short_channel_id`
|
||||||
* - MUST NOT include `payment_data`
|
* - MUST NOT include `payment_data`
|
||||||
*/
|
*/
|
||||||
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,59 +73,46 @@ 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) {
|
/* BOLT #4:
|
||||||
struct tlv_tlv_payload *tlv = tlv_tlv_payload_new(tmpctx);
|
*
|
||||||
struct tlv_tlv_payload_payment_data tlv_pdata;
|
* 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:
|
if (payment_secret) {
|
||||||
*
|
tlv_pdata.payment_secret = *payment_secret;
|
||||||
* The writer:
|
tlv_pdata.total_msat = total_msat.millisatoshis; /* Raw: TLV convert */
|
||||||
*...
|
tlv->payment_data = &tlv_pdata;
|
||||||
* - 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 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,
|
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,138 +215,104 @@ 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) {
|
tlv = tlv_tlv_payload_new(p);
|
||||||
case ONION_V0_PAYLOAD:
|
if (!fromwire_tlv_payload(&cursor, &max, tlv))
|
||||||
p->type = ONION_V0_PAYLOAD;
|
goto fail;
|
||||||
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) {
|
if (!tlv_fields_valid(tlv->fields, accepted_extra_tlvs, failtlvpos)) {
|
||||||
p->total_msat = NULL;
|
*failtlvtype = tlv->fields[*failtlvpos].numtype;
|
||||||
} else {
|
goto fail;
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* You said it was a valid type! */
|
/* BOLT #4:
|
||||||
abort();
|
*
|
||||||
|
* 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:
|
fail:
|
||||||
tal_free(tlv);
|
tal_free(tlv);
|
||||||
tal_free(p);
|
tal_free(p);
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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? */
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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) {
|
json_add_string(s, "type", "tlv");
|
||||||
case ONION_V0_PAYLOAD:
|
|
||||||
json_add_string(s, "type", "legacy");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ONION_TLV_PAYLOAD:
|
|
||||||
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",
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,48 +1603,29 @@ 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) {
|
dst->tlv_payload = tlv_tlv_payload_new(cr->hops);
|
||||||
case ROUTE_HOP_LEGACY:
|
fields = &dst->tlv_payload->fields;
|
||||||
dst->legacy_payload = tal(cr->hops, struct legacy_payload);
|
tlvstream_set_tu64(fields, TLV_TLV_PAYLOAD_AMT_TO_FORWARD,
|
||||||
dst->legacy_payload->forward_amt = next->amount;
|
msat);
|
||||||
|
tlvstream_set_tu32(fields, TLV_TLV_PAYLOAD_OUTGOING_CLTV_VALUE,
|
||||||
|
cltv);
|
||||||
|
|
||||||
if (!final)
|
if (!final)
|
||||||
dst->legacy_payload->scid = next->scid;
|
tlvstream_set_short_channel_id(fields,
|
||||||
else
|
TLV_TLV_PAYLOAD_SHORT_CHANNEL_ID,
|
||||||
dst->legacy_payload->scid = all_zero_scid;
|
&next->scid);
|
||||||
|
|
||||||
dst->legacy_payload->outgoing_cltv = cltv;
|
if (payment_secret != NULL) {
|
||||||
break;
|
assert(final);
|
||||||
case ROUTE_HOP_TLV:
|
tlvstream_set_tlv_payload_data(
|
||||||
dst->tlv_payload = tlv_tlv_payload_new(cr->hops);
|
fields, payment_secret,
|
||||||
fields = &dst->tlv_payload->fields;
|
root->amount.millisatoshis); /* Raw: TLV payload generation*/
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,18 +1703,14 @@ 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);
|
tlv = tal_arr(tmpctx, u8, 0);
|
||||||
json_add_hex_talarr(req->js, "payload", payload);
|
towire_tlvstream_raw(&tlv, hop->tlv_payload->fields);
|
||||||
}else {
|
payload = tal_arr(tmpctx, u8, 0);
|
||||||
tlv = tal_arr(tmpctx, u8, 0);
|
towire_bigsize(&payload, tal_bytelen(tlv));
|
||||||
towire_tlvstream_raw(&tlv, hop->tlv_payload->fields);
|
towire(&payload, tlv, tal_bytelen(tlv));
|
||||||
payload = tal_arr(tmpctx, u8, 0);
|
json_add_hex_talarr(req->js, "payload", payload);
|
||||||
towire_bigsize(&payload, tal_bytelen(tlv));
|
tal_free(tlv);
|
||||||
towire(&payload, tlv, tal_bytelen(tlv));
|
|
||||||
json_add_hex_talarr(req->js, "payload", payload);
|
|
||||||
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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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'])
|
||||||
|
|||||||
@@ -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(); }
|
||||||
|
|||||||
Reference in New Issue
Block a user