From 96ad0e70447132f4588b064925f46d19dc039abb Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 22 Mar 2018 15:11:24 +0100 Subject: [PATCH] gossip: Extract network changes into their own functions Moves any modifications based on an incoming gossip message into its own function separate from the message verification. This allows us to skip verification when reading messages from a trusted source, e.g., the gossip_store, speeding up the gossip replay. Signed-off-by: Christian Decker --- gossipd/routing.c | 145 ++++++++++++++++++++++++++++++++-------------- gossipd/routing.h | 31 ++++++++++ 2 files changed, 131 insertions(+), 45 deletions(-) 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 */