Browse Source

channeld: support HTLCs with blinding (EXPERIMENTAL_FEATURES)

Note that it's channeld which calculates the shared secret, too.  This
minimizes the work that lightningd has to do, at cost of passing this
through.

We also don't yet save the blinding field(s) to the database.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
travis-debug
Rusty Russell 5 years ago
parent
commit
b29d1ed3ff
  1. 1
      channeld/channel_wire.csv
  2. 42
      channeld/channeld.c
  3. 3
      channeld/channeld_htlc.h
  4. 13
      channeld/full_channel.c
  5. 2
      channeld/full_channel.h
  6. 5
      channeld/test/run-full_channel.c
  7. 29
      common/htlc_wire.c
  8. 9
      common/htlc_wire.h
  9. 3
      connectd/test/run-responder-success.c
  10. 1
      lightningd/Makefile
  11. 12
      lightningd/htlc_end.c
  12. 11
      lightningd/htlc_end.h
  13. 17
      lightningd/pay.c
  14. 116
      lightningd/peer_htlcs.c
  15. 1
      lightningd/peer_htlcs.h
  16. 8
      lightningd/test/run-invoice-select-inchan.c
  17. 38
      wallet/test/run-wallet.c
  18. 4
      wallet/wallet.c
  19. 2
      wire/extracted_peer_experimental_add_htlc-plus-blinding

1
channeld/channel_wire.csv

@ -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

Can't render this file because it has a wrong number of fields in line 9.

42
channeld/channeld.c

@ -624,6 +624,7 @@ static void handle_peer_add_htlc(struct peer *peer, const u8 *msg)
#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,
@ -636,9 +637,13 @@ static void handle_peer_add_htlc(struct peer *peer, const u8 *msg)
&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,
@ -1122,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) {
@ -2052,6 +2062,15 @@ 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,
@ -2059,7 +2078,7 @@ static void resend_commitment(struct peer *peer, const struct changed_htlc *last
&h->expiry),
h->routing
#if EXPERIMENTAL_FEATURES
, NULL
, tlvs
#endif
);
sync_crypto_write(peer->pps, take(msg));
@ -2671,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),
@ -2698,7 +2728,7 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg)
&payment_hash, cltv_expiry,
onion_routing_packet
#if EXPERIMENTAL_FEATURES
, NULL
, tlvs
#endif
);
sync_crypto_write(peer->pps, take(msg));

3
channeld/channeld_htlc.h

@ -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)

13
channeld/full_channel.c

@ -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)
@ -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);
@ -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)
{
@ -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)
@ -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

2
channeld/full_channel.h

@ -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
@ -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);

5
channeld/test/run-full_channel.c

@ -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);
}
@ -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);

29
common/htlc_wire.c

@ -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);
@ -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);
@ -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)
@ -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)
@ -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,
@ -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;
}

9
common/htlc_wire.h

@ -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 */
@ -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 */
@ -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);

3
connectd/test/run-responder-success.c

@ -40,9 +40,6 @@ u8 *fromwire_tal_arrn(const tal_t *ctx UNNEEDED,
/* Generated stub for fromwire_u16 */
u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u16 called!\n"); abort(); }
/* Generated stub for notleak_ */
void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)
{ fprintf(stderr, "notleak_ called!\n"); abort(); }
/* Generated stub for towire_u16 */
void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED)
{ fprintf(stderr, "towire_u16 called!\n"); abort(); }

1
lightningd/Makefile

@ -22,6 +22,7 @@ LIGHTNINGD_COMMON_OBJS := \
common/bech32_util.o \
common/bigsize.o \
common/bip32.o \
common/blinding.o \
common/bolt11.o \
common/channel_config.o \
common/configdir.o \

12
lightningd/htlc_end.c

@ -130,6 +130,8 @@ struct htlc_in *new_htlc_in(const tal_t *ctx,
struct amount_msat msat, u32 cltv_expiry,
const struct sha256 *payment_hash,
const struct secret *shared_secret TAKES,
const struct pubkey *blinding TAKES,
const struct secret *blinding_ss,
const u8 *onion_routing_packet)
{
struct htlc_in *hin = tal(ctx, struct htlc_in);
@ -144,6 +146,11 @@ struct htlc_in *new_htlc_in(const tal_t *ctx,
hin->shared_secret = tal_dup(hin, struct secret, shared_secret);
else
hin->shared_secret = NULL;
if (blinding) {
hin->blinding = tal_dup(hin, struct pubkey, blinding);
hin->blinding_ss = *blinding_ss;
} else
hin->blinding = NULL;
memcpy(hin->onion_routing_packet, onion_routing_packet,
sizeof(hin->onion_routing_packet));
@ -267,6 +274,7 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
u32 cltv_expiry,
const struct sha256 *payment_hash,
const u8 *onion_routing_packet,
const struct pubkey *blinding,
bool am_origin,
u64 partid,
struct htlc_in *in)
@ -289,6 +297,10 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
hout->failonion = NULL;
hout->preimage = NULL;
if (blinding)
hout->blinding = tal_dup(hout, struct pubkey, blinding);
else
hout->blinding = NULL;
hout->am_origin = am_origin;
if (am_origin)
hout->partid = partid;

11
lightningd/htlc_end.h

@ -48,6 +48,11 @@ struct htlc_in {
/* Remember the timestamp we received this HTLC so we can later record
* it, and the resolution time, in the forwards table. */
struct timeabs received_time;
/* If it was blinded. */
struct pubkey *blinding;
/* Only set if blinding != NULL */
struct secret blinding_ss;
};
struct htlc_out {
@ -83,6 +88,9 @@ struct htlc_out {
/* Where it's from, if not going to us. */
struct htlc_in *in;
/* Blinding to send alongside, if any. */
struct pubkey *blinding;
};
static inline const struct htlc_key *keyof_htlc_in(const struct htlc_in *in)
@ -133,6 +141,8 @@ struct htlc_in *new_htlc_in(const tal_t *ctx,
struct amount_msat msat, u32 cltv_expiry,
const struct sha256 *payment_hash,
const struct secret *shared_secret TAKES,
const struct pubkey *blinding TAKES,
const struct secret *blinding_ss,
const u8 *onion_routing_packet);
/* You need to set the ID, then connect_htlc_out this! */
@ -142,6 +152,7 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
u32 cltv_expiry,
const struct sha256 *payment_hash,
const u8 *onion_routing_packet,
const struct pubkey *blinding,
bool am_origin,
u64 partid,
struct htlc_in *in);

17
lightningd/pay.c

@ -732,12 +732,13 @@ static bool should_use_tlv(enum route_hop_style style)
/* Returns failmsg on failure, tallocated off ctx */
static const u8 *send_onion(const tal_t *ctx, struct lightningd *ld,
const struct onionpacket *packet,
const struct route_hop *first_hop,
const struct sha256 *payment_hash,
u64 partid,
struct channel *channel,
struct htlc_out **hout)
const struct onionpacket *packet,
const struct route_hop *first_hop,
const struct sha256 *payment_hash,
const struct pubkey *blinding,
u64 partid,
struct channel *channel,
struct htlc_out **hout)
{
const u8 *onion;
unsigned int base_expiry;
@ -746,7 +747,7 @@ static const u8 *send_onion(const tal_t *ctx, struct lightningd *ld,
onion = serialize_onionpacket(tmpctx, packet);
return send_htlc_out(ctx, channel, first_hop->amount,
base_expiry + first_hop->delay,
payment_hash, partid, onion, NULL, hout,
payment_hash, blinding, partid, onion, NULL, hout,
&dont_care_about_channel_update);
}
@ -887,7 +888,7 @@ send_payment_core(struct lightningd *ld,
return command_failed(cmd, data);
}
failmsg = send_onion(tmpctx, ld, packet, first_hop, rhash, partid,
failmsg = send_onion(tmpctx, ld, packet, first_hop, rhash, NULL, partid,
channel, &hout);
if (failmsg) {

116
lightningd/peer_htlcs.c

@ -6,6 +6,8 @@
#include <ccan/mem/mem.h>
#include <ccan/tal/str/str.h>
#include <channeld/gen_channel_wire.h>
#include <common/blinding.h>
#include <common/ecdh.h>
#include <common/json_command.h>
#include <common/jsonrpc_errors.h>
#include <common/onion.h>
@ -204,7 +206,15 @@ static void fail_in_htlc(struct htlc_in *hin,
htlc_in_update_state(hin->key.channel, hin, SENT_REMOVE_HTLC);
htlc_in_check(hin, __func__);
failed_htlc = mk_failed_htlc(tmpctx, hin, hin->failonion);
#if EXPERIMENTAL_FEATURES
/* In a blinded path, all failures become invalid_onion_blinding */
if (hin->blinding) {
failed_htlc = mk_failed_htlc_badonion(tmpctx, hin,
WIRE_INVALID_ONION_BLINDING);
} else
#endif
failed_htlc = mk_failed_htlc(tmpctx, hin, hin->failonion);
tell_channeld_htlc_failed(hin, failed_htlc);
}
@ -599,6 +609,7 @@ const u8 *send_htlc_out(const tal_t *ctx,
struct channel *out,
struct amount_msat amount, u32 cltv,
const struct sha256 *payment_hash,
const struct pubkey *blinding,
u64 partid,
const u8 *onion_routing_packet,
struct htlc_in *in,
@ -631,7 +642,8 @@ const u8 *send_htlc_out(const tal_t *ctx,
/* Make peer's daemon own it, catch if it dies. */
*houtp = new_htlc_out(out->owner, out, amount, cltv,
payment_hash, onion_routing_packet, in == NULL,
payment_hash, onion_routing_packet,
blinding, in == NULL,
partid, in);
tal_add_destructor(*houtp, destroy_hout_subd_died);
@ -642,7 +654,7 @@ const u8 *send_htlc_out(const tal_t *ctx,
htlc_offer_timeout,
out);
msg = towire_channel_offer_htlc(out, amount, cltv, payment_hash,
onion_routing_packet);
onion_routing_packet, blinding);
subd_req(out->peer->ld, out->owner, take(msg), -1, 0, rcvd_htlc_reply,
*houtp);
@ -654,7 +666,8 @@ static void forward_htlc(struct htlc_in *hin,
struct amount_msat amt_to_forward,
u32 outgoing_cltv_value,
const struct short_channel_id *scid,
const u8 next_onion[TOTAL_PACKET_SIZE])
const u8 next_onion[TOTAL_PACKET_SIZE],
const struct pubkey *next_blinding)
{
const u8 *failmsg;
struct amount_msat fee;
@ -749,7 +762,7 @@ static void forward_htlc(struct htlc_in *hin,
failmsg = send_htlc_out(tmpctx, next, amt_to_forward,
outgoing_cltv_value, &hin->payment_hash,
0, next_onion, hin,
next_blinding, 0, next_onion, hin,
&hout, &needs_update_appended);
if (!failmsg)
return;
@ -775,6 +788,7 @@ struct htlc_accepted_hook_payload {
struct htlc_in *hin;
struct channel *channel;
struct lightningd *ld;
struct pubkey *next_blinding;
u8 *next_onion;
u64 failtlvtype;
size_t failtlvpos;
@ -988,7 +1002,8 @@ htlc_accepted_hook_callback(struct htlc_accepted_hook_payload *request,
request->payload->amt_to_forward,
request->payload->outgoing_cltv,
request->payload->forward_channel,
serialize_onionpacket(tmpctx, rs->next));
serialize_onionpacket(tmpctx, rs->next),
request->next_blinding);
} else
handle_localpay(hin,
request->payload->amt_to_forward,
@ -1015,6 +1030,35 @@ REGISTER_PLUGIN_HOOK(htlc_accepted, PLUGIN_HOOK_CHAIN,
htlc_accepted_hook_serialize,
struct htlc_accepted_hook_payload *);
/* Apply tweak to ephemeral key if blinding is non-NULL, then do ECDH */
static bool ecdh_maybe_blinding(const struct pubkey *ephemeral_key,
const struct pubkey *blinding,
const struct secret *blinding_ss,
struct secret *ss)
{
struct pubkey point = *ephemeral_key;
#if EXPERIMENTAL_FEATURES
if (blinding) {
struct secret hmac;
/* b(i) = HMAC256("blinded_node_id", ss(i)) * k(i) */
subkey_from_hmac("blinded_node_id", blinding_ss, &hmac);
/* We instead tweak the *ephemeral* key from the onion and use
* our normal privkey: since hsmd knows only how to ECDH with
* our real key */
if (secp256k1_ec_pubkey_tweak_mul(secp256k1_ctx,
&point.pubkey,
hmac.data) != 1) {
return false;
}
}
#endif /* EXPERIMENTAL_FEATURES */
ecdh(&point, ss);
return true;
}
/**
* Everyone is committed to this htlc of theirs
*
@ -1048,12 +1092,12 @@ static bool peer_accepted_htlc(const tal_t *ctx,
channel_internal_error(channel,
"peer_got_revoke unknown htlc %"PRIu64, id);
*failmsg = towire_temporary_node_failure(ctx);
return false;
goto fail;
}
if (!replay && !htlc_in_update_state(channel, hin, RCVD_ADD_ACK_REVOCATION)) {
*failmsg = towire_temporary_node_failure(ctx);
return false;
goto fail;
}
htlc_in_check(hin, __func__);
@ -1075,7 +1119,7 @@ static bool peer_accepted_htlc(const tal_t *ctx,
"Rejecting their htlc %"PRIu64
" since we're shutting down",
id);
return false;
goto fail;
}
/* BOLT #2:
@ -1099,7 +1143,7 @@ static bool peer_accepted_htlc(const tal_t *ctx,
" since onion is unparsable %s",
id, onion_type_name(*badonion));
/* Now we can fail it. */
return false;
goto fail;
}
rs = process_onionpacket(tmpctx, &op, hin->shared_secret,
@ -1109,16 +1153,17 @@ static bool peer_accepted_htlc(const tal_t *ctx,
*badonion = WIRE_INVALID_ONION_HMAC;
log_debug(channel->log,
"Rejecting their htlc %"PRIu64
" since onion is unprocessable %s",
id, onion_type_name(*badonion));
return false;
" since onion is unprocessable %s ss=%s",
id, onion_type_name(*badonion),
type_to_string(tmpctx, struct secret, hin->shared_secret));
goto fail;
}
hook_payload = tal(hin, struct htlc_accepted_hook_payload);
hook_payload->route_step = tal_steal(hook_payload, rs);
hook_payload->payload = onion_decode(hook_payload, rs,
NULL, NULL,
hin->blinding, &hin->blinding_ss,
&hook_payload->failtlvtype,
&hook_payload->failtlvpos);
hook_payload->ld = ld;
@ -1126,10 +1171,34 @@ static bool peer_accepted_htlc(const tal_t *ctx,
hook_payload->channel = channel;
hook_payload->next_onion = serialize_onionpacket(hook_payload, rs->next);
#if EXPERIMENTAL_FEATURES
/* We could have blinding from hin or from inside onion. */
if (hook_payload->payload && hook_payload->payload->blinding) {
struct sha256 sha;
blinding_hash_e_and_ss(hook_payload->payload->blinding,
&hook_payload->payload->blinding_ss,
&sha);
hook_payload->next_blinding = tal(hook_payload, struct pubkey);
blinding_next_pubkey(hook_payload->payload->blinding, &sha,
hook_payload->next_blinding);
} else
#endif
hook_payload->next_blinding = NULL;
plugin_hook_call_htlc_accepted(ld, hook_payload, hook_payload);
/* Falling through here is ok, after all the HTLC locked */
return true;
fail:
#if EXPERIMENTAL_FEATURES
/* In a blinded path, *all* failures are "invalid_onion_blinding" */
if (hin->blinding) {
*failmsg = tal_free(*failmsg);
*badonion = WIRE_INVALID_ONION_BLINDING;
}
#endif
return false;
}
static void fulfill_our_htlc_out(struct channel *channel, struct htlc_out *hout,
@ -1659,18 +1728,18 @@ static bool channel_added_their_htlc(struct channel *channel,
}
/* Do the work of extracting shared secret now if possible. */
/* FIXME: We do this *again* in peer_accepted_htlc! */
failcode = parse_onionpacket(added->onion_routing_packet,
sizeof(added->onion_routing_packet),
&op);
if (!failcode) {
/* Because wire takes struct pubkey. */
u8 *msg = towire_hsm_ecdh_req(tmpctx, &op.ephemeralkey);
if (!wire_sync_write(ld->hsm_fd, take(msg)))
fatal("Could not write to HSM: %s", strerror(errno));
msg = wire_sync_read(tmpctx, ld->hsm_fd);
if (!fromwire_hsm_ecdh_resp(msg, &shared_secret))
fatal("Reading ecdh response: %s", strerror(errno));
if (!ecdh_maybe_blinding(&op.ephemeralkey,
added->blinding, &added->blinding_ss,
&shared_secret)) {
log_debug(channel->log, "htlc %"PRIu64
": can't tweak pubkey", added->id);
return false;
}
}
/* This stays around even if we fail it immediately: it *is*
@ -1678,6 +1747,7 @@ static bool channel_added_their_htlc(struct channel *channel,
hin = new_htlc_in(channel, channel, added->id, added->amount,
added->cltv_expiry, &added->payment_hash,
failcode ? NULL : &shared_secret,
added->blinding, &added->blinding_ss,
added->onion_routing_packet);
/* Save an incoming htlc to the wallet */
@ -2006,6 +2076,7 @@ const struct existing_htlc **peer_htlcs(const tal_t *ctx,
hin->msat, &hin->payment_hash,
hin->cltv_expiry,
hin->onion_routing_packet,
hin->blinding,
hin->preimage,
f);
tal_arr_expand(&htlcs, existing);
@ -2037,6 +2108,7 @@ const struct existing_htlc **peer_htlcs(const tal_t *ctx,
hout->msat, &hout->payment_hash,
hout->cltv_expiry,
hout->onion_routing_packet,
hout->blinding,
hout->preimage,
f);
tal_arr_expand(&htlcs, existing);

1
lightningd/peer_htlcs.h

@ -46,6 +46,7 @@ const u8 *send_htlc_out(const tal_t *ctx,
struct channel *out,
struct amount_msat amount, u32 cltv,
const struct sha256 *payment_hash,
const struct pubkey *blinding,
u64 partid,
const u8 *onion_routing_packet,
struct htlc_in *in,

8
lightningd/test/run-invoice-select-inchan.c

@ -23,7 +23,7 @@ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED,
{ fprintf(stderr, "bitcoind_getutxout_ called!\n"); abort(); }
/* Generated stub for bolt11_decode */
struct bolt11 *bolt11_decode(const tal_t *ctx UNNEEDED, const char *str UNNEEDED,
const struct feature_set *fset UNNEEDED,
const struct feature_set *our_features UNNEEDED,
const char *description UNNEEDED, char **fail UNNEEDED)
{ fprintf(stderr, "bolt11_decode called!\n"); abort(); }
/* Generated stub for bolt11_encode_ */
@ -48,9 +48,6 @@ bool channel_tell_depth(struct lightningd *ld UNNEEDED,
const struct bitcoin_txid *txid UNNEEDED,
u32 depth UNNEEDED)
{ fprintf(stderr, "channel_tell_depth called!\n"); abort(); }
/* Generated stub for command_check_only */
bool command_check_only(const struct command *cmd UNNEEDED)
{ fprintf(stderr, "command_check_only called!\n"); abort(); }
/* Generated stub for command_fail */
struct command_result *command_fail(struct command *cmd UNNEEDED, errcode_t code UNNEEDED,
const char *fmt UNNEEDED, ...)
@ -103,9 +100,6 @@ void fatal(const char *fmt UNNEEDED, ...)
/* Generated stub for feature_is_set */
bool feature_is_set(const u8 *features UNNEEDED, size_t bit UNNEEDED)
{ fprintf(stderr, "feature_is_set called!\n"); abort(); }
/* Generated stub for featurebits_or */
u8 *featurebits_or(const tal_t *ctx UNNEEDED, const u8 *f1 TAKES UNNEEDED, const u8 *f2 TAKES UNNEEDED)
{ fprintf(stderr, "featurebits_or called!\n"); abort(); }
/* Generated stub for fixup_htlcs_out */
void fixup_htlcs_out(struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "fixup_htlcs_out called!\n"); abort(); }

38
wallet/test/run-wallet.c

@ -45,6 +45,16 @@ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED,
void *arg) UNNEEDED,
void *arg UNNEEDED)
{ fprintf(stderr, "bitcoind_getutxout_ called!\n"); abort(); }
/* Generated stub for blinding_hash_e_and_ss */
void blinding_hash_e_and_ss(const struct pubkey *e UNNEEDED,
const struct secret *ss UNNEEDED,
struct sha256 *sha UNNEEDED)
{ fprintf(stderr, "blinding_hash_e_and_ss called!\n"); abort(); }
/* Generated stub for blinding_next_pubkey */
bool blinding_next_pubkey(const struct pubkey *pk UNNEEDED,
const struct sha256 *h UNNEEDED,
struct pubkey *next UNNEEDED)
{ fprintf(stderr, "blinding_next_pubkey called!\n"); abort(); }
/* Generated stub for broadcast_tx */
void broadcast_tx(struct chain_topology *topo UNNEEDED,
struct channel *channel UNNEEDED, const struct bitcoin_tx *tx UNNEEDED,
@ -58,9 +68,6 @@ bool channel_tell_depth(struct lightningd *ld UNNEEDED,
const struct bitcoin_txid *txid UNNEEDED,
u32 depth UNNEEDED)
{ fprintf(stderr, "channel_tell_depth called!\n"); abort(); }
/* Generated stub for command_check_only */
bool command_check_only(const struct command *cmd UNNEEDED)
{ fprintf(stderr, "command_check_only called!\n"); abort(); }
/* Generated stub for command_fail */
struct command_result *command_fail(struct command *cmd UNNEEDED, errcode_t code UNNEEDED,
const char *fmt UNNEEDED, ...)
@ -91,6 +98,9 @@ struct onionreply *create_onionreply(const tal_t *ctx UNNEEDED,
void delay_then_reconnect(struct channel *channel UNNEEDED, u32 seconds_delay UNNEEDED,
const struct wireaddr_internal *addrhint TAKES UNNEEDED)
{ fprintf(stderr, "delay_then_reconnect called!\n"); abort(); }
/* Generated stub for ecdh */
void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED)
{ fprintf(stderr, "ecdh called!\n"); abort(); }
/* Generated stub for encode_scriptpubkey_to_addr */
char *encode_scriptpubkey_to_addr(const tal_t *ctx UNNEEDED,
const struct chainparams *chainparams UNNEEDED,
@ -123,9 +133,6 @@ bool fromwire_custommsg_in(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8
/* Generated stub for fromwire_gossip_get_stripped_cupdate_reply */
bool fromwire_gossip_get_stripped_cupdate_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **stripped_update UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_get_stripped_cupdate_reply called!\n"); abort(); }
/* Generated stub for fromwire_hsm_ecdh_resp */
bool fromwire_hsm_ecdh_resp(const void *p UNNEEDED, struct secret *ss UNNEEDED)
{ fprintf(stderr, "fromwire_hsm_ecdh_resp called!\n"); abort(); }
/* Generated stub for fromwire_hsm_sign_commitment_tx_reply */
bool fromwire_hsm_sign_commitment_tx_reply(const void *p UNNEEDED, struct bitcoin_signature *sig UNNEEDED)
{ fprintf(stderr, "fromwire_hsm_sign_commitment_tx_reply called!\n"); abort(); }
@ -342,15 +349,6 @@ char *json_strdup(const tal_t *ctx UNNEEDED, const char *buffer UNNEEDED, const
/* Generated stub for json_stream_success */
struct json_stream *json_stream_success(struct command *cmd UNNEEDED)
{ fprintf(stderr, "json_stream_success called!\n"); abort(); }
/* Generated stub for json_to_address_scriptpubkey */
enum address_parse_result json_to_address_scriptpubkey(const tal_t *ctx UNNEEDED,
const struct chainparams *chainparams UNNEEDED,
const char *buffer UNNEEDED,
const jsmntok_t *tok UNNEEDED, const u8 **scriptpubkey UNNEEDED)
{ fprintf(stderr, "json_to_address_scriptpubkey called!\n"); abort(); }
/* Generated stub for json_to_bool */
bool json_to_bool(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, bool *b UNNEEDED)
{ fprintf(stderr, "json_to_bool called!\n"); abort(); }
/* Generated stub for json_to_node_id */
bool json_to_node_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct node_id *id UNNEEDED)
@ -580,6 +578,11 @@ void subd_req_(const tal_t *ctx UNNEEDED,
/* Generated stub for subd_send_msg */
void subd_send_msg(struct subd *sd UNNEEDED, const u8 *msg_out UNNEEDED)
{ fprintf(stderr, "subd_send_msg called!\n"); abort(); }
/* Generated stub for subkey_from_hmac */
void subkey_from_hmac(const char *prefix UNNEEDED,
const struct secret *base UNNEEDED,
struct secret *key UNNEEDED)
{ fprintf(stderr, "subkey_from_hmac called!\n"); abort(); }
/* Generated stub for topology_add_sync_waiter_ */
void topology_add_sync_waiter_(const tal_t *ctx UNNEEDED,
struct chain_topology *topo UNNEEDED,
@ -609,7 +612,7 @@ u8 *towire_channel_got_commitsig_reply(const tal_t *ctx UNNEEDED)
u8 *towire_channel_got_revoke_reply(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_channel_got_revoke_reply called!\n"); abort(); }
/* Generated stub for towire_channel_offer_htlc */
u8 *towire_channel_offer_htlc(const tal_t *ctx UNNEEDED, struct amount_msat amount_msat UNNEEDED, u32 cltv_expiry UNNEEDED, const struct sha256 *payment_hash UNNEEDED, const u8 onion_routing_packet[1366])
u8 *towire_channel_offer_htlc(const tal_t *ctx UNNEEDED, struct amount_msat amount_msat UNNEEDED, u32 cltv_expiry UNNEEDED, const struct sha256 *payment_hash UNNEEDED, const u8 onion_routing_packet[1366] UNNEEDED, const struct pubkey *blinding UNNEEDED)
{ fprintf(stderr, "towire_channel_offer_htlc called!\n"); abort(); }
/* Generated stub for towire_channel_send_shutdown */
u8 *towire_channel_send_shutdown(const tal_t *ctx UNNEEDED, const u8 *shutdown_scriptpubkey UNNEEDED)
@ -652,9 +655,6 @@ u8 *towire_final_incorrect_htlc_amount(const tal_t *ctx UNNEEDED, struct amount_
/* Generated stub for towire_gossip_get_stripped_cupdate */
u8 *towire_gossip_get_stripped_cupdate(const tal_t *ctx UNNEEDED, const struct short_channel_id *channel_id UNNEEDED)
{ fprintf(stderr, "towire_gossip_get_stripped_cupdate called!\n"); abort(); }
/* Generated stub for towire_hsm_ecdh_req */
u8 *towire_hsm_ecdh_req(const tal_t *ctx UNNEEDED, const struct pubkey *point UNNEEDED)
{ fprintf(stderr, "towire_hsm_ecdh_req called!\n"); abort(); }
/* Generated stub for towire_hsm_sign_commitment_tx */
u8 *towire_hsm_sign_commitment_tx(const tal_t *ctx UNNEEDED, const struct node_id *peer_id UNNEEDED, u64 channel_dbid UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, const struct pubkey *remote_funding_key UNNEEDED, struct amount_sat funding_amount UNNEEDED)
{ fprintf(stderr, "towire_hsm_sign_commitment_tx called!\n"); abort(); }

4
wallet/wallet.c

@ -1812,6 +1812,8 @@ static bool wallet_stmt2htlc_in(struct channel *channel,
db_column_amount_msat(stmt, 2, &in->msat);
in->cltv_expiry = db_column_int(stmt, 3);
in->hstate = db_column_int(stmt, 4);
/* FIXME: save blinding in db !*/
in->blinding = NULL;
db_column_sha256(stmt, 5, &in->payment_hash);
@ -1884,6 +1886,8 @@ static bool wallet_stmt2htlc_out(struct wallet *wallet,
out->cltv_expiry = db_column_int(stmt, 3);
out->hstate = db_column_int(stmt, 4);
db_column_sha256(stmt, 5, &out->payment_hash);
/* FIXME: save blinding in db !*/
out->blinding = NULL;
if (!db_column_is_null(stmt, 6)) {
out->preimage = tal(out, struct preimage);

2
wire/extracted_peer_experimental_add_htlc-plus-blinding

@ -8,7 +8,7 @@ index 5a2a8c23f..7b26242e3 100644
msgdata,update_add_htlc,onion_routing_packet,byte,1366
+msgdata,update_add_htlc,tlvs,update_add_tlvs,
+tlvtype,update_add_tlvs,blinding,2
+tlvdata,update_add_tlvs,blinding,ecdh,byte,32
+tlvdata,update_add_tlvs,blinding,blinding,point,
msgtype,update_fulfill_htlc,130
msgdata,update_fulfill_htlc,channel_id,channel_id,
msgdata,update_fulfill_htlc,id,u64,

Loading…
Cancel
Save