From 1ca97a7913edbc323bd56c1cccdde60646f50d8c Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 20 Jun 2017 15:13:03 +0930 Subject: [PATCH] channeld: don't unpack union, leave that to master. We still get the shared secret, since that requires a round trip to the HSM (why waste the master daemon's time?) but it does the processing, which simplifies the message passing and things like realm handling which have nothing to do with this particular channeld. Signed-off-by: Rusty Russell --- lightningd/channel/channel.c | 28 ++---------------- lightningd/channel/channel_wire.csv | 7 ++--- lightningd/htlc_end.h | 2 +- lightningd/peer_control.c | 46 ++++++++++++++++++++++++----- 4 files changed, 43 insertions(+), 40 deletions(-) diff --git a/lightningd/channel/channel.c b/lightningd/channel/channel.c index 5cc81a20b..4b6e8acd3 100644 --- a/lightningd/channel/channel.c +++ b/lightningd/channel/channel.c @@ -591,7 +591,6 @@ static void their_htlc_locked(const struct htlc *htlc, struct peer *peer) tal_t *tmpctx = tal_tmpctx(peer); u8 *msg; struct onionpacket *op; - struct route_step *rs; struct sha256 bad_onion_sha; struct secret ss; enum onion_type failcode; @@ -623,34 +622,12 @@ static void their_htlc_locked(const struct htlc *htlc, struct peer *peer) goto bad_onion; } - rs = process_onionpacket(tmpctx, op, ss.data, htlc->rhash.u.u8, - sizeof(htlc->rhash)); - if (!rs) { - failcode = WIRE_INVALID_ONION_HMAC; - goto bad_onion; - } - - /* Unknown realm isn't a bad onion, it's a normal failure. */ - /* FIXME: Push complete hoppayload up and have master parse? */ - if (rs->hop_data.realm != 0) { - failcode = WIRE_INVALID_REALM; - msg = towire_update_fail_htlc(tmpctx, &peer->channel_id, - htlc->id, NULL); - msg_enqueue(&peer->peer_out, take(msg)); - goto remove_htlc; - } - /* Tell master to deal with it. */ msg = towire_channel_accepted_htlc(tmpctx, htlc->id, htlc->msatoshi, abs_locktime_to_blocks(&htlc->expiry), &htlc->rhash, - serialize_onionpacket(tmpctx, - rs->next), - rs->nextcase == ONION_FORWARD, - rs->hop_data.amt_forward, - rs->hop_data.outgoing_cltv, - &rs->hop_data.channel_id, - &ss); + &ss, + htlc->routing); daemon_conn_send(&peer->master, take(msg)); tal_free(tmpctx); return; @@ -662,7 +639,6 @@ bad_onion: failcode); msg_enqueue(&peer->peer_out, take(msg)); -remove_htlc: status_trace("htlc %"PRIu64" %s", htlc->id, onion_type_name(failcode)); rerr = channel_fail_htlc(peer->channel, REMOTE, htlc->id); if (rerr != CHANNEL_ERR_REMOVE_OK) diff --git a/lightningd/channel/channel_wire.csv b/lightningd/channel/channel_wire.csv index b90847adf..8663d8266 100644 --- a/lightningd/channel/channel_wire.csv +++ b/lightningd/channel/channel_wire.csv @@ -79,17 +79,14 @@ channel_fail_htlc,,len,2 channel_fail_htlc,,error_pkt,len*u8 # Peer and I are irrevocably committed to this HTLC. +# channelds get shared secret from HSM to save master daemon work. channel_accepted_htlc,7 channel_accepted_htlc,,id,8 channel_accepted_htlc,,amount_msat,8 channel_accepted_htlc,,cltv_expiry,4 channel_accepted_htlc,,payment_hash,32 -channel_accepted_htlc,,next_onion,1366*u8 -channel_accepted_htlc,,forward,bool -channel_accepted_htlc,,amt_to_forward,u64 -channel_accepted_htlc,,outgoing_cltv_value,u32 -channel_accepted_htlc,,next_channel,struct short_channel_id channel_accepted_htlc,,shared_secret,struct secret +channel_accepted_htlc,,onion,1366*u8 # FIXME: Add code to commit current channel state! diff --git a/lightningd/htlc_end.h b/lightningd/htlc_end.h index 549590ad6..34cb1a594 100644 --- a/lightningd/htlc_end.h +++ b/lightningd/htlc_end.h @@ -22,7 +22,7 @@ struct htlc_end { struct pay_command *pay_command; /* Temporary information, while we resolve the next hop */ - u8 next_onion[TOTAL_PACKET_SIZE]; + u8 *next_onion; struct short_channel_id next_channel; u64 amt_to_forward; u32 outgoing_cltv_value; diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 51542f739..4c75bad5f 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1213,25 +1213,34 @@ static bool channel_resolve_reply(struct subd *gossip, const u8 *msg, static int peer_accepted_htlc(struct peer *peer, const u8 *msg) { - bool forward; struct htlc_end *hend; u8 *req; + u8 onion[TOTAL_PACKET_SIZE]; + struct onionpacket *op; + struct route_step *rs; + struct sha256 bad_onion_sha; hend = tal(msg, struct htlc_end); hend->shared_secret = tal(hend, struct secret); if (!fromwire_channel_accepted_htlc(msg, NULL, &hend->htlc_id, &hend->msatoshis, - &hend->cltv_expiry, &hend->payment_hash, - hend->next_onion, &forward, - &hend->amt_to_forward, - &hend->outgoing_cltv_value, - &hend->next_channel, - hend->shared_secret)) { + &hend->cltv_expiry, + &hend->payment_hash, + hend->shared_secret, + onion)) { log_broken(peer->log, "bad fromwire_channel_accepted_htlc %s", tal_hex(peer, msg)); return -1; } + /* channeld tests this, so we shouldn't see it! */ + op = parse_onionpacket(msg, onion, TOTAL_PACKET_SIZE); + if (!op) { + log_broken(peer->log, "bad onion in fromwire_channel_accepted_htlc %s", + tal_hex(peer, msg)); + return -1; + } + tal_steal(peer, hend); hend->which_end = HTLC_SRC; hend->peer = peer; @@ -1239,7 +1248,28 @@ static int peer_accepted_htlc(struct peer *peer, const u8 *msg) hend->pay_command = NULL; hend->fail_msg = NULL; - if (forward) { + /* If it's crap, not their fault, just fail it */ + rs = process_onionpacket(msg, op, hend->shared_secret->data, + hend->payment_hash.u.u8, + sizeof(hend->payment_hash)); + if (!rs) { + sha256(&bad_onion_sha, onion, sizeof(onion)); + fail_htlc(hend, WIRE_INVALID_ONION_HMAC, &bad_onion_sha); + return 0; + } + + /* Unknown realm isn't a bad onion, it's a normal failure. */ + if (rs->hop_data.realm != 0) { + fail_htlc(hend, WIRE_INVALID_REALM, NULL); + return 0; + } + + hend->amt_to_forward = rs->hop_data.amt_forward; + hend->outgoing_cltv_value = rs->hop_data.outgoing_cltv; + hend->next_channel = rs->hop_data.channel_id; + + if (rs->nextcase == ONION_FORWARD) { + hend->next_onion = serialize_onionpacket(hend, rs->next); req = towire_gossip_resolve_channel_request(msg, &hend->next_channel); log_broken(peer->log, "Asking gossip to resolve channel %d/%d/%d", hend->next_channel.blocknum, hend->next_channel.txnum, hend->next_channel.outnum); subd_req(hend, peer->ld->gossip, req, -1, 0, channel_resolve_reply, hend);