diff --git a/gossipd/gossip.c b/gossipd/gossip.c index f38e7ece1..189861d19 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -83,8 +83,6 @@ struct daemon { /* To make sure our node_announcement timestamps increase */ u32 last_announce_timestamp; - - u32 update_channel_interval; }; /* Peers we're trying to reach. */ @@ -1331,19 +1329,19 @@ static void gossip_send_keepalive_update(struct routing_state *rstate, } -static void gossip_prune_network(struct daemon *daemon) +static void gossip_refresh_network(struct daemon *daemon) { u64 now = time_now().ts.tv_sec; struct node_map_iter it; /* Anything below this highwater mark ought to be pruned */ - s64 highwater = now - 2*daemon->update_channel_interval; + s64 highwater = now - daemon->rstate->prune_timeout; struct node *n; const tal_t *pruned = tal_tmpctx(daemon); /* Schedule next run now */ new_reltimer(&daemon->timers, daemon, - time_from_sec(daemon->update_channel_interval/2), - gossip_prune_network, daemon); + time_from_sec(daemon->rstate->prune_timeout/4), + gossip_refresh_network, daemon); /* Find myself in the network */ n = get_node(daemon->rstate, &daemon->id); @@ -1361,7 +1359,7 @@ static void gossip_prune_network(struct daemon *daemon) continue; } - if (now - nc->last_timestamp < daemon->update_channel_interval) { + if (now - nc->last_timestamp < daemon->rstate->prune_timeout / 2) { /* No need to send a keepalive update message */ continue; } @@ -1522,21 +1520,24 @@ static struct io_plan *gossip_init(struct daemon_conn *master, { struct bitcoin_blkid chain_hash; u16 port; + u32 update_channel_interval; if (!fromwire_gossipctl_init( daemon, msg, &daemon->broadcast_interval, &chain_hash, &daemon->id, &port, &daemon->globalfeatures, &daemon->localfeatures, &daemon->wireaddrs, daemon->rgb, - daemon->alias, &daemon->update_channel_interval)) { + daemon->alias, &update_channel_interval)) { master_badmsg(WIRE_GOSSIPCTL_INIT, msg); } - daemon->rstate = new_routing_state(daemon, &chain_hash, &daemon->id); + /* Prune time is twice update time */ + daemon->rstate = new_routing_state(daemon, &chain_hash, &daemon->id, + update_channel_interval * 2); setup_listeners(daemon, port); new_reltimer(&daemon->timers, daemon, - time_from_sec(daemon->update_channel_interval/2), - gossip_prune_network, daemon); + time_from_sec(daemon->rstate->prune_timeout/4), + gossip_refresh_network, daemon); return daemon_conn_read_next(master->conn, master); } diff --git a/gossipd/routing.c b/gossipd/routing.c index fb046e467..403ada47e 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -94,13 +94,15 @@ static struct node_map *empty_node_map(const tal_t *ctx) struct routing_state *new_routing_state(const tal_t *ctx, const struct bitcoin_blkid *chain_hash, - const struct pubkey *local_id) + const struct pubkey *local_id, + u32 prune_timeout) { struct routing_state *rstate = tal(ctx, struct routing_state); rstate->nodes = empty_node_map(rstate); rstate->broadcasts = new_broadcast_state(rstate); rstate->chain_hash = *chain_hash; rstate->local_id = *local_id; + rstate->prune_timeout = prune_timeout; list_head_init(&rstate->pending_cannouncement); uintmap_init(&rstate->channels); @@ -242,9 +244,9 @@ static struct node_connection *new_node_connection(struct routing_state *rstate, c->unroutable_until = 0; c->active = false; c->flags = idx; - /* We haven't seen channel_update: give it an hour before we prune, + /* We haven't seen channel_update: make it halfway to prune time, * which should be older than any update we'd see. */ - c->last_timestamp = time_now().ts.tv_sec - (1209600 - 3600); + c->last_timestamp = time_now().ts.tv_sec - rstate->prune_timeout/2; /* Hook it into in/out arrays. */ chan->connections[idx] = c; diff --git a/gossipd/routing.h b/gossipd/routing.h index 7ba222292..5c44225ad 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -157,6 +157,9 @@ struct routing_state { /* Our own ID so we can identify local channels */ struct pubkey local_id; + /* How old does a channel have to be before we prune it? */ + u32 prune_timeout; + /* A map of channels indexed by short_channel_ids */ UINTMAP(struct routing_channel*) channels; }; @@ -177,7 +180,8 @@ struct route_hop { struct routing_state *new_routing_state(const tal_t *ctx, const struct bitcoin_blkid *chain_hash, - const struct pubkey *local_id); + const struct pubkey *local_id, + u32 prune_timeout); struct routing_channel *new_routing_channel(struct routing_state *rstate, const struct short_channel_id *scid, @@ -236,12 +240,7 @@ void routing_failure(struct routing_state *rstate, void mark_channel_unroutable(struct routing_state *rstate, const struct short_channel_id *channel); -/* Add the connection to the channel */ -void channel_add_connection(struct routing_state *rstate, - struct routing_channel *chan, - struct node_connection *nc); - -void delete_connection(struct routing_channel *chan, int idx); +void route_prune(struct routing_state *rstate); /* Utility function that, given a source and a destination, gives us * the direction bit the matching channel should get */ diff --git a/gossipd/test/run-bench-find_route.c b/gossipd/test/run-bench-find_route.c index 59b1a196e..fed7d756e 100644 --- a/gossipd/test/run-bench-find_route.c +++ b/gossipd/test/run-bench-find_route.c @@ -191,7 +191,7 @@ int main(int argc, char *argv[]) secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); - rstate = new_routing_state(ctx, &zerohash, &me); + rstate = new_routing_state(ctx, &zerohash, &me, 0); opt_register_noarg("--perfme", opt_set_bool, &perfme, "Run perfme-start and perfme-stop around benchmark"); diff --git a/gossipd/test/run-find_route-specific.c b/gossipd/test/run-find_route-specific.c index c9dec5b60..b34c979a5 100644 --- a/gossipd/test/run-find_route-specific.c +++ b/gossipd/test/run-find_route-specific.c @@ -110,7 +110,7 @@ int main(void) strlen("02ea622d5c8d6143f15ed3ce1d501dd0d3d09d3b1c83a44d0034949f8a9ab60f06"), &c); - rstate = new_routing_state(ctx, &zerohash, &a); + rstate = new_routing_state(ctx, &zerohash, &a, 0); /* [{'active': True, 'short_id': '6990:2:1/1', 'fee_per_kw': 10, 'delay': 5, 'flags': 1, 'destination': '0230ad0e74ea03976b28fda587bb75bdd357a1938af4424156a18265167f5e40ae', 'source': '02ea622d5c8d6143f15ed3ce1d501dd0d3d09d3b1c83a44d0034949f8a9ab60f06', 'last_update': 1504064344}, */ nc = get_or_make_connection(rstate, &c, &b, "6990:2:1"); diff --git a/gossipd/test/run-find_route.c b/gossipd/test/run-find_route.c index 59015f63f..6ad29d9c5 100644 --- a/gossipd/test/run-find_route.c +++ b/gossipd/test/run-find_route.c @@ -146,7 +146,7 @@ int main(void) | SECP256K1_CONTEXT_SIGN); memset(&tmp, 'a', sizeof(tmp)); - rstate = new_routing_state(ctx, &zerohash, &a); + rstate = new_routing_state(ctx, &zerohash, &a, 0); pubkey_from_privkey(&tmp, &a); new_node(rstate, &a); diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index 4caed7938..134bde8ba 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -1854,7 +1854,7 @@ class LightningDTests(BaseLightningDTests): assert [c['active'] for c in l2.rpc.listchannels()['channels']] == [True, True] assert [c['public'] for c in l2.rpc.listchannels()['channels']] == [True, True] - @unittest.skip("Temporarily broken for short pruning times") + @unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1 for --dev-broadcast-interval") def test_gossip_pruning(self): """ Create channel and see it being updated in time before pruning """ @@ -1889,6 +1889,12 @@ class LightningDTests(BaseLightningDTests): ]) # Now kill l3, so that l2 and l1 can prune it from their view after 10 seconds + + # FIXME: This sleep() masks a real bug: that channeld sends a + # channel_update message (to disable the channel) with same + # timestamp as the last keepalive, and thus is ignored. The minimal + # fix is to backdate the keepalives 1 second, but maybe we should + # simply have gossipd generate all updates? time.sleep(1) l3.stop()