diff --git a/channeld/channel_wire.csv b/channeld/channel_wire.csv index a57f92ea3..3f36ac80e 100644 --- a/channeld/channel_wire.csv +++ b/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 diff --git a/channeld/channeld.c b/channeld/channeld.c index 8dbf09988..90c404bc9 100644 --- a/channeld/channeld.c +++ b/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)); diff --git a/channeld/channeld_htlc.h b/channeld/channeld_htlc.h index 482038bb3..2a14d5e37 100644 --- a/channeld/channeld_htlc.h +++ b/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) diff --git a/channeld/full_channel.c b/channeld/full_channel.c index c1ced3ee2..fe8cf2b2f 100644 --- a/channeld/full_channel.c +++ b/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 diff --git a/channeld/full_channel.h b/channeld/full_channel.h index 3485e039a..e7fa565c7 100644 --- a/channeld/full_channel.h +++ b/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); diff --git a/channeld/test/run-full_channel.c b/channeld/test/run-full_channel.c index 3c1564511..4a4c2f8b2 100644 --- a/channeld/test/run-full_channel.c +++ b/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); diff --git a/common/htlc_wire.c b/common/htlc_wire.c index fc8b68691..8064f3c82 100644 --- a/common/htlc_wire.c +++ b/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; } diff --git a/common/htlc_wire.h b/common/htlc_wire.h index 9809b14e1..6424bf897 100644 --- a/common/htlc_wire.h +++ b/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); diff --git a/connectd/test/run-responder-success.c b/connectd/test/run-responder-success.c index cd9410cb5..5657d1780 100644 --- a/connectd/test/run-responder-success.c +++ b/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(); } diff --git a/lightningd/Makefile b/lightningd/Makefile index 075bfe9a4..7d8444abd 100644 --- a/lightningd/Makefile +++ b/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 \ diff --git a/lightningd/htlc_end.c b/lightningd/htlc_end.c index 7489976ce..c41121f31 100644 --- a/lightningd/htlc_end.c +++ b/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; diff --git a/lightningd/htlc_end.h b/lightningd/htlc_end.h index c25f0625a..8d180e724 100644 --- a/lightningd/htlc_end.h +++ b/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); diff --git a/lightningd/pay.c b/lightningd/pay.c index 38e2e7171..3070a49b3 100644 --- a/lightningd/pay.c +++ b/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) { diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 4484559dc..d809ae15f 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include #include @@ -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); diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index 4a8329f54..02ed1c871 100644 --- a/lightningd/peer_htlcs.h +++ b/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, diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 2392f76f9..f0083949c 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/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(); } diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 7c29663c9..af28c9bee 100644 --- a/wallet/test/run-wallet.c +++ b/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(); } diff --git a/wallet/wallet.c b/wallet/wallet.c index 37edd2eae..2c2b0655f 100644 --- a/wallet/wallet.c +++ b/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); diff --git a/wire/extracted_peer_experimental_add_htlc-plus-blinding b/wire/extracted_peer_experimental_add_htlc-plus-blinding index 587971d89..8f0ba00c9 100644 --- a/wire/extracted_peer_experimental_add_htlc-plus-blinding +++ b/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,