diff --git a/lightningd/channel/channel.c b/lightningd/channel/channel.c index df629cb86..a11534c52 100644 --- a/lightningd/channel/channel.c +++ b/lightningd/channel/channel.c @@ -585,6 +585,36 @@ static struct io_plan *send_revocation(struct io_conn *conn, struct peer *peer) return peer_read_message(conn, &peer->pcs, peer_in); } +/* FIXME: We could do this earlier and call HSM async, for speed. */ +static void get_shared_secret(const struct htlc *htlc, + struct secret *shared_secret) +{ + tal_t *tmpctx = tal_tmpctx(htlc); + struct pubkey ephemeral; + struct onionpacket *op; + u8 *msg; + + /* We unwrap the onion now. */ + op = parse_onionpacket(tmpctx, htlc->routing, TOTAL_PACKET_SIZE); + if (!op) { + /* Return an invalid shared secret. */ + memset(shared_secret, 0, sizeof(*shared_secret)); + tal_free(tmpctx); + return; + } + + /* Because wire takes struct pubkey. */ + ephemeral.pubkey = op->ephemeralkey; + msg = towire_hsm_ecdh_req(tmpctx, &ephemeral); + if (!wire_sync_write(HSM_FD, msg)) + status_failed(WIRE_CHANNEL_HSM_FAILED, "Writing ecdh req"); + msg = wire_sync_read(tmpctx, HSM_FD); + /* Gives all-zero shares_secret if it was invalid. */ + if (!msg || !fromwire_hsm_ecdh_resp(msg, NULL, shared_secret)) + status_failed(WIRE_CHANNEL_HSM_FAILED, "Reading ecdh response"); + tal_free(tmpctx); +} + static u8 *got_commitsig_msg(const tal_t *ctx, u64 local_commit_index, const secp256k1_ecdsa_signature *commit_sig, @@ -596,10 +626,12 @@ static u8 *got_commitsig_msg(const tal_t *ctx, struct fulfilled_htlc *fulfilled; struct failed_htlc *failed; struct added_htlc *added; + struct secret *shared_secret; u8 *msg; changed = tal_arr(tmpctx, struct changed_htlc, 0); added = tal_arr(tmpctx, struct added_htlc, 0); + shared_secret = tal_arr(tmpctx, struct secret, 0); failed = tal_arr(tmpctx, struct failed_htlc, 0); fulfilled = tal_arr(tmpctx, struct fulfilled_htlc, 0); @@ -607,6 +639,7 @@ static u8 *got_commitsig_msg(const tal_t *ctx, const struct htlc *htlc = changed_htlcs[i]; if (htlc->state == RCVD_ADD_COMMIT) { struct added_htlc *a = tal_arr_append(&added); + struct secret *s = tal_arr_append(&shared_secret); a->id = htlc->id; a->amount_msat = htlc->msatoshi; a->payment_hash = htlc->rhash; @@ -614,6 +647,7 @@ static u8 *got_commitsig_msg(const tal_t *ctx, memcpy(a->onion_routing_packet, htlc->routing, sizeof(a->onion_routing_packet)); + get_shared_secret(htlc, s); } else if (htlc->state == RCVD_REMOVE_COMMIT) { if (htlc->r) { struct fulfilled_htlc *f; @@ -642,6 +676,7 @@ static u8 *got_commitsig_msg(const tal_t *ctx, commit_sig, htlc_sigs, added, + shared_secret, fulfilled, failed, changed); @@ -770,68 +805,28 @@ static struct io_plan *handle_peer_commit_sig(struct io_conn *conn, return io_wait(conn, peer, send_revocation, peer); } -static void add_htlc_with_ss(u64 **added_ids, struct secret **shared_secrets, - const struct htlc *htlc) -{ - tal_t *tmpctx = tal_tmpctx(*added_ids); - struct pubkey ephemeral; - struct onionpacket *op; - u8 *msg; - struct secret *ss = tal_arr_append(shared_secrets); - u64 *id = tal_arr_append(added_ids); - - *id = htlc->id; - - /* We unwrap the onion now. */ - /* FIXME: We could do this earlier and call HSM async, for speed. */ - op = parse_onionpacket(tmpctx, htlc->routing, TOTAL_PACKET_SIZE); - if (!op) { - /* Return an invalid shared secret. */ - memset(ss, 0, sizeof(*ss)); - tal_free(tmpctx); - return; - } - - /* Because wire takes struct pubkey. */ - ephemeral.pubkey = op->ephemeralkey; - msg = towire_hsm_ecdh_req(tmpctx, &ephemeral); - if (!wire_sync_write(HSM_FD, msg)) - status_failed(WIRE_CHANNEL_HSM_FAILED, "Writing ecdh req"); - msg = wire_sync_read(tmpctx, HSM_FD); - /* Gives all-zero shares_secret if it was invalid. */ - if (!msg || !fromwire_hsm_ecdh_resp(msg, NULL, ss)) - status_failed(WIRE_CHANNEL_HSM_FAILED, "Reading ecdh response"); - tal_free(tmpctx); -} - static u8 *got_revoke_msg(const tal_t *ctx, u64 revoke_num, const struct sha256 *per_commitment_secret, const struct htlc **changed_htlcs) { tal_t *tmpctx = tal_tmpctx(ctx); u8 *msg; - u64 *added_ids = tal_arr(tmpctx, u64, 0); - struct secret *shared_secrets = tal_arr(tmpctx, struct secret, 0); struct changed_htlc *changed = tal_arr(tmpctx, struct changed_htlc, 0); for (size_t i = 0; i < tal_count(changed_htlcs); i++) { + struct changed_htlc *c = tal_arr_append(&changed); const struct htlc *htlc = changed_htlcs[i]; + status_trace("HTLC %"PRIu64"[%s] => %s", htlc->id, side_to_str(htlc_owner(htlc)), htlc_state_name(htlc->state)); - /* We've both committed to their htlc now. */ - if (htlc->state == RCVD_ADD_ACK_REVOCATION) { - add_htlc_with_ss(&added_ids, &shared_secrets, htlc); - } else { - struct changed_htlc *c = tal_arr_append(&changed); - c->id = changed_htlcs[i]->id; - c->newstate = changed_htlcs[i]->state; - } + c->id = changed_htlcs[i]->id; + c->newstate = changed_htlcs[i]->state; } msg = towire_channel_got_revoke(ctx, revoke_num, per_commitment_secret, - added_ids, shared_secrets, changed); + changed); tal_free(tmpctx); return msg; } diff --git a/lightningd/channel/channel_wire.csv b/lightningd/channel/channel_wire.csv index 11463fdfc..f6735670c 100644 --- a/lightningd/channel/channel_wire.csv +++ b/lightningd/channel/channel_wire.csv @@ -108,6 +108,7 @@ channel_got_commitsig,,htlc_signature,num_htlcs*secp256k1_ecdsa_signature # RCVD_ADD_COMMIT: we're now committed to their new offered HTLCs. channel_got_commitsig,,num_added,u16 channel_got_commitsig,,added,num_added*struct added_htlc +channel_got_commitsig,,shared_secret,num_added*struct secret # RCVD_REMOVE_COMMIT: we're now no longer committed to these HTLCs. channel_got_commitsig,,num_fulfilled,u16 channel_got_commitsig,,fulfilled,num_fulfilled*struct fulfilled_htlc @@ -125,11 +126,7 @@ channel_got_commitsig_reply,121 channel_got_revoke,22 channel_got_revoke,,revokenum,u64 channel_got_revoke,,per_commitment_secret,struct sha256 -# RCVD_ADD_ACK_REVOCATION -channel_got_revoke,,num_added,u16 -channel_got_revoke,,added_ids,num_added*u64 -channel_got_revoke,,shared_secret,num_added*struct secret -# RCVD_REMOVE_ACK_REVOCATION, RCVD_ADD_REVOCATION, RCVD_REMOVE_REVOCATION +# RCVD_ADD_ACK_REVOCATION, RCVD_REMOVE_ACK_REVOCATION, RCVD_ADD_REVOCATION, RCVD_REMOVE_REVOCATION channel_got_revoke,,num_changed,u16 channel_got_revoke,,changed,num_changed*struct changed_htlc # Wait for reply, to make sure it's on disk before we continue diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 5dfbb97e1..b695b74c5 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -520,7 +520,6 @@ static bool htlc_out_update_state(struct peer *peer, /* Everyone is committed to this htlc of theirs */ static bool peer_accepted_htlc(struct peer *peer, u64 id, - const struct secret *shared_secret, enum onion_type *failcode) { struct htlc_in *hin; @@ -536,9 +535,6 @@ static bool peer_accepted_htlc(struct peer *peer, return false; } - /* We need to keep this to encrypt failure message replies anyway */ - hin->shared_secret = *shared_secret; - if (!htlc_in_update_state(peer, hin, RCVD_ADD_ACK_REVOCATION)) return false; @@ -546,7 +542,7 @@ static bool peer_accepted_htlc(struct peer *peer, op = parse_onionpacket(tmpctx, hin->onion_routing_packet, sizeof(hin->onion_routing_packet)); if (!op) { - if (!memeqzero(shared_secret, sizeof(*shared_secret))) { + if (!memeqzero(&hin->shared_secret, sizeof(hin->shared_secret))){ log_broken(peer->log, "bad onion in got_revoke: %s", tal_hexstr(peer, hin->onion_routing_packet, @@ -560,13 +556,13 @@ static bool peer_accepted_htlc(struct peer *peer, } /* Channeld sets this to zero if HSM won't ecdh it */ - if (memeqzero(shared_secret, sizeof(*shared_secret))) { + if (memeqzero(&hin->shared_secret, sizeof(hin->shared_secret))) { *failcode = WIRE_INVALID_ONION_KEY; goto out; } /* If it's crap, not channeld's fault, just fail it */ - rs = process_onionpacket(tmpctx, op, shared_secret->data, + rs = process_onionpacket(tmpctx, op, hin->shared_secret.data, hin->payment_hash.u.u8, sizeof(hin->payment_hash)); if (!rs) { @@ -780,17 +776,17 @@ int peer_sending_commitsig(struct peer *peer, const u8 *msg) return 0; } -static void added_their_htlc(struct peer *peer, const struct added_htlc *added) +static void added_their_htlc(struct peer *peer, + const struct added_htlc *added, + const struct secret *shared_secret) { struct htlc_in *hin; - static struct secret dummy; /* This stays around even if we fail it immediately: it *is* * part of the current commitment. */ hin = new_htlc_in(peer, peer, added->id, added->amount_msat, added->cltv_expiry, &added->payment_hash, - /* FIXME: have user pass shared_secret now */ - &dummy, added->onion_routing_packet); + shared_secret, added->onion_routing_packet); /* FIXME: Save to db */ @@ -851,6 +847,7 @@ int peer_got_commitsig(struct peer *peer, const u8 *msg) secp256k1_ecdsa_signature commit_sig; secp256k1_ecdsa_signature *htlc_sigs; struct added_htlc *added; + struct secret *shared_secrets; struct fulfilled_htlc *fulfilled; struct failed_htlc *failed; struct changed_htlc *changed; @@ -861,6 +858,7 @@ int peer_got_commitsig(struct peer *peer, const u8 *msg) &commit_sig, &htlc_sigs, &added, + &shared_secrets, &fulfilled, &failed, &changed)) { @@ -879,7 +877,7 @@ int peer_got_commitsig(struct peer *peer, const u8 *msg) /* New HTLCs */ for (i = 0; i < tal_count(added); i++) - added_their_htlc(peer, &added[i]); + added_their_htlc(peer, &added[i], &shared_secrets[i]); /* Save information now for fulfilled & failed HTLCs */ for (i = 0; i < tal_count(fulfilled); i++) { @@ -923,15 +921,12 @@ int peer_got_revoke(struct peer *peer, const u8 *msg) { u64 revokenum, shachainidx; struct sha256 per_commitment_secret; - u64 *added_ids; - struct secret *shared_secret; struct changed_htlc *changed; enum onion_type *failcodes; size_t i; if (!fromwire_channel_got_revoke(msg, msg, NULL, &revokenum, &per_commitment_secret, - &added_ids, &shared_secret, &changed)) { log_broken(peer->log, "bad fromwire_channel_got_revoke %s", tal_hex(peer, msg)); @@ -939,22 +934,23 @@ int peer_got_revoke(struct peer *peer, const u8 *msg) } log_debug(peer->log, - "got revoke %"PRIu64": %zu changed, %zu incoming locked in", - revokenum, - tal_count(changed), tal_count(added_ids)); + "got revoke %"PRIu64": %zu changed", + revokenum, tal_count(changed)); /* Save any immediate failures for after we reply. */ - failcodes = tal_arr(msg, enum onion_type, tal_count(added_ids)); - for (i = 0; i < tal_count(added_ids); i++) { - if (!peer_accepted_htlc(peer, added_ids[i], &shared_secret[i], - &failcodes[i])) - return -1; - } - + failcodes = tal_arrz(msg, enum onion_type, tal_count(changed)); for (i = 0; i < tal_count(changed); i++) { - if (!changed_htlc(peer, &changed[i])) { - log_broken(peer->log, "got_revoke: update failed"); - return -1; + /* If we're doing final accept, we need to forward */ + if (changed[i].newstate == RCVD_ADD_ACK_REVOCATION) { + if (!peer_accepted_htlc(peer, changed[i].id, + &failcodes[i])) + return -1; + } else { + if (!changed_htlc(peer, &changed[i])) { + log_broken(peer->log, + "got_revoke: update failed"); + return -1; + } } } @@ -996,14 +992,14 @@ int peer_got_revoke(struct peer *peer, const u8 *msg) subd_send_msg(peer->owner, take(msg)); /* Now, any HTLCs we need to immediately fail? */ - for (i = 0; i < tal_count(added_ids); i++) { + for (i = 0; i < tal_count(changed); i++) { struct sha256 bad_onion_sha; struct htlc_in *hin; if (!failcodes[i]) continue; - hin = find_htlc_in(&peer->ld->htlcs_in, peer, added_ids[i]); + hin = find_htlc_in(&peer->ld->htlcs_in, peer, changed[i].id); sha256(&bad_onion_sha, hin->onion_routing_packet, sizeof(hin->onion_routing_packet)); fail_htlc(hin, failcodes[i], &bad_onion_sha);