Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTLC blinded route support (EXPERIMENTAL) #3623

Merged
merged 10 commits into from
Apr 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions channeld/channel_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ msgdata,channel_offer_htlc,amount_msat,amount_msat,
msgdata,channel_offer_htlc,cltv_expiry,u32,
msgdata,channel_offer_htlc,payment_hash,sha256,
msgdata,channel_offer_htlc,onion_routing_packet,u8,1366
msgdata,channel_offer_htlc,blinding,?pubkey,

# Reply; synchronous since IDs have to increment.
msgtype,channel_offer_htlc_reply,1104
Expand Down
59 changes: 52 additions & 7 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,17 +621,29 @@ static void handle_peer_add_htlc(struct peer *peer, const u8 *msg)
u8 onion_routing_packet[TOTAL_PACKET_SIZE];
enum channel_add_err add_err;
struct htlc *htlc;
#if EXPERIMENTAL_FEATURES
struct tlv_update_add_tlvs *tlvs = tlv_update_add_tlvs_new(msg);
#endif
struct pubkey *blinding = NULL;

if (!fromwire_update_add_htlc(msg, &channel_id, &id, &amount,
&payment_hash, &cltv_expiry,
onion_routing_packet))
onion_routing_packet
#if EXPERIMENTAL_FEATURES
, tlvs
#endif
))
peer_failed(peer->pps,
&peer->channel_id,
"Bad peer_add_htlc %s", tal_hex(msg, msg));

#if EXPERIMENTAL_FEATURES
if (tlvs->blinding)
blinding = &tlvs->blinding->blinding;
#endif
add_err = channel_add_htlc(peer->channel, REMOTE, id, amount,
cltv_expiry, &payment_hash,
onion_routing_packet, &htlc, NULL);
onion_routing_packet, blinding, &htlc, NULL);
if (add_err != CHANNEL_ERR_ADD_OK)
peer_failed(peer->pps,
&peer->channel_id,
Expand Down Expand Up @@ -1115,6 +1127,11 @@ static void marshall_htlc_info(const tal_t *ctx,
memcpy(a.onion_routing_packet,
htlc->routing,
sizeof(a.onion_routing_packet));
if (htlc->blinding) {
a.blinding = htlc->blinding;
ecdh(a.blinding, &a.blinding_ss);
} else
a.blinding = NULL;
tal_arr_expand(added, a);
} else if (htlc->state == RCVD_REMOVE_COMMIT) {
if (htlc->r) {
Expand Down Expand Up @@ -2045,12 +2062,25 @@ static void resend_commitment(struct peer *peer, const struct changed_htlc *last
last[i].id);

if (h->state == SENT_ADD_COMMIT) {
#if EXPERIMENTAL_FEATURES
struct tlv_update_add_tlvs *tlvs;
if (h->blinding) {
tlvs = tlv_update_add_tlvs_new(tmpctx);
tlvs->blinding = tal(tlvs, struct tlv_update_add_tlvs_blinding);
tlvs->blinding->blinding = *h->blinding;
} else
tlvs = NULL;
#endif
u8 *msg = towire_update_add_htlc(NULL, &peer->channel_id,
h->id, h->amount,
&h->rhash,
abs_locktime_to_blocks(
&h->expiry),
h->routing);
h->routing
#if EXPERIMENTAL_FEATURES
, tlvs
#endif
);
sync_crypto_write(peer->pps, take(msg));
} else if (h->state == SENT_REMOVE_COMMIT) {
send_fail_or_fulfill(peer, h);
Expand Down Expand Up @@ -2660,19 +2690,30 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg)
const u8 *failwiremsg;
const char *failstr;
struct amount_sat htlc_fee;
struct pubkey *blinding;

if (!peer->funding_locked[LOCAL] || !peer->funding_locked[REMOTE])
status_failed(STATUS_FAIL_MASTER_IO,
"funding not locked for offer_htlc");

if (!fromwire_channel_offer_htlc(inmsg, &amount,
if (!fromwire_channel_offer_htlc(tmpctx, inmsg, &amount,
&cltv_expiry, &payment_hash,
onion_routing_packet))
onion_routing_packet, &blinding))
master_badmsg(WIRE_CHANNEL_OFFER_HTLC, inmsg);

#if EXPERIMENTAL_FEATURES
struct tlv_update_add_tlvs *tlvs;
if (blinding) {
tlvs = tlv_update_add_tlvs_new(tmpctx);
tlvs->blinding = tal(tlvs, struct tlv_update_add_tlvs_blinding);
tlvs->blinding->blinding = *blinding;
} else
tlvs = NULL;
#endif

e = channel_add_htlc(peer->channel, LOCAL, peer->htlc_id,
amount, cltv_expiry, &payment_hash,
onion_routing_packet, NULL, &htlc_fee);
onion_routing_packet, take(blinding), NULL, &htlc_fee);
status_debug("Adding HTLC %"PRIu64" amount=%s cltv=%u gave %s",
peer->htlc_id,
type_to_string(tmpctx, struct amount_msat, &amount),
Expand All @@ -2685,7 +2726,11 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg)
msg = towire_update_add_htlc(NULL, &peer->channel_id,
peer->htlc_id, amount,
&payment_hash, cltv_expiry,
onion_routing_packet);
onion_routing_packet
#if EXPERIMENTAL_FEATURES
, tlvs
#endif
);
sync_crypto_write(peer->pps, take(msg));
start_commit_timer(peer);
/* Tell the master. */
Expand Down
3 changes: 3 additions & 0 deletions channeld/channeld_htlc.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ struct htlc {

/* Routing information sent with this HTLC (outgoing only). */
const u8 *routing;

/* Blinding (optional). */
struct pubkey *blinding;
};

static inline bool htlc_has(const struct htlc *h, int flag)
Expand Down
13 changes: 11 additions & 2 deletions channeld/full_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ static enum channel_add_err add_htlc(struct channel *channel,
u32 cltv_expiry,
const struct sha256 *payment_hash,
const u8 routing[TOTAL_PACKET_SIZE],
const struct pubkey *blinding TAKES,
struct htlc **htlcp,
bool enforce_aggregate_limits,
struct amount_sat *htlc_fee)
Expand Down Expand Up @@ -479,6 +480,10 @@ static enum channel_add_err add_htlc(struct channel *channel,
}

htlc->rhash = *payment_hash;
if (blinding)
htlc->blinding = tal_dup(htlc, struct pubkey, blinding);
else
htlc->blinding = NULL;
htlc->failed = NULL;
htlc->r = NULL;
htlc->routing = tal_dup_arr(htlc, u8, routing, TOTAL_PACKET_SIZE, 0);
Expand Down Expand Up @@ -694,6 +699,7 @@ enum channel_add_err channel_add_htlc(struct channel *channel,
u32 cltv_expiry,
const struct sha256 *payment_hash,
const u8 routing[TOTAL_PACKET_SIZE],
const struct pubkey *blinding TAKES,
struct htlc **htlcp,
struct amount_sat *htlc_fee)
{
Expand All @@ -705,7 +711,8 @@ enum channel_add_err channel_add_htlc(struct channel *channel,
state = RCVD_ADD_HTLC;

return add_htlc(channel, state, id, amount, cltv_expiry,
payment_hash, routing, htlcp, true, htlc_fee);
payment_hash, routing, blinding,
htlcp, true, htlc_fee);
}

struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id)
Expand Down Expand Up @@ -1212,7 +1219,9 @@ bool channel_force_htlcs(struct channel *channel,
htlcs[i]->id, htlcs[i]->amount,
htlcs[i]->cltv_expiry,
&htlcs[i]->payment_hash,
htlcs[i]->onion_routing_packet, &htlc, false, NULL);
htlcs[i]->onion_routing_packet,
htlcs[i]->blinding,
&htlc, false, NULL);
if (e != CHANNEL_ERR_ADD_OK) {
status_broken("%s HTLC %"PRIu64" failed error %u",
htlc_state_owner(htlcs[i]->state) == LOCAL
Expand Down
2 changes: 2 additions & 0 deletions channeld/full_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ u32 actual_feerate(const struct channel *channel,
* @cltv_expiry: block number when HTLC can no longer be redeemed.
* @payment_hash: hash whose preimage can redeem HTLC.
* @routing: routing information (copied)
* @blinding: optional blinding information for this HTLC.
* @htlcp: optional pointer for resulting htlc: filled in if and only if CHANNEL_ERR_NONE.
*
* If this returns CHANNEL_ERR_NONE, the fee htlc was added and
Expand All @@ -105,6 +106,7 @@ enum channel_add_err channel_add_htlc(struct channel *channel,
u32 cltv_expiry,
const struct sha256 *payment_hash,
const u8 routing[TOTAL_PACKET_SIZE],
const struct pubkey *blinding TAKES,
struct htlc **htlcp,
struct amount_sat *htlc_fee);

Expand Down
5 changes: 3 additions & 2 deletions channeld/test/run-full_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ static const struct htlc **include_htlcs(struct channel *channel, enum side side
memset(&preimage, i, sizeof(preimage));
sha256(&hash, &preimage, sizeof(preimage));
e = channel_add_htlc(channel, sender, i, msatoshi, 500+i, &hash,
dummy_routing, NULL, NULL);
dummy_routing, NULL, NULL, NULL);
assert(e == CHANNEL_ERR_ADD_OK);
htlcs[i] = channel_get_htlc(channel, sender, i);
}
Expand Down Expand Up @@ -257,7 +257,8 @@ static void send_and_fulfill_htlc(struct channel *channel,
sha256(&rhash, &r, sizeof(r));

assert(channel_add_htlc(channel, sender, 1337, msatoshi, 900, &rhash,
dummy_routing, NULL, NULL) == CHANNEL_ERR_ADD_OK);
dummy_routing, NULL, NULL, NULL)
== CHANNEL_ERR_ADD_OK);

changed_htlcs = tal_arr(channel, const struct htlc *, 0);

Expand Down
7 changes: 7 additions & 0 deletions common/features.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ static const struct feature_style feature_styles[] = {
.copy_style = { [INIT_FEATURE] = FEATURE_REPRESENT,
[NODE_ANNOUNCE_FEATURE] = FEATURE_REPRESENT,
[CHANNEL_FEATURE] = FEATURE_REPRESENT_AS_OPTIONAL } },
#if EXPERIMENTAL_FEATURES
{ OPT_ONION_MESSAGES,
.copy_style = { [INIT_FEATURE] = FEATURE_REPRESENT,
[NODE_ANNOUNCE_FEATURE] = FEATURE_REPRESENT,
[BOLT11_FEATURE] = FEATURE_REPRESENT,
[CHANNEL_FEATURE] = FEATURE_REPRESENT_AS_OPTIONAL} },
#endif
};

static enum feature_copy_style feature_copy_style(u32 f, enum feature_place p)
Expand Down
7 changes: 7 additions & 0 deletions common/features.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,11 @@ u8 *featurebits_or(const tal_t *ctx, const u8 *f1 TAKES, const u8 *f2 TAKES);
#define OPT_BASIC_MPP 16
#define OPT_LARGE_CHANNELS 18

/* BOLT-9fc25cfd2895578c0b1ab701ebe6c1eb67a19623 #9:
*
* | 102/103 | `option_onion_messages` |... INC+ ...
*/
#if EXPERIMENTAL_FEATURES
#define OPT_ONION_MESSAGES 102
#endif
#endif /* LIGHTNING_COMMON_FEATURES_H */
29 changes: 28 additions & 1 deletion common/htlc_wire.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ struct existing_htlc *new_existing_htlc(const tal_t *ctx,
const struct sha256 *payment_hash,
u32 cltv_expiry,
const u8 onion_routing_packet[TOTAL_PACKET_SIZE],
const struct preimage *preimage,
const struct pubkey *blinding TAKES,
const struct preimage *preimage TAKES,
const struct failed_htlc *failed TAKES)
{
struct existing_htlc *existing = tal(ctx, struct existing_htlc);
Expand All @@ -47,6 +48,10 @@ struct existing_htlc *new_existing_htlc(const tal_t *ctx,
existing->payment_hash = *payment_hash;
memcpy(existing->onion_routing_packet, onion_routing_packet,
sizeof(existing->onion_routing_packet));
if (blinding)
existing->blinding = tal_dup(existing, struct pubkey, blinding);
else
existing->blinding = NULL;
if (preimage)
existing->payment_preimage
= tal_dup(existing, struct preimage, preimage);
Expand All @@ -70,6 +75,12 @@ void towire_added_htlc(u8 **pptr, const struct added_htlc *added)
towire_u32(pptr, added->cltv_expiry);
towire(pptr, added->onion_routing_packet,
sizeof(added->onion_routing_packet));
if (added->blinding) {
towire_bool(pptr, true);
towire_pubkey(pptr, added->blinding);
towire_secret(pptr, &added->blinding_ss);
} else
towire_bool(pptr, false);
}

void towire_existing_htlc(u8 **pptr, const struct existing_htlc *existing)
Expand All @@ -91,6 +102,11 @@ void towire_existing_htlc(u8 **pptr, const struct existing_htlc *existing)
towire_failed_htlc(pptr, existing->failed);
} else
towire_bool(pptr, false);
if (existing->blinding) {
towire_bool(pptr, true);
towire_pubkey(pptr, existing->blinding);
} else
towire_bool(pptr, false);
}

void towire_fulfilled_htlc(u8 **pptr, const struct fulfilled_htlc *fulfilled)
Expand Down Expand Up @@ -152,6 +168,12 @@ void fromwire_added_htlc(const u8 **cursor, size_t *max,
added->cltv_expiry = fromwire_u32(cursor, max);
fromwire(cursor, max, added->onion_routing_packet,
sizeof(added->onion_routing_packet));
if (fromwire_bool(cursor, max)) {
added->blinding = tal(added, struct pubkey);
fromwire_pubkey(cursor, max, added->blinding);
fromwire_secret(cursor, max, &added->blinding_ss);
} else
added->blinding = NULL;
}

struct existing_htlc *fromwire_existing_htlc(const tal_t *ctx,
Expand All @@ -175,6 +197,11 @@ struct existing_htlc *fromwire_existing_htlc(const tal_t *ctx,
existing->failed = fromwire_failed_htlc(existing, cursor, max);
else
existing->failed = NULL;
if (fromwire_bool(cursor, max)) {
existing->blinding = tal(existing, struct pubkey);
fromwire_pubkey(cursor, max, existing->blinding);
} else
existing->blinding = NULL;
return existing;
}

Expand Down
9 changes: 8 additions & 1 deletion common/htlc_wire.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ struct added_htlc {
struct sha256 payment_hash;
u32 cltv_expiry;
u8 onion_routing_packet[TOTAL_PACKET_SIZE];

/* If this is non-NULL, secret is the resulting shared secret */
struct pubkey *blinding;
struct secret blinding_ss;
};

/* This is how lightningd tells us about HTLCs which already exist at startup */
Expand All @@ -28,6 +32,8 @@ struct existing_htlc {
struct sha256 payment_hash;
u32 cltv_expiry;
u8 onion_routing_packet[TOTAL_PACKET_SIZE];
/* If this is non-NULL, this is blinding to send with (outgoing) HTLC */
struct pubkey *blinding;
/* If fulfilled, this is non-NULL */
struct preimage *payment_preimage;
/* If failed, this is set */
Expand Down Expand Up @@ -66,7 +72,8 @@ struct existing_htlc *new_existing_htlc(const tal_t *ctx,
const struct sha256 *payment_hash,
u32 cltv_expiry,
const u8 onion_routing_packet[TOTAL_PACKET_SIZE],
const struct preimage *preimage,
const struct pubkey *blinding TAKES,
const struct preimage *preimage TAKES,
const struct failed_htlc *failed TAKES);

struct failed_htlc *failed_htlc_dup(const tal_t *ctx, const struct failed_htlc *f TAKES);
Expand Down
Loading