Browse Source

gossipd: preserve unannounced channels across store compaction.

Otherwise we'd forget them on restart, again.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
pr-2587
Rusty Russell 6 years ago
parent
commit
2bd7df93c6
  1. 1
      CHANGELOG.md
  2. 50
      gossipd/gossip_store.c
  3. 3
      gossipd/test/run-bench-find_route.c
  4. 3
      gossipd/test/run-find_route-specific.c
  5. 3
      gossipd/test/run-find_route.c
  6. 2
      tests/test_gossip.py

1
CHANGELOG.md

@ -25,6 +25,7 @@ changes.
### Fixed ### Fixed
- `--bind-addr=<path>` fixed for nodes using local sockets (eg. testing). - `--bind-addr=<path>` fixed for nodes using local sockets (eg. testing).
- Unannounced local channels were forgotten for routing on restart until reconnection occurred.
### Security ### Security

50
gossipd/gossip_store.c

@ -150,6 +150,46 @@ static bool gossip_store_append(int fd, struct routing_state *rstate, const u8 *
write(fd, msg, msglen) == msglen); write(fd, msg, msglen) == msglen);
} }
/* Local unannounced channels don't appear in broadcast map, but we need to
* remember them anyway, so we manually append to the store.
*
* Note these do *not* add to gs->count, since that's compared with
* the broadcast map count.
*/
static bool add_local_unnannounced(int fd,
struct routing_state *rstate,
struct node *self)
{
struct chan_map_iter i;
struct chan *c;
for (c = chan_map_first(&self->chans, &i);
c;
c = chan_map_next(&self->chans, &i)) {
struct node *peer = other_node(self, c);
const u8 *msg;
/* Ignore already announced. */
if (c->channel_announce)
continue;
msg = towire_gossipd_local_add_channel(tmpctx, &c->scid,
&peer->id, c->sat);
if (!gossip_store_append(fd, rstate, msg))
return false;
for (size_t i = 0; i < 2; i++) {
msg = c->half[i].channel_update;
if (!msg)
continue;
if (!gossip_store_append(fd, rstate, msg))
return false;
}
}
return true;
}
/** /**
* Rewrite the on-disk gossip store, compacting it along the way * Rewrite the on-disk gossip store, compacting it along the way
* *
@ -162,6 +202,7 @@ bool gossip_store_compact(struct gossip_store *gs)
u64 index = 0; u64 index = 0;
int fd; int fd;
const u8 *msg; const u8 *msg;
struct node *self;
assert(gs->broadcast); assert(gs->broadcast);
status_trace( status_trace(
@ -187,11 +228,18 @@ bool gossip_store_compact(struct gossip_store *gs)
status_broken("Failed writing to gossip store: %s", status_broken("Failed writing to gossip store: %s",
strerror(errno)); strerror(errno));
goto unlink_disable; goto unlink_disable;
} }
count++; count++;
} }
/* Local unannounced channels are not in the store! */
self = get_node(gs->rstate, &gs->rstate->local_id);
if (self && !add_local_unnannounced(fd, gs->rstate, self)) {
status_broken("Failed writing unannounced to gossip store: %s",
strerror(errno));
goto unlink_disable;
}
if (rename(GOSSIP_STORE_TEMP_FILENAME, GOSSIP_STORE_FILENAME) == -1) { if (rename(GOSSIP_STORE_TEMP_FILENAME, GOSSIP_STORE_FILENAME) == -1) {
status_broken( status_broken(
"Error swapping compacted gossip_store into place: %s", "Error swapping compacted gossip_store into place: %s",

3
gossipd/test/run-bench-find_route.c

@ -95,6 +95,9 @@ u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
const struct channel_id *channel UNNEEDED, const struct channel_id *channel UNNEEDED,
const char *fmt UNNEEDED, ...) const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "towire_errorfmt called!\n"); abort(); } { fprintf(stderr, "towire_errorfmt called!\n"); abort(); }
/* Generated stub for towire_gossipd_local_add_channel */
u8 *towire_gossipd_local_add_channel(const tal_t *ctx UNNEEDED, const struct short_channel_id *short_channel_id UNNEEDED, const struct pubkey *remote_node_id UNNEEDED, struct amount_sat satoshis UNNEEDED)
{ fprintf(stderr, "towire_gossipd_local_add_channel called!\n"); abort(); }
/* Generated stub for towire_gossip_store_channel_announcement */ /* Generated stub for towire_gossip_store_channel_announcement */
u8 *towire_gossip_store_channel_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED, struct amount_sat satoshis UNNEEDED) u8 *towire_gossip_store_channel_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED, struct amount_sat satoshis UNNEEDED)
{ fprintf(stderr, "towire_gossip_store_channel_announcement called!\n"); abort(); } { fprintf(stderr, "towire_gossip_store_channel_announcement called!\n"); abort(); }

3
gossipd/test/run-find_route-specific.c

@ -84,6 +84,9 @@ u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
const struct channel_id *channel UNNEEDED, const struct channel_id *channel UNNEEDED,
const char *fmt UNNEEDED, ...) const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "towire_errorfmt called!\n"); abort(); } { fprintf(stderr, "towire_errorfmt called!\n"); abort(); }
/* Generated stub for towire_gossipd_local_add_channel */
u8 *towire_gossipd_local_add_channel(const tal_t *ctx UNNEEDED, const struct short_channel_id *short_channel_id UNNEEDED, const struct pubkey *remote_node_id UNNEEDED, struct amount_sat satoshis UNNEEDED)
{ fprintf(stderr, "towire_gossipd_local_add_channel called!\n"); abort(); }
/* Generated stub for towire_gossip_store_channel_announcement */ /* Generated stub for towire_gossip_store_channel_announcement */
u8 *towire_gossip_store_channel_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED, struct amount_sat satoshis UNNEEDED) u8 *towire_gossip_store_channel_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED, struct amount_sat satoshis UNNEEDED)
{ fprintf(stderr, "towire_gossip_store_channel_announcement called!\n"); abort(); } { fprintf(stderr, "towire_gossip_store_channel_announcement called!\n"); abort(); }

3
gossipd/test/run-find_route.c

@ -82,6 +82,9 @@ u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
const struct channel_id *channel UNNEEDED, const struct channel_id *channel UNNEEDED,
const char *fmt UNNEEDED, ...) const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "towire_errorfmt called!\n"); abort(); } { fprintf(stderr, "towire_errorfmt called!\n"); abort(); }
/* Generated stub for towire_gossipd_local_add_channel */
u8 *towire_gossipd_local_add_channel(const tal_t *ctx UNNEEDED, const struct short_channel_id *short_channel_id UNNEEDED, const struct pubkey *remote_node_id UNNEEDED, struct amount_sat satoshis UNNEEDED)
{ fprintf(stderr, "towire_gossipd_local_add_channel called!\n"); abort(); }
/* Generated stub for towire_gossip_store_channel_announcement */ /* Generated stub for towire_gossip_store_channel_announcement */
u8 *towire_gossip_store_channel_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED, struct amount_sat satoshis UNNEEDED) u8 *towire_gossip_store_channel_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED, struct amount_sat satoshis UNNEEDED)
{ fprintf(stderr, "towire_gossip_store_channel_announcement called!\n"); abort(); } { fprintf(stderr, "towire_gossip_store_channel_announcement called!\n"); abort(); }

2
tests/test_gossip.py

@ -1033,7 +1033,6 @@ def test_getroute_exclude(node_factory, bitcoind):
l1.rpc.getroute(l4.info['id'], 1, 1, exclude=[chan_l2l3, chan_l2l4]) l1.rpc.getroute(l4.info['id'], 1, 1, exclude=[chan_l2l3, chan_l2l4])
@pytest.mark.xfail(strict=True)
@unittest.skipIf(not DEVELOPER, "need dev-compact-gossip-store") @unittest.skipIf(not DEVELOPER, "need dev-compact-gossip-store")
def test_gossip_store_local_channels(node_factory, bitcoind): def test_gossip_store_local_channels(node_factory, bitcoind):
l1, l2 = node_factory.line_graph(2, wait_for_announce=False) l1, l2 = node_factory.line_graph(2, wait_for_announce=False)
@ -1059,7 +1058,6 @@ def test_gossip_store_local_channels(node_factory, bitcoind):
assert len(chans) == 2 assert len(chans) == 2
@pytest.mark.xfail(strict=True)
@unittest.skipIf(not DEVELOPER, "need dev-compact-gossip-store") @unittest.skipIf(not DEVELOPER, "need dev-compact-gossip-store")
def test_gossip_store_private_channels(node_factory, bitcoind): def test_gossip_store_private_channels(node_factory, bitcoind):
l1, l2 = node_factory.line_graph(2, announce_channels=False) l1, l2 = node_factory.line_graph(2, announce_channels=False)

Loading…
Cancel
Save