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