Browse Source

sphinx: separate nonfinal from final interface, add tlv option.

For legacy, they were the same, but for TLV we care whether it's the
final hop or not.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
travis-debug
Rusty Russell 5 years ago
committed by Christian Decker
parent
commit
0211712f5e
  1. 74
      common/sphinx.c
  2. 19
      common/sphinx.h
  3. 6
      common/test/run-sphinx.c
  4. 34
      lightningd/pay.c

74
common/sphinx.c

@ -149,6 +149,80 @@ void sphinx_add_v0_hop(struct sphinx_path *path, const struct pubkey *pubkey,
sphinx_add_raw_hop(path, pubkey, 0, buf);
}
static void sphinx_add_tlv_hop(struct sphinx_path *path,
const struct pubkey *pubkey,
const struct tlv_tlv_payload *tlv)
{
u8 *tlvs = tal_arr(path, u8, 0);
towire_tlvs(&tlvs, tlvs_tlv_payload, TLVS_TLV_PAYLOAD_ARRAY_SIZE, tlv);
sphinx_add_raw_hop(path, pubkey, tal_bytelen(tlvs), tlvs);
}
void sphinx_add_nonfinal_hop(struct sphinx_path *path,
const struct pubkey *pubkey,
bool use_tlv,
const struct short_channel_id *scid,
struct amount_msat forward,
u32 outgoing_cltv)
{
if (use_tlv) {
struct tlv_tlv_payload *tlv = tlv_tlv_payload_new(tmpctx);
struct tlv_tlv_payload_amt_to_forward tlv_amt;
struct tlv_tlv_payload_outgoing_cltv_value tlv_cltv;
struct tlv_tlv_payload_short_channel_id tlv_scid;
/* BOLT #4:
*
* The writer:
* - MUST include `amt_to_forward` and `outgoing_cltv_value`
* for every node.
* - MUST include `short_channel_id` for every non-final node.
*/
tlv_amt.amt_to_forward = forward.millisatoshis; /* Raw: TLV convert */
tlv_cltv.outgoing_cltv_value = outgoing_cltv;
tlv_scid.short_channel_id = *scid;
tlv->amt_to_forward = &tlv_amt;
tlv->outgoing_cltv_value = &tlv_cltv;
tlv->short_channel_id = &tlv_scid;
sphinx_add_tlv_hop(path, pubkey, tlv);
} else {
sphinx_add_v0_hop(path, pubkey, scid, forward, outgoing_cltv);
}
}
void sphinx_add_final_hop(struct sphinx_path *path,
const struct pubkey *pubkey,
bool use_tlv,
struct amount_msat forward,
u32 outgoing_cltv)
{
if (use_tlv) {
struct tlv_tlv_payload *tlv = tlv_tlv_payload_new(tmpctx);
struct tlv_tlv_payload_amt_to_forward tlv_amt;
struct tlv_tlv_payload_outgoing_cltv_value tlv_cltv;
/* BOLT #4:
*
* The writer:
* - MUST include `amt_to_forward` and `outgoing_cltv_value`
* for every node.
*...
* - MUST NOT include `short_channel_id` for the final node.
*/
tlv_amt.amt_to_forward = forward.millisatoshis; /* Raw: TLV convert */
tlv_cltv.outgoing_cltv_value = outgoing_cltv;
tlv->amt_to_forward = &tlv_amt;
tlv->outgoing_cltv_value = &tlv_cltv;
sphinx_add_tlv_hop(path, pubkey, tlv);
} else {
static struct short_channel_id all_zero_scid;
sphinx_add_v0_hop(path, pubkey, &all_zero_scid,
forward, outgoing_cltv);
}
}
/* Small helper to append data to a buffer and update the position
* into the buffer
*/

19
common/sphinx.h

@ -231,6 +231,25 @@ void sphinx_add_v0_hop(struct sphinx_path *path, const struct pubkey *pubkey,
void sphinx_add_raw_hop(struct sphinx_path *path, const struct pubkey *pubkey,
enum sphinx_payload_type type, const u8 *payload);
/**
* Add a non-final hop to the path.
*/
void sphinx_add_nonfinal_hop(struct sphinx_path *path,
const struct pubkey *pubkey,
bool use_tlv,
const struct short_channel_id *scid,
struct amount_msat forward,
u32 outgoing_cltv);
/**
* Add a final hop to the path.
*/
void sphinx_add_final_hop(struct sphinx_path *path,
const struct pubkey *pubkey,
bool use_tlv,
struct amount_msat forward,
u32 outgoing_cltv);
/**
* Helper to extract fields from ONION_END.
*/

6
common/test/run-sphinx.c

@ -99,6 +99,12 @@ void towire_sha256(u8 **pptr UNNEEDED, const struct sha256 *sha256 UNNEEDED)
void towire_short_channel_id(u8 **pptr UNNEEDED,
const struct short_channel_id *short_channel_id UNNEEDED)
{ fprintf(stderr, "towire_short_channel_id called!\n"); abort(); }
/* Generated stub for towire_tlvs */
void towire_tlvs(u8 **pptr UNNEEDED,
const struct tlv_record_type types[] UNNEEDED,
size_t num_types UNNEEDED,
const void *record UNNEEDED)
{ fprintf(stderr, "towire_tlvs called!\n"); abort(); }
/* Generated stub for towire_tu32 */
void towire_tu32(u8 **pptr UNNEEDED, u32 v UNNEEDED)
{ fprintf(stderr, "towire_tu32 called!\n"); abort(); }

34
lightningd/pay.c

@ -615,6 +615,20 @@ 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:
#if EXPERIMENTAL_FEATURES
return true;
#endif
/* Otherwise fall thru */
case ROUTE_HOP_LEGACY:
return false;
}
abort();
}
/* Returns command_result if cmd was resolved, NULL if not yet called. */
static struct command_result *
send_payment(struct lightningd *ld,
@ -639,13 +653,11 @@ send_payment(struct lightningd *ld,
struct routing_failure *fail;
struct channel *channel;
struct sphinx_path *path;
struct short_channel_id finalscid;
struct pubkey pubkey;
bool ret;
/* Expiry for HTLCs is absolute. And add one to give some margin. */
base_expiry = get_block_height(ld->topology) + 1;
memset(&finalscid, 0, sizeof(struct short_channel_id));
path = sphinx_path_new(tmpctx, rhash->u.u8);
/* Extract IDs for each hop: create_onionpacket wants array. */
@ -656,19 +668,23 @@ send_payment(struct lightningd *ld,
for (i = 0; i < n_hops - 1; i++) {
ret = pubkey_from_node_id(&pubkey, &ids[i]);
assert(ret);
sphinx_add_v0_hop(path, &pubkey, &route[i + 1].channel_id,
route[i + 1].amount,
base_expiry + route[i + 1].delay);
sphinx_add_nonfinal_hop(path, &pubkey,
should_use_tlv(route[i].style),
&route[i + 1].channel_id,
route[i + 1].amount,
base_expiry + route[i + 1].delay);
}
/* And finally set the final hop to the special values in
* BOLT04 */
memset(&finalscid, 0, sizeof(struct short_channel_id));
ret = pubkey_from_node_id(&pubkey, &ids[i]);
assert(ret);
sphinx_add_v0_hop(path, &pubkey, &finalscid,
route[i].amount,
base_expiry + route[i].delay);
sphinx_add_final_hop(path, &pubkey,
should_use_tlv(route[i].style),
route[i].amount,
base_expiry + route[i].delay);
/* Now, do we already have a payment? */
payment = wallet_payment_by_hash(tmpctx, ld->wallet, rhash);

Loading…
Cancel
Save