mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-23 09:04:22 +01:00
gossipd: preserve unannounced channels across store compaction.
Otherwise we'd forget them on restart, again. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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(); }
|
||||||
|
|||||||
@@ -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(); }
|
||||||
|
|||||||
@@ -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(); }
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user