diff --git a/gossipd/routing.c b/gossipd/routing.c index 091c5e01f..7127ec320 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -595,6 +595,41 @@ static void destroy_pending_cannouncement(struct pending_cannouncement *pending, list_del_from(&rstate->pending_cannouncement, &pending->list); } +void routing_add_channel_announcement(struct routing_state *rstate, + const u8 *msg TAKES, u64 satoshis) +{ + struct chan *chan; + secp256k1_ecdsa_signature node_signature_1, node_signature_2; + secp256k1_ecdsa_signature bitcoin_signature_1, bitcoin_signature_2; + u8 *features; + struct bitcoin_blkid chain_hash; + struct short_channel_id scid; + struct pubkey node_id_1; + struct pubkey node_id_2; + struct pubkey bitcoin_key_1; + struct pubkey bitcoin_key_2; + fromwire_channel_announcement( + tmpctx, msg, &node_signature_1, &node_signature_2, + &bitcoin_signature_1, &bitcoin_signature_2, &features, &chain_hash, + &scid, &node_id_1, &node_id_2, &bitcoin_key_1, &bitcoin_key_2); + /* The channel may already exist if it was non-public from + * local_add_channel(); normally we don't accept new + * channel_announcements. See handle_channel_announcement. */ + chan = get_channel(rstate, &scid); + if (!chan) + chan = new_chan(rstate, &scid, &node_id_1, &node_id_2); + + /* Channel is now public. */ + chan->public = true; + chan->satoshis = satoshis; + + if (replace_broadcast(chan, rstate->broadcasts, + &chan->channel_announce_msgidx, take(msg))) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Announcement %s was replaced?", + tal_hex(tmpctx, msg)); +} + u8 *handle_channel_announcement(struct routing_state *rstate, const u8 *announce TAKES, const struct short_channel_id **scid, @@ -758,7 +793,6 @@ bool handle_pending_cannouncement(struct routing_state *rstate, bool local; const u8 *s; struct pending_cannouncement *pending; - struct chan *chan; pending = find_pending_cannouncement(rstate, scid); if (!pending) @@ -798,28 +832,9 @@ bool handle_pending_cannouncement(struct routing_state *rstate, return false; } - /* The channel may already exist if it was non-public from - * local_add_channel(); normally we don't accept new - * channel_announcements. See handle_channel_announcement. */ - chan = get_channel(rstate, scid); - if (!chan) - chan = new_chan(rstate, scid, - &pending->node_id_1, - &pending->node_id_2); - - /* Channel is now public. */ - chan->public = true; - chan->satoshis = satoshis; - - if (replace_broadcast(chan, rstate->broadcasts, - &chan->channel_announce_msgidx, - pending->announce)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Announcement %s was replaced?", - tal_hex(tmpctx, pending->announce)); - if (pending->store) gossip_store_append(rstate->store, pending->announce); + routing_add_channel_announcement(rstate, pending->announce, satoshis); local = pubkey_eq(&pending->node_id_1, &rstate->local_id) || pubkey_eq(&pending->node_id_2, &rstate->local_id); @@ -890,6 +905,37 @@ void set_connection_values(struct chan *chan, } } +void routing_add_channel_update(struct routing_state *rstate, + const u8 *update TAKES) +{ + secp256k1_ecdsa_signature signature; + struct short_channel_id short_channel_id; + u32 timestamp; + u16 flags; + u16 expiry; + u64 htlc_minimum_msat; + u32 fee_base_msat; + u32 fee_proportional_millionths; + struct bitcoin_blkid chain_hash; + struct chan *chan; + u8 direction; + + fromwire_channel_update(update, &signature, &chain_hash, + &short_channel_id, ×tamp, &flags, &expiry, + &htlc_minimum_msat, &fee_base_msat, + &fee_proportional_millionths); + chan = get_channel(rstate, &short_channel_id); + direction = flags & 0x1; + set_connection_values(chan, direction, fee_base_msat, + fee_proportional_millionths, expiry, + (flags & ROUTING_FLAGS_DISABLED) == 0, timestamp, + htlc_minimum_msat); + + replace_broadcast(chan, rstate->broadcasts, + &chan->half[direction].channel_update_msgidx, + take(update)); +} + u8 *handle_channel_update(struct routing_state *rstate, const u8 *update, bool store) { @@ -983,20 +1029,9 @@ u8 *handle_channel_update(struct routing_state *rstate, const u8 *update, flags & 0x01, flags & ROUTING_FLAGS_DISABLED ? "DISABLED" : "ACTIVE"); - set_connection_values(chan, direction, - fee_base_msat, - fee_proportional_millionths, - expiry, - (flags & ROUTING_FLAGS_DISABLED) == 0, - timestamp, - htlc_minimum_msat); - if (store) gossip_store_append(rstate->store, serialized); - replace_broadcast(chan, rstate->broadcasts, - &chan->half[direction].channel_update_msgidx, - take(serialized)); - + routing_add_channel_update(rstate, serialized); return NULL; } @@ -1034,6 +1069,36 @@ static struct wireaddr *read_addresses(const tal_t *ctx, const u8 *ser) return wireaddrs; } +void routing_add_node_announcement(struct routing_state *rstate, const u8 *msg TAKES) +{ + struct node *node; + secp256k1_ecdsa_signature signature; + u32 timestamp; + struct pubkey node_id; + u8 rgb_color[3]; + u8 alias[32]; + u8 *features, *addresses; + struct wireaddr *wireaddrs; + fromwire_node_announcement(tmpctx, msg, + &signature, &features, ×tamp, + &node_id, rgb_color, alias, + &addresses); + + node = get_node(rstate, &node_id); + wireaddrs = read_addresses(tmpctx, addresses); + tal_free(node->addresses); + node->addresses = tal_steal(node, wireaddrs); + + node->last_timestamp = timestamp; + memcpy(node->rgb_color, rgb_color, 3); + tal_free(node->alias); + node->alias = tal_dup_arr(node, u8, alias, 32, 0); + + replace_broadcast(node, rstate->broadcasts, + &node->node_announce_msgidx, + take(msg)); +} + u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann, bool store) { @@ -1159,20 +1224,10 @@ u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann, status_trace("Received node_announcement for node %s", type_to_string(tmpctx, struct pubkey, &node_id)); - tal_free(node->addresses); - node->addresses = tal_steal(node, wireaddrs); - - node->last_timestamp = timestamp; - - memcpy(node->rgb_color, rgb_color, 3); - tal_free(node->alias); - node->alias = tal_dup_arr(node, u8, alias, 32, 0); - + /* FIXME: remove store guard */ if (store) gossip_store_append(rstate->store, serialized); - replace_broadcast(node, rstate->broadcasts, - &node->node_announce_msgidx, - take(serialized)); + routing_add_node_announcement(rstate, serialized); return NULL; } diff --git a/gossipd/routing.h b/gossipd/routing.h index bdb8388a3..102ebd43b 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -261,4 +261,35 @@ void route_prune(struct routing_state *rstate); * the direction bit the matching channel should get */ #define get_channel_direction(from, to) (pubkey_cmp(from, to) > 0) +/** + * Add a channel_announcement to the network view without checking it + * + * Directly add the channel to the local network, without checking it first. Use + * this only for messages from trusted sources. Untrusted sources should use the + * @see{handle_channel_announcement} entrypoint to check before adding. + */ +void routing_add_channel_announcement(struct routing_state *rstate, + const u8 *msg TAKES, u64 satoshis); + +/** + * Add a channel_update without checking for errors + * + * Used to actually insert the information in the channel update into the local + * network view. Only use this for messages that are known to be good. For + * untrusted source, requiring verification please use + * @see{handle_channel_update} + */ +void routing_add_channel_update(struct routing_state *rstate, + const u8 *update TAKES); + +/** + * Add a node_announcement to the network view without checking it + * + * Directly add the node being announced to the network view, without verifying + * it. This must be from a trusted source, e.g., gossip_store. For untrusted + * sources (peers) please use @see{handle_node_announcement}. + */ +void routing_add_node_announcement(struct routing_state *rstate, + const u8 *msg TAKES); + #endif /* LIGHTNING_GOSSIPD_ROUTING_H */