diff --git a/gossipd/gossip.c b/gossipd/gossip.c index b8629c8e8..e8b852236 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ #include #include #include +#include #define HSM_FD 3 @@ -371,12 +373,69 @@ static struct io_plan *owner_msg_in(struct io_conn *conn, static struct io_plan *nonlocal_dump_gossip(struct io_conn *conn, struct daemon_conn *dc); -static void handle_gossip_msg(struct routing_state *rstate, u8 *msg) +/* Create a node_announcement with the given signature. It may be NULL + * in the case we need to create a provisional announcement for the + * HSM to sign. This is typically called twice: once with the dummy + * signature to get it signed and a second time to build the full + * packet with the signature. The timestamp is handed in since that is + * the only thing that may change between the dummy creation and the + * call with a signature.*/ +static u8 *create_node_announcement(const tal_t *ctx, struct daemon *daemon, + secp256k1_ecdsa_signature *sig, + u32 timestamp) { + u8 *features = NULL; + u8 *addresses = tal_arr(ctx, u8, 0); + u8 *announcement; + size_t i; + if (!sig) { + sig = tal(ctx, secp256k1_ecdsa_signature); + memset(sig, 0, sizeof(*sig)); + } + for (i = 0; i < tal_count(daemon->wireaddrs); i++) + towire_wireaddr(&addresses, daemon->wireaddrs+i); + + announcement = + towire_node_announcement(ctx, sig, features, timestamp, + &daemon->id, daemon->rgb, daemon->alias, + addresses); + return announcement; +} + +static void send_node_announcement(struct daemon *daemon) +{ + tal_t *tmpctx = tal_tmpctx(daemon); + u32 timestamp = time_now().ts.tv_sec; + secp256k1_ecdsa_signature sig; + u8 *msg, *nannounce = create_node_announcement(tmpctx, daemon, NULL, timestamp); + + if (!wire_sync_write(HSM_FD, take(towire_hsm_node_announcement_sig_req(tmpctx, nannounce)))) + status_failed(STATUS_FAIL_MASTER_IO, "Could not write to HSM: %s", strerror(errno)); + + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsm_node_announcement_sig_reply(msg, NULL, &sig)) + status_failed(STATUS_FAIL_MASTER_IO, "HSM returned an invalid node_announcement sig"); + + /* We got the signature for out provisional node_announcement back + * from the HSM, create the real announcement and forward it to + * gossipd so it can take care of forwarding it. */ + nannounce = create_node_announcement(tmpctx, daemon, &sig, timestamp); + handle_node_announcement(daemon->rstate, take(nannounce), tal_len(nannounce)); + tal_free(tmpctx); +} + +static void handle_gossip_msg(struct daemon *daemon, u8 *msg) +{ + struct routing_state *rstate = daemon->rstate; int t = fromwire_peektype(msg); switch(t) { case WIRE_CHANNEL_ANNOUNCEMENT: - handle_channel_announcement(rstate, msg, tal_count(msg)); + /* Add the channel_announcement to the routing state, + * it'll tell us whether this is local and signed, so + * we can hand in a node_announcement as well. */ + if(handle_channel_announcement(rstate, msg, tal_count(msg))) { + send_node_announcement(daemon); + } break; case WIRE_NODE_ANNOUNCEMENT: @@ -489,7 +548,7 @@ static struct io_plan *peer_msgin(struct io_conn *conn, case WIRE_CHANNEL_ANNOUNCEMENT: case WIRE_NODE_ANNOUNCEMENT: case WIRE_CHANNEL_UPDATE: - handle_gossip_msg(peer->daemon->rstate, msg); + handle_gossip_msg(peer->daemon, msg); return peer_next_in(conn, peer); case WIRE_PING: @@ -661,7 +720,7 @@ static struct io_plan *owner_msg_in(struct io_conn *conn, int type = fromwire_peektype(msg); if (type == WIRE_CHANNEL_ANNOUNCEMENT || type == WIRE_CHANNEL_UPDATE || type == WIRE_NODE_ANNOUNCEMENT) { - handle_gossip_msg(peer->daemon->rstate, dc->msg_in); + handle_gossip_msg(peer->daemon, dc->msg_in); } else if (type == WIRE_GOSSIP_GET_UPDATE) { handle_get_update(peer, dc->msg_in); } @@ -1161,7 +1220,7 @@ static void handle_forwarded_msg(struct io_conn *conn, struct daemon *daemon, co if (!fromwire_gossip_forwarded_msg(msg, msg, NULL, &payload)) master_badmsg(WIRE_GOSSIP_FORWARDED_MSG, msg); - handle_gossip_msg(daemon->rstate, payload); + handle_gossip_msg(daemon, payload); } static struct io_plan *handshake_out_success(struct io_conn *conn, diff --git a/gossipd/routing.c b/gossipd/routing.c index 736563ff2..1d4dcb812 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -463,12 +463,12 @@ static bool check_channel_announcement( check_signed_hash(&hash, bitcoin2_sig, bitcoin2_key); } -void handle_channel_announcement( +bool handle_channel_announcement( struct routing_state *rstate, const u8 *announce, size_t len) { u8 *serialized; - bool forward = false; + bool forward = false, local, sigfail; secp256k1_ecdsa_signature node_signature_1; secp256k1_ecdsa_signature node_signature_2; struct short_channel_id short_channel_id; @@ -493,7 +493,7 @@ void handle_channel_announcement( &node_id_1, &node_id_2, &bitcoin_key_1, &bitcoin_key_2)) { tal_free(tmpctx); - return; + return false; } /* BOLT #7: @@ -507,7 +507,7 @@ void handle_channel_announcement( type_to_string(tmpctx, struct sha256_double, &chain_hash)); tal_free(tmpctx); - return; + return false; } // FIXME: Check features! @@ -517,24 +517,31 @@ void handle_channel_announcement( type_to_string(trc, struct short_channel_id, &short_channel_id)); - if (!check_channel_announcement(&node_id_1, &node_id_2, &bitcoin_key_1, - &bitcoin_key_2, &node_signature_1, - &node_signature_2, &bitcoin_signature_1, - &bitcoin_signature_2, serialized)) { + local = pubkey_eq(&node_id_1, &rstate->local_id) || + pubkey_eq(&node_id_2, &rstate->local_id); + sigfail = !check_channel_announcement( + &node_id_1, &node_id_2, &bitcoin_key_1, &bitcoin_key_2, + &node_signature_1, &node_signature_2, &bitcoin_signature_1, + &bitcoin_signature_2, serialized); + + if (sigfail && !local) { status_trace( "Signature verification of channel announcement failed"); tal_free(tmpctx); - return; + return false; } forward |= add_channel_direction(rstate, &node_id_1, &node_id_2, &short_channel_id, serialized); forward |= add_channel_direction(rstate, &node_id_2, &node_id_1, &short_channel_id, serialized); + if (!forward) { status_trace("Not forwarding channel_announcement"); tal_free(tmpctx); - return; + /* This will not be forwarded so we do not want to + * announce the node either, others might drop it. */ + return false; } u8 *tag = tal_arr(tmpctx, u8, 0); @@ -543,6 +550,7 @@ void handle_channel_announcement( tag, serialized); tal_free(tmpctx); + return local; } void handle_channel_update(struct routing_state *rstate, const u8 *update, size_t len) diff --git a/gossipd/routing.h b/gossipd/routing.h index 9c51f9512..8a931333a 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -83,6 +83,9 @@ struct routing_state { struct broadcast_state *broadcasts; struct sha256_double chain_hash; + + /* Our own ID so we can identify local channels */ + struct pubkey local_id; }; struct route_hop { @@ -117,7 +120,15 @@ struct node_connection *get_connection_by_scid(const struct routing_state *rstat const u8 direction); /* Handlers for incoming messages */ -void handle_channel_announcement(struct routing_state *rstate, const u8 *announce, size_t len); + +/** + * handle_channel_announcement -- Add channel announcement to state + * + * Returns true if the channel was fully signed and is local. This + * means that if we haven't sent a node_announcement just yet, now + * would be a good time. + */ +bool handle_channel_announcement(struct routing_state *rstate, const u8 *announce, size_t len); void handle_channel_update(struct routing_state *rstate, const u8 *update, size_t len); void handle_node_announcement(struct routing_state *rstate, const u8 *node, size_t len);