diff --git a/gossipd/gossip_store.c b/gossipd/gossip_store.c index 13fc23dc3..97dc454c8 100644 --- a/gossipd/gossip_store.c +++ b/gossipd/gossip_store.c @@ -509,7 +509,7 @@ int gossip_store_readonly_fd(struct gossip_store *gs) return fd; } -void gossip_store_load(struct routing_state *rstate, struct gossip_store *gs) +bool gossip_store_load(struct routing_state *rstate, struct gossip_store *gs) { struct gossip_hdr hdr; u32 msglen, checksum; @@ -519,6 +519,8 @@ void gossip_store_load(struct routing_state *rstate, struct gossip_store *gs) size_t stats[] = {0, 0, 0, 0}; struct timeabs start = time_now(); const u8 *chan_ann = NULL; + bool contents_ok; + u32 last_timestamp = 0; u64 chan_ann_off = 0; /* Spurious gcc-9 (Ubuntu 9-20190402-1ubuntu1) 9.0.1 20190402 (experimental) warning */ gs->writable = false; @@ -571,6 +573,9 @@ void gossip_store_load(struct routing_state *rstate, struct gossip_store *gs) /* Save for channel_amount (next msg) */ chan_ann = tal_steal(gs, msg); chan_ann_off = gs->len; + /* If we have a channel_announcement, that's a reasonable + * timestamp to use. */ + last_timestamp = be32_to_cpu(hdr.timestamp); break; case WIRE_GOSSIP_STORE_PRIVATE_UPDATE: if (!fromwire_gossip_store_private_update(tmpctx, msg, &msg)) { @@ -610,6 +615,9 @@ void gossip_store_load(struct routing_state *rstate, struct gossip_store *gs) gs->len += sizeof(hdr) + msglen; clean_tmpctx(); } + + /* If last timestamp is within 24 hours, say we're OK. */ + contents_ok = (last_timestamp >= time_now().ts.tv_sec - 24*3600); goto out; truncate: @@ -623,6 +631,7 @@ truncate_nomsg: if (ftruncate(gs->fd, gs->len) != 0) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Truncating store: %s", strerror(errno)); + contents_ok = false; out: gs->writable = true; /* If we ever truncated, we might have a dangling channel_announce */ @@ -638,4 +647,6 @@ out: status_trace("gossip_store: Read %zu/%zu/%zu/%zu cannounce/cupdate/nannounce/cdelete from store (%zu deleted) in %"PRIu64" bytes", stats[0], stats[1], stats[2], stats[3], gs->deleted, gs->len); + + return contents_ok; } diff --git a/gossipd/gossip_store.h b/gossipd/gossip_store.h index 6e0de37ca..ef00dd9eb 100644 --- a/gossipd/gossip_store.h +++ b/gossipd/gossip_store.h @@ -23,8 +23,10 @@ struct gossip_store *gossip_store_new(struct routing_state *rstate, * * @param rstate The routing state to load init. * @param gs The `gossip_store` to read from + * + * Returns true if the store seems fully populated. */ -void gossip_store_load(struct routing_state *rstate, struct gossip_store *gs); +bool gossip_store_load(struct routing_state *rstate, struct gossip_store *gs); /** * Add a private channel_update message to the gossip_store diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index 1c30ea715..a8787bd2e 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -113,6 +113,9 @@ struct daemon { /* What addresses we can actually announce. */ struct wireaddr *announcable; + + /* Do we think we're missing gossip? */ + bool gossip_missing; }; /* This represents each peer we're gossiping with */ @@ -1829,6 +1832,12 @@ static void gossip_disable_local_channels(struct daemon *daemon) local_disable_chan(daemon->rstate, c); } +/*~ We've found gossip is missing. */ +static void gossip_missing(struct daemon *daemon) +{ + daemon->gossip_missing = true; +} + /*~ Parse init message from lightningd: starts the daemon properly. */ static struct io_plan *gossip_init(struct io_conn *conn, struct daemon *daemon, @@ -1859,7 +1868,8 @@ static struct io_plan *gossip_init(struct io_conn *conn, dev_gossip_time); /* Load stored gossip messages */ - gossip_store_load(daemon->rstate, daemon->rstate->gs); + if (!gossip_store_load(daemon->rstate, daemon->rstate->gs)) + gossip_missing(daemon); /* Now disable all local channels, they can't be connected yet. */ gossip_disable_local_channels(daemon); @@ -2807,6 +2817,7 @@ int main(int argc, char *argv[]) daemon = tal(NULL, struct daemon); list_head_init(&daemon->peers); + daemon->gossip_missing = false; /* 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