diff --git a/channeld/channeld.c b/channeld/channeld.c index 27c0e0701..705d11352 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -51,7 +51,6 @@ #include #include #include -#include #include #include #include @@ -65,7 +64,6 @@ #include #include #include -#include #include #if EXPERIMENTAL_FEATURES #include @@ -1805,230 +1803,6 @@ static bool channeld_handle_custommsg(const u8 *msg) } #if EXPERIMENTAL_FEATURES -/* Peer sends onion msg. */ -static void handle_onion_message(struct peer *peer, const u8 *msg) -{ - enum onion_wire badreason; - struct onionpacket *op; - struct secret ss, *blinding_ss; - struct pubkey *blinding_in; - struct route_step *rs; - u8 onion[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)]; - const u8 *cursor; - size_t max, maxlen; - struct tlv_onionmsg_payload *om; - struct tlv_onion_message_tlvs *tlvs = tlv_onion_message_tlvs_new(msg); - - if (!fromwire_onion_message(msg, onion, tlvs)) - peer_failed(peer->pps, - &peer->channel_id, - "Bad onion_message %s", tal_hex(peer, msg)); - - /* We unwrap the onion now. */ - op = parse_onionpacket(tmpctx, onion, TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE), &badreason); - if (badreason != 0) { - status_debug("onion msg: can't parse onionpacket: %s", - onion_wire_name(badreason)); - return; - } - - if (tlvs->blinding) { - struct secret hmac; - - /* E(i) */ - blinding_in = tal_dup(msg, struct pubkey, tlvs->blinding); - status_debug("blinding in = %s", - type_to_string(tmpctx, struct pubkey, blinding_in)); - blinding_ss = tal(msg, struct secret); - ecdh(blinding_in, blinding_ss); - - /* 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, - &op->ephemeralkey.pubkey, - hmac.data) != 1) { - status_debug("onion msg: can't tweak pubkey"); - return; - } - } else { - blinding_ss = NULL; - blinding_in = NULL; - } - - ecdh(&op->ephemeralkey, &ss); - - /* We make sure we can parse onion packet, so we know if shared secret - * is actually valid (this checks hmac). */ - rs = process_onionpacket(tmpctx, op, &ss, NULL, 0, false); - if (!rs) { - status_debug("onion msg: can't process onionpacket ss=%s", - type_to_string(tmpctx, struct secret, &ss)); - return; - } - - /* The raw payload is prepended with length in the TLV world. */ - cursor = rs->raw_payload; - max = tal_bytelen(rs->raw_payload); - maxlen = fromwire_bigsize(&cursor, &max); - if (!cursor) { - status_debug("onion msg: Invalid hop payload %s", - tal_hex(tmpctx, rs->raw_payload)); - return; - } - if (maxlen > max) { - status_debug("onion msg: overlong hop payload %s", - tal_hex(tmpctx, rs->raw_payload)); - return; - } - - om = tlv_onionmsg_payload_new(msg); - if (!fromwire_onionmsg_payload(&cursor, &maxlen, om)) { - status_debug("onion msg: invalid onionmsg_payload %s", - tal_hex(tmpctx, rs->raw_payload)); - return; - } - - /* If we weren't given a blinding factor, tlv can provide one. */ - if (om->blinding && !blinding_ss) { - /* E(i) */ - blinding_in = tal_dup(msg, struct pubkey, om->blinding); - blinding_ss = tal(msg, struct secret); - - ecdh(blinding_in, blinding_ss); - } - - if (om->enctlv) { - const unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - u8 *dec; - struct secret rho; - int ret; - - if (!blinding_ss) { - status_debug("enctlv but no blinding?"); - return; - } - - /* We need this to decrypt enctlv */ - subkey_from_hmac("rho", blinding_ss, &rho); - - /* Overrides next_scid / next_node */ - if (tal_bytelen(om->enctlv) - < crypto_aead_chacha20poly1305_ietf_ABYTES) { - status_debug("enctlv too short for mac"); - return; - } - - dec = tal_arr(msg, u8, - tal_bytelen(om->enctlv) - - crypto_aead_chacha20poly1305_ietf_ABYTES); - ret = crypto_aead_chacha20poly1305_ietf_decrypt(dec, NULL, - NULL, - om->enctlv, - tal_bytelen(om->enctlv), - NULL, 0, - npub, - rho.data); - if (ret != 0) - errx(1, "Failed to decrypt enctlv field"); - - status_debug("enctlv -> %s", tal_hex(tmpctx, dec)); - - /* Replace onionmsg with one from enctlv */ - cursor = dec; - maxlen = tal_bytelen(dec); - - om = tlv_onionmsg_payload_new(msg); - if (!fromwire_onionmsg_payload(&cursor, &maxlen, om)) { - status_debug("onion msg: invalid enctlv onionmsg_payload %s", - tal_hex(tmpctx, dec)); - return; - } - } else if (blinding_ss && rs->nextcase != ONION_END) { - status_debug("Onion had %s, but not enctlv?", - tlvs->blinding ? "blinding" : "om blinding"); - return; - } - - if (rs->nextcase == ONION_END) { - struct pubkey *blinding; - const struct onionmsg_path **path; - u8 *omsg; - - if (om->reply_path) { - blinding = &om->reply_path->blinding; - path = cast_const2(const struct onionmsg_path **, - om->reply_path->path); - } else { - blinding = NULL; - path = NULL; - } - - /* We re-marshall here by policy, before handing to lightningd */ - omsg = tal_arr(tmpctx, u8, 0); - towire_tlvstream_raw(&omsg, om->fields); - wire_sync_write(MASTER_FD, - take(towire_got_onionmsg_to_us(NULL, - blinding_in, - blinding, - path, - omsg))); - } else { - struct pubkey *next_blinding; - struct node_id *next_node; - - /* This *MUST* have instructions on where to go next. */ - if (!om->next_short_channel_id && !om->next_node_id) { - status_debug("onion msg: no next field in %s", - tal_hex(tmpctx, rs->raw_payload)); - return; - } - - if (blinding_ss) { - /* E(i-1) = H(E(i) || ss(i)) * E(i) */ - struct sha256 h; - blinding_hash_e_and_ss(blinding_in, blinding_ss, &h); - next_blinding = tal(msg, struct pubkey); - blinding_next_pubkey(blinding_in, &h, next_blinding); - } else - next_blinding = NULL; - - if (om->next_node_id) { - next_node = tal(tmpctx, struct node_id); - node_id_from_pubkey(next_node, om->next_node_id); - } else - next_node = NULL; - - wire_sync_write(MASTER_FD, - take(towire_got_onionmsg_forward(NULL, - om->next_short_channel_id, - next_node, - next_blinding, - serialize_onionpacket(tmpctx, rs->next)))); - } -} - -/* We send onion msg. */ -static void send_onionmsg(struct peer *peer, const u8 *msg) -{ - u8 onion_routing_packet[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)]; - struct pubkey *blinding; - struct tlv_onion_message_tlvs *tlvs = tlv_onion_message_tlvs_new(msg); - - if (!fromwire_send_onionmsg(msg, msg, onion_routing_packet, &blinding)) - master_badmsg(WIRE_SEND_ONIONMSG, msg); - - if (blinding) - tlvs->blinding = tal_dup(tlvs, struct pubkey, blinding); - sync_crypto_write(peer->pps, - take(towire_onion_message(NULL, - onion_routing_packet, - tlvs))); -} - static void handle_send_tx_sigs(struct peer *peer, const u8 *msg) { struct wally_psbt *psbt; @@ -2278,9 +2052,6 @@ static void peer_in(struct peer *peer, const u8 *msg) handle_peer_shutdown(peer, msg); return; #if EXPERIMENTAL_FEATURES - case WIRE_ONION_MESSAGE: - handle_onion_message(peer, msg); - return; case WIRE_TX_SIGNATURES: handle_tx_sigs(peer, msg); return; @@ -2323,6 +2094,9 @@ static void peer_in(struct peer *peer, const u8 *msg) case WIRE_PING: case WIRE_PONG: case WIRE_ERROR: +#if EXPERIMENTAL_FEATURES + case WIRE_ONION_MESSAGE: +#endif abort(); } @@ -3361,14 +3135,6 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNELD_SEND_TX_SIGS: break; #endif /* !EXPERIMENTAL_FEATURES */ -#if EXPERIMENTAL_FEATURES - case WIRE_SEND_ONIONMSG: - send_onionmsg(peer, msg); - return; -#else - case WIRE_SEND_ONIONMSG: - break; -#endif /* !EXPERIMENTAL_FEATURES */ #if DEVELOPER case WIRE_CHANNELD_DEV_REENABLE_COMMIT: handle_dev_reenable_commit(peer); @@ -3397,8 +3163,6 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNELD_FAIL_FALLEN_BEHIND: case WIRE_CHANNELD_DEV_MEMLEAK_REPLY: case WIRE_CHANNELD_SEND_ERROR_REPLY: - case WIRE_GOT_ONIONMSG_TO_US: - case WIRE_GOT_ONIONMSG_FORWARD: break; } diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index 84dd5ddcf..4a7e74c4c 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -224,23 +224,3 @@ msgdata,channeld_send_error,reason,wirestring, # Tell master channeld has sent the error message. msgtype,channeld_send_error_reply,1108 - -# Tell lightningd we got a onion message (for us, or to fwd) -msgtype,got_onionmsg_to_us,1142 -msgdata,got_onionmsg_to_us,blinding_in,?pubkey, -msgdata,got_onionmsg_to_us,reply_blinding,?pubkey, -msgdata,got_onionmsg_to_us,reply_path_len,u16, -msgdata,got_onionmsg_to_us,reply_path,onionmsg_path,reply_path_len -msgdata,got_onionmsg_to_us,rawmsg_len,u16, -msgdata,got_onionmsg_to_us,rawmsg,u8,rawmsg_len - -msgtype,got_onionmsg_forward,1143 -msgdata,got_onionmsg_forward,next_scid,?short_channel_id, -msgdata,got_onionmsg_forward,next_node_id,?node_id, -msgdata,got_onionmsg_forward,next_blinding,?pubkey, -msgdata,got_onionmsg_forward,next_onion,u8,1366 - -# Lightningd tells us to send a onion message. -msgtype,send_onionmsg,1040 -msgdata,send_onionmsg,onion,u8,1366 -msgdata,send_onionmsg,blinding,?pubkey, diff --git a/channeld/channeld_wiregen.c b/channeld/channeld_wiregen.c index d6d98b6d0..85d021c84 100644 --- a/channeld/channeld_wiregen.c +++ b/channeld/channeld_wiregen.c @@ -48,9 +48,6 @@ const char *channeld_wire_name(int e) case WIRE_CHANNELD_GOT_ANNOUNCEMENT: return "WIRE_CHANNELD_GOT_ANNOUNCEMENT"; case WIRE_CHANNELD_SEND_ERROR: return "WIRE_CHANNELD_SEND_ERROR"; case WIRE_CHANNELD_SEND_ERROR_REPLY: return "WIRE_CHANNELD_SEND_ERROR_REPLY"; - case WIRE_GOT_ONIONMSG_TO_US: return "WIRE_GOT_ONIONMSG_TO_US"; - case WIRE_GOT_ONIONMSG_FORWARD: return "WIRE_GOT_ONIONMSG_FORWARD"; - case WIRE_SEND_ONIONMSG: return "WIRE_SEND_ONIONMSG"; } snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e); @@ -88,9 +85,6 @@ bool channeld_wire_is_defined(u16 type) case WIRE_CHANNELD_GOT_ANNOUNCEMENT:; case WIRE_CHANNELD_SEND_ERROR:; case WIRE_CHANNELD_SEND_ERROR_REPLY:; - case WIRE_GOT_ONIONMSG_TO_US:; - case WIRE_GOT_ONIONMSG_FORWARD:; - case WIRE_SEND_ONIONMSG:; return true; } return false; @@ -1102,158 +1096,4 @@ bool fromwire_channeld_send_error_reply(const void *p) return false; return cursor != NULL; } - -/* WIRE: GOT_ONIONMSG_TO_US */ -/* Tell lightningd we got a onion message (for us */ -u8 *towire_got_onionmsg_to_us(const tal_t *ctx, const struct pubkey *blinding_in, const struct pubkey *reply_blinding, const struct onionmsg_path **reply_path, const u8 *rawmsg) -{ - u16 reply_path_len = tal_count(reply_path); - u16 rawmsg_len = tal_count(rawmsg); - u8 *p = tal_arr(ctx, u8, 0); - - towire_u16(&p, WIRE_GOT_ONIONMSG_TO_US); - if (!blinding_in) - towire_bool(&p, false); - else { - towire_bool(&p, true); - towire_pubkey(&p, blinding_in); - } - if (!reply_blinding) - towire_bool(&p, false); - else { - towire_bool(&p, true); - towire_pubkey(&p, reply_blinding); - } - towire_u16(&p, reply_path_len); - for (size_t i = 0; i < reply_path_len; i++) - towire_onionmsg_path(&p, reply_path[i]); - towire_u16(&p, rawmsg_len); - towire_u8_array(&p, rawmsg, rawmsg_len); - - return memcheck(p, tal_count(p)); -} -bool fromwire_got_onionmsg_to_us(const tal_t *ctx, const void *p, struct pubkey **blinding_in, struct pubkey **reply_blinding, struct onionmsg_path ***reply_path, u8 **rawmsg) -{ - u16 reply_path_len; - u16 rawmsg_len; - - const u8 *cursor = p; - size_t plen = tal_count(p); - - if (fromwire_u16(&cursor, &plen) != WIRE_GOT_ONIONMSG_TO_US) - return false; - if (!fromwire_bool(&cursor, &plen)) - *blinding_in = NULL; - else { - *blinding_in = tal(ctx, struct pubkey); - fromwire_pubkey(&cursor, &plen, *blinding_in); - } - if (!fromwire_bool(&cursor, &plen)) - *reply_blinding = NULL; - else { - *reply_blinding = tal(ctx, struct pubkey); - fromwire_pubkey(&cursor, &plen, *reply_blinding); - } - reply_path_len = fromwire_u16(&cursor, &plen); - // 2nd case reply_path - *reply_path = reply_path_len ? tal_arr(ctx, struct onionmsg_path *, reply_path_len) : NULL; - for (size_t i = 0; i < reply_path_len; i++) - (*reply_path)[i] = fromwire_onionmsg_path(*reply_path, &cursor, &plen); - rawmsg_len = fromwire_u16(&cursor, &plen); - // 2nd case rawmsg - *rawmsg = rawmsg_len ? tal_arr(ctx, u8, rawmsg_len) : NULL; - fromwire_u8_array(&cursor, &plen, *rawmsg, rawmsg_len); - return cursor != NULL; -} - -/* WIRE: GOT_ONIONMSG_FORWARD */ -u8 *towire_got_onionmsg_forward(const tal_t *ctx, const struct short_channel_id *next_scid, const struct node_id *next_node_id, const struct pubkey *next_blinding, const u8 next_onion[1366]) -{ - u8 *p = tal_arr(ctx, u8, 0); - - towire_u16(&p, WIRE_GOT_ONIONMSG_FORWARD); - if (!next_scid) - towire_bool(&p, false); - else { - towire_bool(&p, true); - towire_short_channel_id(&p, next_scid); - } - if (!next_node_id) - towire_bool(&p, false); - else { - towire_bool(&p, true); - towire_node_id(&p, next_node_id); - } - if (!next_blinding) - towire_bool(&p, false); - else { - towire_bool(&p, true); - towire_pubkey(&p, next_blinding); - } - towire_u8_array(&p, next_onion, 1366); - - return memcheck(p, tal_count(p)); -} -bool fromwire_got_onionmsg_forward(const tal_t *ctx, const void *p, struct short_channel_id **next_scid, struct node_id **next_node_id, struct pubkey **next_blinding, u8 next_onion[1366]) -{ - const u8 *cursor = p; - size_t plen = tal_count(p); - - if (fromwire_u16(&cursor, &plen) != WIRE_GOT_ONIONMSG_FORWARD) - return false; - if (!fromwire_bool(&cursor, &plen)) - *next_scid = NULL; - else { - *next_scid = tal(ctx, struct short_channel_id); - fromwire_short_channel_id(&cursor, &plen, *next_scid); - } - if (!fromwire_bool(&cursor, &plen)) - *next_node_id = NULL; - else { - *next_node_id = tal(ctx, struct node_id); - fromwire_node_id(&cursor, &plen, *next_node_id); - } - if (!fromwire_bool(&cursor, &plen)) - *next_blinding = NULL; - else { - *next_blinding = tal(ctx, struct pubkey); - fromwire_pubkey(&cursor, &plen, *next_blinding); - } - fromwire_u8_array(&cursor, &plen, next_onion, 1366); - return cursor != NULL; -} - -/* WIRE: SEND_ONIONMSG */ -/* Lightningd tells us to send a onion message. */ -u8 *towire_send_onionmsg(const tal_t *ctx, const u8 onion[1366], const struct pubkey *blinding) -{ - u8 *p = tal_arr(ctx, u8, 0); - - towire_u16(&p, WIRE_SEND_ONIONMSG); - towire_u8_array(&p, onion, 1366); - if (!blinding) - towire_bool(&p, false); - else { - towire_bool(&p, true); - towire_pubkey(&p, blinding); - } - - return memcheck(p, tal_count(p)); -} -bool fromwire_send_onionmsg(const tal_t *ctx, const void *p, u8 onion[1366], struct pubkey **blinding) -{ - const u8 *cursor = p; - size_t plen = tal_count(p); - - if (fromwire_u16(&cursor, &plen) != WIRE_SEND_ONIONMSG) - return false; - fromwire_u8_array(&cursor, &plen, onion, 1366); - if (!fromwire_bool(&cursor, &plen)) - *blinding = NULL; - else { - *blinding = tal(ctx, struct pubkey); - fromwire_pubkey(&cursor, &plen, *blinding); - } - return cursor != NULL; -} -// SHA256STAMP:564860d28225780e0746b0f9e6944d691a342d12bd9d0400bb962577fab64067 +// SHA256STAMP:58b780dc0bd7296e837407e362f2364f70104199c6a6b01382bb9278696688ae diff --git a/channeld/channeld_wiregen.h b/channeld/channeld_wiregen.h index 808cce431..6a65a7d23 100644 --- a/channeld/channeld_wiregen.h +++ b/channeld/channeld_wiregen.h @@ -74,11 +74,6 @@ enum channeld_wire { WIRE_CHANNELD_SEND_ERROR = 1008, /* Tell master channeld has sent the error message. */ WIRE_CHANNELD_SEND_ERROR_REPLY = 1108, - /* Tell lightningd we got a onion message (for us */ - WIRE_GOT_ONIONMSG_TO_US = 1142, - WIRE_GOT_ONIONMSG_FORWARD = 1143, - /* Lightningd tells us to send a onion message. */ - WIRE_SEND_ONIONMSG = 1040, }; const char *channeld_wire_name(int e); @@ -230,20 +225,6 @@ bool fromwire_channeld_send_error(const tal_t *ctx, const void *p, wirestring ** u8 *towire_channeld_send_error_reply(const tal_t *ctx); bool fromwire_channeld_send_error_reply(const void *p); -/* WIRE: GOT_ONIONMSG_TO_US */ -/* Tell lightningd we got a onion message (for us */ -u8 *towire_got_onionmsg_to_us(const tal_t *ctx, const struct pubkey *blinding_in, const struct pubkey *reply_blinding, const struct onionmsg_path **reply_path, const u8 *rawmsg); -bool fromwire_got_onionmsg_to_us(const tal_t *ctx, const void *p, struct pubkey **blinding_in, struct pubkey **reply_blinding, struct onionmsg_path ***reply_path, u8 **rawmsg); - -/* WIRE: GOT_ONIONMSG_FORWARD */ -u8 *towire_got_onionmsg_forward(const tal_t *ctx, const struct short_channel_id *next_scid, const struct node_id *next_node_id, const struct pubkey *next_blinding, const u8 next_onion[1366]); -bool fromwire_got_onionmsg_forward(const tal_t *ctx, const void *p, struct short_channel_id **next_scid, struct node_id **next_node_id, struct pubkey **next_blinding, u8 next_onion[1366]); - -/* WIRE: SEND_ONIONMSG */ -/* Lightningd tells us to send a onion message. */ -u8 *towire_send_onionmsg(const tal_t *ctx, const u8 onion[1366], const struct pubkey *blinding); -bool fromwire_send_onionmsg(const tal_t *ctx, const void *p, u8 onion[1366], struct pubkey **blinding); - #endif /* LIGHTNING_CHANNELD_CHANNELD_WIREGEN_H */ -// SHA256STAMP:564860d28225780e0746b0f9e6944d691a342d12bd9d0400bb962577fab64067 +// SHA256STAMP:58b780dc0bd7296e837407e362f2364f70104199c6a6b01382bb9278696688ae diff --git a/gossipd/Makefile b/gossipd/Makefile index 5d52463b6..7d4f7d70a 100644 --- a/gossipd/Makefile +++ b/gossipd/Makefile @@ -33,6 +33,7 @@ GOSSIPD_COMMON_OBJS := \ common/bech32_util.o \ common/bigsize.o \ common/bip32.o \ + common/blinding.o \ common/channel_id.o \ common/crypto_state.o \ common/cryptomsg.o \ @@ -41,13 +42,16 @@ GOSSIPD_COMMON_OBJS := \ common/decode_array.o \ common/derive_basepoints.o \ common/dev_disconnect.o \ + common/ecdh_hsmd.o \ common/features.o \ + common/hmac.o \ common/status_wiregen.o \ common/gossip_rcvd_filter.o \ common/key_derive.o \ common/memleak.o \ common/msg_queue.o \ common/node_id.o \ + common/onion.o \ common/onionreply.o \ common/per_peer_state.o \ common/ping.o \ @@ -56,6 +60,7 @@ GOSSIPD_COMMON_OBJS := \ common/private_channel_announcement.o \ common/random_select.o \ common/setup.o \ + common/sphinx.o \ common/status.o \ common/status_wire.o \ common/subdaemon.o \ diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index 740d2f0ce..c87f2b704 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -27,12 +27,15 @@ #include #include #include +#include #include #include +#include #include #include #include #include +#include #include #include #include @@ -58,12 +61,16 @@ #include #include #include +#include #include #include #include #include #include #include +#if EXPERIMENTAL_FEATURES +#include +#endif #include #include @@ -428,6 +435,263 @@ static bool handle_local_channel_announcement(struct daemon *daemon, return true; } +#if EXPERIMENTAL_FEATURES +/* Peer sends onion msg. */ +static u8 *handle_onion_message(struct peer *peer, const u8 *msg) +{ + enum onion_wire badreason; + struct onionpacket *op; + struct secret ss, *blinding_ss; + struct pubkey *blinding_in; + struct route_step *rs; + u8 onion[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)]; + const u8 *cursor; + size_t max, maxlen; + struct tlv_onionmsg_payload *om; + struct tlv_onion_message_tlvs *tlvs = tlv_onion_message_tlvs_new(msg); + + /* FIXME: ratelimit! */ + if (!fromwire_onion_message(msg, onion, tlvs)) + return towire_errorfmt(peer, NULL, "Bad onion_message"); + + /* We unwrap the onion now. */ + op = parse_onionpacket(tmpctx, onion, TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE), &badreason); + if (!op) { + status_debug("peer %s: onion msg: can't parse onionpacket: %s", + type_to_string(tmpctx, struct node_id, &peer->id), + onion_wire_name(badreason)); + return NULL; + } + + if (tlvs->blinding) { + struct secret hmac; + + /* E(i) */ + blinding_in = tal_dup(msg, struct pubkey, tlvs->blinding); + status_debug("peer %s: blinding in = %s", + type_to_string(tmpctx, struct node_id, &peer->id), + type_to_string(tmpctx, struct pubkey, blinding_in)); + blinding_ss = tal(msg, struct secret); + ecdh(blinding_in, blinding_ss); + + /* 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, + &op->ephemeralkey.pubkey, + hmac.data) != 1) { + status_debug("peer %s: onion msg: can't tweak pubkey", + type_to_string(tmpctx, struct node_id, &peer->id)); + return NULL; + } + } else { + blinding_ss = NULL; + blinding_in = NULL; + } + + ecdh(&op->ephemeralkey, &ss); + + /* We make sure we can parse onion packet, so we know if shared secret + * is actually valid (this checks hmac). */ + rs = process_onionpacket(tmpctx, op, &ss, NULL, 0, false); + if (!rs) { + status_debug("peer %s: onion msg: can't process onionpacket ss=%s", + type_to_string(tmpctx, struct node_id, &peer->id), + type_to_string(tmpctx, struct secret, &ss)); + return NULL; + } + + /* The raw payload is prepended with length in the TLV world. */ + cursor = rs->raw_payload; + max = tal_bytelen(rs->raw_payload); + maxlen = fromwire_bigsize(&cursor, &max); + if (!cursor) { + status_debug("peer %s: onion msg: Invalid hop payload %s", + type_to_string(tmpctx, struct node_id, &peer->id), + tal_hex(tmpctx, rs->raw_payload)); + return NULL; + } + if (maxlen > max) { + status_debug("peer %s: onion msg: overlong hop payload %s", + type_to_string(tmpctx, struct node_id, &peer->id), + tal_hex(tmpctx, rs->raw_payload)); + return NULL; + } + + om = tlv_onionmsg_payload_new(msg); + if (!fromwire_onionmsg_payload(&cursor, &maxlen, om)) { + status_debug("peer %s: onion msg: invalid onionmsg_payload %s", + type_to_string(tmpctx, struct node_id, &peer->id), + tal_hex(tmpctx, rs->raw_payload)); + return NULL; + } + + /* If we weren't given a blinding factor, tlv can provide one. */ + if (om->blinding && !blinding_ss) { + /* E(i) */ + blinding_in = tal_dup(msg, struct pubkey, om->blinding); + blinding_ss = tal(msg, struct secret); + + ecdh(blinding_in, blinding_ss); + } + + if (om->enctlv) { + const unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 *dec; + struct secret rho; + int ret; + + if (!blinding_ss) { + status_debug("peer %s: enctlv but no blinding?", + type_to_string(tmpctx, struct node_id, &peer->id)); + return NULL; + } + + /* We need this to decrypt enctlv */ + subkey_from_hmac("rho", blinding_ss, &rho); + + /* Overrides next_scid / next_node */ + if (tal_bytelen(om->enctlv) + < crypto_aead_chacha20poly1305_ietf_ABYTES) { + status_debug("peer %s: enctlv too short for mac", + type_to_string(tmpctx, struct node_id, &peer->id)); + return NULL; + } + + dec = tal_arr(msg, u8, + tal_bytelen(om->enctlv) + - crypto_aead_chacha20poly1305_ietf_ABYTES); + ret = crypto_aead_chacha20poly1305_ietf_decrypt(dec, NULL, + NULL, + om->enctlv, + tal_bytelen(om->enctlv), + NULL, 0, + npub, + rho.data); + if (ret != 0) { + status_debug("peer %s: Failed to decrypt enctlv field", + type_to_string(tmpctx, struct node_id, &peer->id)); + return NULL; + } + + status_debug("peer %s: enctlv -> %s", + type_to_string(tmpctx, struct node_id, &peer->id), + tal_hex(tmpctx, dec)); + + /* Replace onionmsg with one from enctlv */ + cursor = dec; + maxlen = tal_bytelen(dec); + + om = tlv_onionmsg_payload_new(msg); + if (!fromwire_onionmsg_payload(&cursor, &maxlen, om)) { + status_debug("peer %s: onion msg: invalid enctlv onionmsg_payload %s", + type_to_string(tmpctx, struct node_id, &peer->id), + tal_hex(tmpctx, dec)); + return NULL; + } + } else if (blinding_ss && rs->nextcase != ONION_END) { + status_debug("peer %s: Onion had %s, but not enctlv?", + type_to_string(tmpctx, struct node_id, &peer->id), + tlvs->blinding ? "blinding" : "om blinding"); + return NULL; + } + + if (rs->nextcase == ONION_END) { + struct pubkey *blinding; + const struct onionmsg_path **path; + u8 *omsg; + + if (om->reply_path) { + blinding = &om->reply_path->blinding; + path = cast_const2(const struct onionmsg_path **, + om->reply_path->path); + } else { + blinding = NULL; + path = NULL; + } + + /* We re-marshall here by policy, before handing to lightningd */ + omsg = tal_arr(tmpctx, u8, 0); + towire_tlvstream_raw(&omsg, om->fields); + daemon_conn_send(peer->daemon->master, + take(towire_gossipd_got_onionmsg_to_us(NULL, + blinding_in, + blinding, + path, + omsg))); + } else { + struct pubkey *next_blinding; + struct node_id *next_node; + + /* This *MUST* have instructions on where to go next. */ + if (!om->next_short_channel_id && !om->next_node_id) { + status_debug("peer %s: onion msg: no next field in %s", + type_to_string(tmpctx, struct node_id, &peer->id), + tal_hex(tmpctx, rs->raw_payload)); + return NULL; + } + + if (blinding_ss) { + /* E(i-1) = H(E(i) || ss(i)) * E(i) */ + struct sha256 h; + blinding_hash_e_and_ss(blinding_in, blinding_ss, &h); + next_blinding = tal(msg, struct pubkey); + blinding_next_pubkey(blinding_in, &h, next_blinding); + } else + next_blinding = NULL; + + if (om->next_node_id) { + next_node = tal(tmpctx, struct node_id); + node_id_from_pubkey(next_node, om->next_node_id); + } else + next_node = NULL; + + daemon_conn_send(peer->daemon->master, + take(towire_gossipd_got_onionmsg_forward(NULL, + om->next_short_channel_id, + next_node, + next_blinding, + serialize_onionpacket(tmpctx, rs->next)))); + } + return NULL; +} + +/* We send onion msg. */ +static struct io_plan *onionmsg_req(struct io_conn *conn, struct daemon *daemon, + const u8 *msg) +{ + struct node_id id; + u8 onion_routing_packet[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)]; + struct pubkey *blinding; + struct peer *peer; + + if (!fromwire_gossipd_send_onionmsg(msg, msg, &id, onion_routing_packet, + &blinding)) + master_badmsg(WIRE_GOSSIPD_SEND_ONIONMSG, msg); + + /* Even if lightningd were to check for valid ids, there's a race + * where it might vanish before we read this command; cleaner to + * handle it here with 'sent' = false. */ + peer = find_peer(daemon, &id); + if (peer) { + struct tlv_onion_message_tlvs *tlvs; + + tlvs = tlv_onion_message_tlvs_new(msg); + if (blinding) + tlvs->blinding = tal_dup(tlvs, struct pubkey, blinding); + + queue_peer_msg(peer, + take(towire_onion_message(NULL, + onion_routing_packet, + tlvs))); + } + return daemon_conn_read_next(conn, daemon->master); +} +#endif /* EXPERIMENTAL_FEATURES */ + /*~ This is where the per-peer daemons send us messages. It's either forwarded * gossip, or a request for information. We deliberately use non-overlapping * message types so we can distinguish them. */ @@ -467,6 +731,11 @@ static struct io_plan *peer_msg_in(struct io_conn *conn, case WIRE_PONG: err = handle_pong(peer, msg); goto handled_relay; +#if EXPERIMENTAL_FEATURES + case WIRE_ONION_MESSAGE: + err = handle_onion_message(peer, msg); + goto handled_relay; +#endif /* These are non-gossip messages (!is_msg_for_gossipd()) */ case WIRE_INIT: @@ -489,7 +758,6 @@ static struct io_plan *peer_msg_in(struct io_conn *conn, case WIRE_ANNOUNCEMENT_SIGNATURES: case WIRE_GOSSIP_TIMESTAMP_FILTER: #if EXPERIMENTAL_FEATURES - case WIRE_ONION_MESSAGE: case WIRE_TX_ADD_INPUT: case WIRE_TX_REMOVE_INPUT: case WIRE_TX_ADD_OUTPUT: @@ -1662,6 +1930,10 @@ static struct io_plan *recv_req(struct io_conn *conn, break; #endif /* !DEVELOPER */ + case WIRE_GOSSIPD_SEND_ONIONMSG: +#if EXPERIMENTAL_FEATURES + return onionmsg_req(conn, daemon, msg); +#endif /* We send these, we don't receive them */ case WIRE_GOSSIPD_GETNODES_REPLY: case WIRE_GOSSIPD_GETROUTE_REPLY: @@ -1672,6 +1944,8 @@ static struct io_plan *recv_req(struct io_conn *conn, case WIRE_GOSSIPD_GET_TXOUT: case WIRE_GOSSIPD_DEV_MEMLEAK_REPLY: case WIRE_GOSSIPD_DEV_COMPACT_STORE_REPLY: + case WIRE_GOSSIPD_GOT_ONIONMSG_TO_US: + case WIRE_GOSSIPD_GOT_ONIONMSG_FORWARD: break; } @@ -1703,6 +1977,9 @@ int main(int argc, char *argv[]) daemon->node_announce_timer = NULL; daemon->current_blockheight = 0; /* i.e. unknown */ + /* Tell the ecdh() function how to talk to hsmd */ + ecdh_hsmd_setup(HSM_FD, status_failed); + /* Note the use of time_mono() here. That's a monotonic clock, which * is really useful: it can only be used to measure relative events * (there's no correspondence to time-since-Ken-grew-a-beard or diff --git a/gossipd/gossipd_wire.csv b/gossipd/gossipd_wire.csv index 4433d104e..2e5c158d8 100644 --- a/gossipd/gossipd_wire.csv +++ b/gossipd/gossipd_wire.csv @@ -138,3 +138,24 @@ msgdata,gossipd_get_incoming_channels_reply,private_deadends,bool,num_private # master -> gossipd: blockheight increased. msgtype,gossipd_new_blockheight,3026 msgdata,gossipd_new_blockheight,blockheight,u32, + +# Tell lightningd we got a onion message (for us, or to fwd) +msgtype,gossipd_got_onionmsg_to_us,3142 +msgdata,gossipd_got_onionmsg_to_us,blinding_in,?pubkey, +msgdata,gossipd_got_onionmsg_to_us,reply_blinding,?pubkey, +msgdata,gossipd_got_onionmsg_to_us,reply_path_len,u16, +msgdata,gossipd_got_onionmsg_to_us,reply_path,onionmsg_path,reply_path_len +msgdata,gossipd_got_onionmsg_to_us,rawmsg_len,u16, +msgdata,gossipd_got_onionmsg_to_us,rawmsg,u8,rawmsg_len + +msgtype,gossipd_got_onionmsg_forward,3143 +msgdata,gossipd_got_onionmsg_forward,next_scid,?short_channel_id, +msgdata,gossipd_got_onionmsg_forward,next_node_id,?node_id, +msgdata,gossipd_got_onionmsg_forward,next_blinding,?pubkey, +msgdata,gossipd_got_onionmsg_forward,next_onion,u8,1366 + +# Lightningd tells us to send a onion message. +msgtype,gossipd_send_onionmsg,3040 +msgdata,gossipd_send_onionmsg,id,node_id, +msgdata,gossipd_send_onionmsg,onion,u8,1366 +msgdata,gossipd_send_onionmsg,blinding,?pubkey, diff --git a/gossipd/gossipd_wiregen.c b/gossipd/gossipd_wiregen.c index 09e07ba42..e508e1e03 100644 --- a/gossipd/gossipd_wiregen.c +++ b/gossipd/gossipd_wiregen.c @@ -46,6 +46,9 @@ const char *gossipd_wire_name(int e) case WIRE_GOSSIPD_GET_INCOMING_CHANNELS: return "WIRE_GOSSIPD_GET_INCOMING_CHANNELS"; case WIRE_GOSSIPD_GET_INCOMING_CHANNELS_REPLY: return "WIRE_GOSSIPD_GET_INCOMING_CHANNELS_REPLY"; case WIRE_GOSSIPD_NEW_BLOCKHEIGHT: return "WIRE_GOSSIPD_NEW_BLOCKHEIGHT"; + case WIRE_GOSSIPD_GOT_ONIONMSG_TO_US: return "WIRE_GOSSIPD_GOT_ONIONMSG_TO_US"; + case WIRE_GOSSIPD_GOT_ONIONMSG_FORWARD: return "WIRE_GOSSIPD_GOT_ONIONMSG_FORWARD"; + case WIRE_GOSSIPD_SEND_ONIONMSG: return "WIRE_GOSSIPD_SEND_ONIONMSG"; } snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e); @@ -81,6 +84,9 @@ bool gossipd_wire_is_defined(u16 type) case WIRE_GOSSIPD_GET_INCOMING_CHANNELS:; case WIRE_GOSSIPD_GET_INCOMING_CHANNELS_REPLY:; case WIRE_GOSSIPD_NEW_BLOCKHEIGHT:; + case WIRE_GOSSIPD_GOT_ONIONMSG_TO_US:; + case WIRE_GOSSIPD_GOT_ONIONMSG_FORWARD:; + case WIRE_GOSSIPD_SEND_ONIONMSG:; return true; } return false; @@ -857,4 +863,160 @@ bool fromwire_gossipd_new_blockheight(const void *p, u32 *blockheight) *blockheight = fromwire_u32(&cursor, &plen); return cursor != NULL; } -// SHA256STAMP:ae8bf4f19cc3dd086b9a20b8bc034d93d8ef066e901279de09fe2fd189f1344b + +/* WIRE: GOSSIPD_GOT_ONIONMSG_TO_US */ +/* Tell lightningd we got a onion message (for us */ +u8 *towire_gossipd_got_onionmsg_to_us(const tal_t *ctx, const struct pubkey *blinding_in, const struct pubkey *reply_blinding, const struct onionmsg_path **reply_path, const u8 *rawmsg) +{ + u16 reply_path_len = tal_count(reply_path); + u16 rawmsg_len = tal_count(rawmsg); + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_GOSSIPD_GOT_ONIONMSG_TO_US); + if (!blinding_in) + towire_bool(&p, false); + else { + towire_bool(&p, true); + towire_pubkey(&p, blinding_in); + } + if (!reply_blinding) + towire_bool(&p, false); + else { + towire_bool(&p, true); + towire_pubkey(&p, reply_blinding); + } + towire_u16(&p, reply_path_len); + for (size_t i = 0; i < reply_path_len; i++) + towire_onionmsg_path(&p, reply_path[i]); + towire_u16(&p, rawmsg_len); + towire_u8_array(&p, rawmsg, rawmsg_len); + + return memcheck(p, tal_count(p)); +} +bool fromwire_gossipd_got_onionmsg_to_us(const tal_t *ctx, const void *p, struct pubkey **blinding_in, struct pubkey **reply_blinding, struct onionmsg_path ***reply_path, u8 **rawmsg) +{ + u16 reply_path_len; + u16 rawmsg_len; + + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_GOSSIPD_GOT_ONIONMSG_TO_US) + return false; + if (!fromwire_bool(&cursor, &plen)) + *blinding_in = NULL; + else { + *blinding_in = tal(ctx, struct pubkey); + fromwire_pubkey(&cursor, &plen, *blinding_in); + } + if (!fromwire_bool(&cursor, &plen)) + *reply_blinding = NULL; + else { + *reply_blinding = tal(ctx, struct pubkey); + fromwire_pubkey(&cursor, &plen, *reply_blinding); + } + reply_path_len = fromwire_u16(&cursor, &plen); + // 2nd case reply_path + *reply_path = reply_path_len ? tal_arr(ctx, struct onionmsg_path *, reply_path_len) : NULL; + for (size_t i = 0; i < reply_path_len; i++) + (*reply_path)[i] = fromwire_onionmsg_path(*reply_path, &cursor, &plen); + rawmsg_len = fromwire_u16(&cursor, &plen); + // 2nd case rawmsg + *rawmsg = rawmsg_len ? tal_arr(ctx, u8, rawmsg_len) : NULL; + fromwire_u8_array(&cursor, &plen, *rawmsg, rawmsg_len); + return cursor != NULL; +} + +/* WIRE: GOSSIPD_GOT_ONIONMSG_FORWARD */ +u8 *towire_gossipd_got_onionmsg_forward(const tal_t *ctx, const struct short_channel_id *next_scid, const struct node_id *next_node_id, const struct pubkey *next_blinding, const u8 next_onion[1366]) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_GOSSIPD_GOT_ONIONMSG_FORWARD); + if (!next_scid) + towire_bool(&p, false); + else { + towire_bool(&p, true); + towire_short_channel_id(&p, next_scid); + } + if (!next_node_id) + towire_bool(&p, false); + else { + towire_bool(&p, true); + towire_node_id(&p, next_node_id); + } + if (!next_blinding) + towire_bool(&p, false); + else { + towire_bool(&p, true); + towire_pubkey(&p, next_blinding); + } + towire_u8_array(&p, next_onion, 1366); + + return memcheck(p, tal_count(p)); +} +bool fromwire_gossipd_got_onionmsg_forward(const tal_t *ctx, const void *p, struct short_channel_id **next_scid, struct node_id **next_node_id, struct pubkey **next_blinding, u8 next_onion[1366]) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_GOSSIPD_GOT_ONIONMSG_FORWARD) + return false; + if (!fromwire_bool(&cursor, &plen)) + *next_scid = NULL; + else { + *next_scid = tal(ctx, struct short_channel_id); + fromwire_short_channel_id(&cursor, &plen, *next_scid); + } + if (!fromwire_bool(&cursor, &plen)) + *next_node_id = NULL; + else { + *next_node_id = tal(ctx, struct node_id); + fromwire_node_id(&cursor, &plen, *next_node_id); + } + if (!fromwire_bool(&cursor, &plen)) + *next_blinding = NULL; + else { + *next_blinding = tal(ctx, struct pubkey); + fromwire_pubkey(&cursor, &plen, *next_blinding); + } + fromwire_u8_array(&cursor, &plen, next_onion, 1366); + return cursor != NULL; +} + +/* WIRE: GOSSIPD_SEND_ONIONMSG */ +/* Lightningd tells us to send a onion message. */ +u8 *towire_gossipd_send_onionmsg(const tal_t *ctx, const struct node_id *id, const u8 onion[1366], const struct pubkey *blinding) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_GOSSIPD_SEND_ONIONMSG); + towire_node_id(&p, id); + towire_u8_array(&p, onion, 1366); + if (!blinding) + towire_bool(&p, false); + else { + towire_bool(&p, true); + towire_pubkey(&p, blinding); + } + + return memcheck(p, tal_count(p)); +} +bool fromwire_gossipd_send_onionmsg(const tal_t *ctx, const void *p, struct node_id *id, u8 onion[1366], struct pubkey **blinding) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_GOSSIPD_SEND_ONIONMSG) + return false; + fromwire_node_id(&cursor, &plen, id); + fromwire_u8_array(&cursor, &plen, onion, 1366); + if (!fromwire_bool(&cursor, &plen)) + *blinding = NULL; + else { + *blinding = tal(ctx, struct pubkey); + fromwire_pubkey(&cursor, &plen, *blinding); + } + return cursor != NULL; +} +// SHA256STAMP:45335ac4c553938ed7c2d63344d80465eca1ff70ab8ec750e3d0305f81acdad5 diff --git a/gossipd/gossipd_wiregen.h b/gossipd/gossipd_wiregen.h index 29f89ab98..4139cf874 100644 --- a/gossipd/gossipd_wiregen.h +++ b/gossipd/gossipd_wiregen.h @@ -60,6 +60,11 @@ enum gossipd_wire { WIRE_GOSSIPD_GET_INCOMING_CHANNELS_REPLY = 3125, /* master -> gossipd: blockheight increased. */ WIRE_GOSSIPD_NEW_BLOCKHEIGHT = 3026, + /* Tell lightningd we got a onion message (for us */ + WIRE_GOSSIPD_GOT_ONIONMSG_TO_US = 3142, + WIRE_GOSSIPD_GOT_ONIONMSG_FORWARD = 3143, + /* Lightningd tells us to send a onion message. */ + WIRE_GOSSIPD_SEND_ONIONMSG = 3040, }; const char *gossipd_wire_name(int e); @@ -197,6 +202,20 @@ bool fromwire_gossipd_get_incoming_channels_reply(const tal_t *ctx, const void * u8 *towire_gossipd_new_blockheight(const tal_t *ctx, u32 blockheight); bool fromwire_gossipd_new_blockheight(const void *p, u32 *blockheight); +/* WIRE: GOSSIPD_GOT_ONIONMSG_TO_US */ +/* Tell lightningd we got a onion message (for us */ +u8 *towire_gossipd_got_onionmsg_to_us(const tal_t *ctx, const struct pubkey *blinding_in, const struct pubkey *reply_blinding, const struct onionmsg_path **reply_path, const u8 *rawmsg); +bool fromwire_gossipd_got_onionmsg_to_us(const tal_t *ctx, const void *p, struct pubkey **blinding_in, struct pubkey **reply_blinding, struct onionmsg_path ***reply_path, u8 **rawmsg); + +/* WIRE: GOSSIPD_GOT_ONIONMSG_FORWARD */ +u8 *towire_gossipd_got_onionmsg_forward(const tal_t *ctx, const struct short_channel_id *next_scid, const struct node_id *next_node_id, const struct pubkey *next_blinding, const u8 next_onion[1366]); +bool fromwire_gossipd_got_onionmsg_forward(const tal_t *ctx, const void *p, struct short_channel_id **next_scid, struct node_id **next_node_id, struct pubkey **next_blinding, u8 next_onion[1366]); + +/* WIRE: GOSSIPD_SEND_ONIONMSG */ +/* Lightningd tells us to send a onion message. */ +u8 *towire_gossipd_send_onionmsg(const tal_t *ctx, const struct node_id *id, const u8 onion[1366], const struct pubkey *blinding); +bool fromwire_gossipd_send_onionmsg(const tal_t *ctx, const void *p, struct node_id *id, u8 onion[1366], struct pubkey **blinding); + #endif /* LIGHTNING_GOSSIPD_GOSSIPD_WIREGEN_H */ -// SHA256STAMP:ae8bf4f19cc3dd086b9a20b8bc034d93d8ef066e901279de09fe2fd189f1344b +// SHA256STAMP:45335ac4c553938ed7c2d63344d80465eca1ff70ab8ec750e3d0305f81acdad5 diff --git a/lightningd/channel.c b/lightningd/channel.c index 9b88346de..f8d82142e 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -355,13 +355,21 @@ struct channel *active_channel_by_id(struct lightningd *ld, struct channel *active_channel_by_scid(struct lightningd *ld, const struct short_channel_id *scid) +{ + struct channel *chan = any_channel_by_scid(ld, scid); + if (chan && !channel_active(chan)) + chan = NULL; + return chan; +} + +struct channel *any_channel_by_scid(struct lightningd *ld, + const struct short_channel_id *scid) { struct peer *p; struct channel *chan; list_for_each(&ld->peers, p, list) { list_for_each(&p->channels, chan, list) { - if (channel_active(chan) - && chan->scid + if (chan->scid && short_channel_id_eq(scid, chan->scid)) return chan; } diff --git a/lightningd/channel.h b/lightningd/channel.h index b9a573fe2..fb4a1b008 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -263,6 +263,8 @@ struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid); struct channel *active_channel_by_scid(struct lightningd *ld, const struct short_channel_id *scid); +struct channel *any_channel_by_scid(struct lightningd *ld, + const struct short_channel_id *scid); /* Get channel by channel_id, optionally returning uncommitted_channel. */ struct channel *channel_by_cid(struct lightningd *ld, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 757ea3456..7d915b91a 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -522,17 +521,6 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_SEND_ERROR_REPLY: handle_error_channel(sd->channel, msg); break; -#if EXPERIMENTAL_FEATURES - case WIRE_GOT_ONIONMSG_TO_US: - handle_onionmsg_to_us(sd->channel, msg); - break; - case WIRE_GOT_ONIONMSG_FORWARD: - handle_onionmsg_forward(sd->channel, msg); - break; -#else - case WIRE_GOT_ONIONMSG_TO_US: - case WIRE_GOT_ONIONMSG_FORWARD: -#endif /* And we never get these from channeld. */ case WIRE_CHANNELD_INIT: case WIRE_CHANNELD_SEND_TX_SIGS: @@ -548,7 +536,6 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_FEERATES: case WIRE_CHANNELD_SPECIFIC_FEERATES: case WIRE_CHANNELD_DEV_MEMLEAK: - case WIRE_SEND_ONIONMSG: /* Replies go to requests. */ case WIRE_CHANNELD_OFFER_HTLC_REPLY: case WIRE_CHANNELD_DEV_REENABLE_COMMIT_REPLY: diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index a3b608ff5..f493d5acc 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -149,6 +150,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIPD_DEV_COMPACT_STORE: case WIRE_GOSSIPD_DEV_SET_TIME: case WIRE_GOSSIPD_NEW_BLOCKHEIGHT: + case WIRE_GOSSIPD_SEND_ONIONMSG: /* This is a reply, so never gets through to here. */ case WIRE_GOSSIPD_GETNODES_REPLY: case WIRE_GOSSIPD_GETROUTE_REPLY: @@ -159,6 +161,18 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIPD_GET_STRIPPED_CUPDATE_REPLY: break; +#if EXPERIMENTAL_FEATURES + case WIRE_GOSSIPD_GOT_ONIONMSG_TO_US: + handle_onionmsg_to_us(gossip->ld, msg); + break; + case WIRE_GOSSIPD_GOT_ONIONMSG_FORWARD: + handle_onionmsg_forward(gossip->ld, msg); + break; +#else + case WIRE_GOSSIPD_GOT_ONIONMSG_TO_US: + case WIRE_GOSSIPD_GOT_ONIONMSG_FORWARD: + break; +#endif case WIRE_GOSSIPD_PING_REPLY: ping_reply(gossip, msg); break; @@ -193,7 +207,7 @@ void gossip_init(struct lightningd *ld, int connectd_fd) u8 *msg; int hsmfd; - hsmfd = hsm_get_global_fd(ld, HSM_CAP_SIGN_GOSSIP); + hsmfd = hsm_get_global_fd(ld, HSM_CAP_ECDH|HSM_CAP_SIGN_GOSSIP); ld->gossip = new_global_subd(ld, "lightning_gossipd", gossipd_wire_name, gossip_msg, diff --git a/lightningd/onion_message.c b/lightningd/onion_message.c index a8083d64a..faaadf6eb 100644 --- a/lightningd/onion_message.c +++ b/lightningd/onion_message.c @@ -1,6 +1,5 @@ -#include #include -#include +#include #include #include #include @@ -88,40 +87,8 @@ REGISTER_PLUGIN_HOOK(onion_message_blinded, onion_message_serialize, struct onion_message_hook_payload *); -/* Returns false if we can't tell it */ -static bool make_peer_send(struct lightningd *ld, - struct channel *dst, const u8 *msg TAKES) +void handle_onionmsg_to_us(struct lightningd *ld, const u8 *msg) { - /* Take ownership of msg (noop if it's taken) */ - msg = tal_dup_talarr(tmpctx, u8, msg); - - if (!dst) { - log_debug(ld->log, "Can't send %s: no channel", - channeld_wire_name(fromwire_peektype(msg))); - return false; - } - - if (!dst->owner) { - log_debug(ld->log, "Can't send %s: not connected", - channeld_wire_name(fromwire_peektype(msg))); - return false; - } - - /* FIXME: We should allow this for closingd too, and we should - * allow incoming via openingd!. */ - if (!streq(dst->owner->name, "channeld")) { - log_debug(ld->log, "Can't send %s: owned by %s", - channeld_wire_name(fromwire_peektype(msg)), - dst->owner->name); - return false; - } - subd_send_msg(dst->owner, take(msg)); - return true; -} - -void handle_onionmsg_to_us(struct channel *channel, const u8 *msg) -{ - struct lightningd *ld = channel->peer->ld; struct onion_message_hook_payload *payload; u8 *submsg; size_t submsglen; @@ -129,30 +96,30 @@ void handle_onionmsg_to_us(struct channel *channel, const u8 *msg) payload = tal(ld, struct onion_message_hook_payload); payload->om = tlv_onionmsg_payload_new(payload); - if (!fromwire_got_onionmsg_to_us(payload, msg, - &payload->blinding_in, - &payload->reply_blinding, - &payload->reply_path, - &submsg)) { - channel_internal_error(channel, "bad got_onionmsg_tous: %s", - tal_hex(tmpctx, msg)); + if (!fromwire_gossipd_got_onionmsg_to_us(payload, msg, + &payload->blinding_in, + &payload->reply_blinding, + &payload->reply_path, + &submsg)) { + log_broken(ld->log, "bad got_onionmsg_tous: %s", + tal_hex(tmpctx, msg)); return; } submsglen = tal_bytelen(submsg); if (!fromwire_onionmsg_payload(cast_const2(const u8 **, &submsg), &submsglen, payload->om)) { - channel_internal_error(channel, "bad got_onionmsg_tous om: %s", - tal_hex(tmpctx, msg)); + log_broken(ld->log, "bad got_onionmsg_tous om: %s", + tal_hex(tmpctx, msg)); return; } if (payload->reply_path && !payload->reply_blinding) { - log_broken(channel->log, + log_broken(ld->log, "No reply blinding, ignoring reply path"); payload->reply_path = tal_free(payload->reply_path); } - log_debug(channel->log, "Got onionmsg%s%s", + log_debug(ld->log, "Got onionmsg%s%s", payload->reply_blinding ? " reply_blinding": "", payload->reply_path ? " reply_path": ""); @@ -162,35 +129,40 @@ void handle_onionmsg_to_us(struct channel *channel, const u8 *msg) plugin_hook_call_onion_message(ld, payload); } -void handle_onionmsg_forward(struct channel *channel, const u8 *msg) +void handle_onionmsg_forward(struct lightningd *ld, const u8 *msg) { - struct lightningd *ld = channel->peer->ld; struct short_channel_id *next_scid; struct node_id *next_node; struct pubkey *next_blinding; u8 onion[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)]; - struct channel *outchan; - if (!fromwire_got_onionmsg_forward(msg, msg, &next_scid, &next_node, - &next_blinding, onion)) { - channel_internal_error(channel, "bad got_onionmsg_forward: %s", - tal_hex(tmpctx, msg)); + if (!fromwire_gossipd_got_onionmsg_forward(msg, msg, &next_scid, + &next_node, + &next_blinding, onion)) { + log_broken(ld->log, "bad got_onionmsg_forward: %s", + tal_hex(tmpctx, msg)); return; } - if (next_scid) - outchan = active_channel_by_scid(ld, next_scid); - else if (next_node) { - struct peer *p = peer_by_id(ld, next_node); - if (p) - outchan = peer_active_channel(p); - else - outchan = NULL; - } else - outchan = NULL; + if (next_scid) { + struct channel *outchan = any_channel_by_scid(ld, next_scid); + if (outchan) + next_node = &outchan->peer->id; + } - make_peer_send(ld, outchan, - take(towire_send_onionmsg(NULL, onion, next_blinding))); + if (!next_node) { + log_debug(ld->log, "Cannot forward onionmsg to %s", + next_scid ? type_to_string(tmpctx, + struct short_channel_id, + next_scid) + : "unspecified dest"); + } else { + subd_send_msg(ld->gossip, + take(towire_gossipd_send_onionmsg(NULL, + next_node, + onion, + next_blinding))); + } } struct hop { @@ -421,7 +393,6 @@ static struct command_result *json_send_onion_message(struct command *cmd, struct sphinx_path *sphinx_path; struct onionpacket *op; struct secret *path_secrets; - struct channel *first_hop; struct node_id first_id; if (!param(cmd, buffer, params, @@ -430,10 +401,11 @@ static struct command_result *json_send_onion_message(struct command *cmd, NULL)) return command_param_failed(); - /* FIXME: Allow sending to non-channel peers! */ node_id_from_pubkey(&first_id, &hops[0].id); - first_hop = active_channel_by_id(cmd->ld, &first_id, NULL); - if (!first_hop) + + /* Sanity check first; gossipd doesn't bother telling us if peer + * can't be reached. */ + if (!peer_by_id(cmd->ld, &first_id)) return command_fail(cmd, LIGHTNINGD, "Unknown first peer"); /* Create an onion which encodes this. */ @@ -452,11 +424,10 @@ static struct command_result *json_send_onion_message(struct command *cmd, return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Creating onion failed (tlvs too long?)"); - if (!make_peer_send(cmd->ld, first_hop, - take(towire_send_onionmsg(NULL, - serialize_onionpacket(tmpctx, op), - NULL)))) - return command_fail(cmd, LIGHTNINGD, "First peer not ready"); + subd_send_msg(cmd->ld->gossip, + take(towire_gossipd_send_onionmsg(NULL, &first_id, + serialize_onionpacket(tmpctx, op), + NULL))); return command_success(cmd, json_stream_success(cmd)); } diff --git a/lightningd/onion_message.h b/lightningd/onion_message.h index c2a2099a8..748be5d93 100644 --- a/lightningd/onion_message.h +++ b/lightningd/onion_message.h @@ -3,9 +3,9 @@ #include "config.h" #include -struct channel; +struct lightningd; -void handle_onionmsg_to_us(struct channel *channel, const u8 *msg); -void handle_onionmsg_forward(struct channel *channel, const u8 *msg); +void handle_onionmsg_to_us(struct lightningd *ld, const u8 *msg); +void handle_onionmsg_forward(struct lightningd *ld, const u8 *msg); #endif /* LIGHTNING_LIGHTNINGD_ONION_MESSAGE_H */ diff --git a/wire/peer_wire.c b/wire/peer_wire.c index 7c4467113..a2602cc78 100644 --- a/wire/peer_wire.c +++ b/wire/peer_wire.c @@ -62,6 +62,9 @@ bool is_msg_for_gossipd(const u8 *cursor) case WIRE_REPLY_CHANNEL_RANGE: case WIRE_PING: case WIRE_PONG: +#if EXPERIMENTAL_FEATURES + case WIRE_ONION_MESSAGE: +#endif return true; case WIRE_INIT: case WIRE_ERROR: @@ -83,7 +86,6 @@ bool is_msg_for_gossipd(const u8 *cursor) case WIRE_ANNOUNCEMENT_SIGNATURES: case WIRE_GOSSIP_TIMESTAMP_FILTER: #if EXPERIMENTAL_FEATURES - case WIRE_ONION_MESSAGE: case WIRE_TX_ADD_INPUT: case WIRE_TX_REMOVE_INPUT: case WIRE_TX_ADD_OUTPUT: