mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
gossipd: don't "unmark" dying channels' updates if we receive them.
This looked like a test flake, but was real:
```
l1.daemon.wait_for_log("closing soon due to the funding outpoint being spent")
# We won't gossip the dead channel any more (but we still propagate node_announcement). But connectd is not explicitly synced, so wait for "a bit".
time.sleep(1)
> assert len(get_gossip(l1)) == 2
E assert 4 == 2
```
We can see that two channel_updates come in *after* we mark it dying:
```
gossipd: channel 103x1x0 closing soon due to the funding outpoint being spent
gossipd: REPLY WIRE_GOSSIPD_NEW_BLOCKHEIGHT_REPLY with 0 fds
022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-gossipd: Received channel_update for channel 103x1x0/0 now DISABLED
022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-gossipd: Received channel_update for channel 103x1x0/1 now DISABLED
```
We should keep marking channel_updates the same way.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -70,7 +70,7 @@ static ssize_t gossip_pwritev(int fd, const struct iovec *iov, int iovcnt,
|
|||||||
#endif /* !HAVE_PWRITEV */
|
#endif /* !HAVE_PWRITEV */
|
||||||
|
|
||||||
static bool append_msg(int fd, const u8 *msg, u32 timestamp,
|
static bool append_msg(int fd, const u8 *msg, u32 timestamp,
|
||||||
bool zombie, bool spam, u64 *len)
|
bool zombie, bool spam, bool dying, u64 *len)
|
||||||
{
|
{
|
||||||
struct gossip_hdr hdr;
|
struct gossip_hdr hdr;
|
||||||
u32 msglen;
|
u32 msglen;
|
||||||
@@ -86,6 +86,8 @@ static bool append_msg(int fd, const u8 *msg, u32 timestamp,
|
|||||||
hdr.flags |= CPU_TO_BE16(GOSSIP_STORE_RATELIMIT_BIT);
|
hdr.flags |= CPU_TO_BE16(GOSSIP_STORE_RATELIMIT_BIT);
|
||||||
if (zombie)
|
if (zombie)
|
||||||
hdr.flags |= CPU_TO_BE16(GOSSIP_STORE_ZOMBIE_BIT);
|
hdr.flags |= CPU_TO_BE16(GOSSIP_STORE_ZOMBIE_BIT);
|
||||||
|
if (dying)
|
||||||
|
hdr.flags |= CPU_TO_BE16(GOSSIP_STORE_DYING_BIT);
|
||||||
hdr.crc = cpu_to_be32(crc32c(timestamp, msg, msglen));
|
hdr.crc = cpu_to_be32(crc32c(timestamp, msg, msglen));
|
||||||
hdr.timestamp = cpu_to_be32(timestamp);
|
hdr.timestamp = cpu_to_be32(timestamp);
|
||||||
|
|
||||||
@@ -246,7 +248,7 @@ static u32 gossip_store_compact_offline(struct routing_state *rstate)
|
|||||||
oldlen = lseek(old_fd, SEEK_END, 0);
|
oldlen = lseek(old_fd, SEEK_END, 0);
|
||||||
newlen = lseek(new_fd, SEEK_END, 0);
|
newlen = lseek(new_fd, SEEK_END, 0);
|
||||||
append_msg(old_fd, towire_gossip_store_ended(tmpctx, newlen),
|
append_msg(old_fd, towire_gossip_store_ended(tmpctx, newlen),
|
||||||
0, false, false, &oldlen);
|
0, false, false, false, &oldlen);
|
||||||
close(old_fd);
|
close(old_fd);
|
||||||
status_debug("gossip_store_compact_offline: %zu deleted, %zu copied",
|
status_debug("gossip_store_compact_offline: %zu deleted, %zu copied",
|
||||||
deleted, count);
|
deleted, count);
|
||||||
@@ -526,7 +528,7 @@ bool gossip_store_compact(struct gossip_store *gs)
|
|||||||
|
|
||||||
/* Write end marker now new one is ready */
|
/* Write end marker now new one is ready */
|
||||||
append_msg(gs->fd, towire_gossip_store_ended(tmpctx, len),
|
append_msg(gs->fd, towire_gossip_store_ended(tmpctx, len),
|
||||||
0, false, false, &gs->len);
|
0, false, false, false, &gs->len);
|
||||||
|
|
||||||
gs->count = count;
|
gs->count = count;
|
||||||
gs->deleted = 0;
|
gs->deleted = 0;
|
||||||
@@ -547,19 +549,19 @@ disable:
|
|||||||
|
|
||||||
u64 gossip_store_add(struct gossip_store *gs, const u8 *gossip_msg,
|
u64 gossip_store_add(struct gossip_store *gs, const u8 *gossip_msg,
|
||||||
u32 timestamp, bool zombie,
|
u32 timestamp, bool zombie,
|
||||||
bool spam, const u8 *addendum)
|
bool spam, bool dying, const u8 *addendum)
|
||||||
{
|
{
|
||||||
u64 off = gs->len;
|
u64 off = gs->len;
|
||||||
|
|
||||||
/* Should never get here during loading! */
|
/* Should never get here during loading! */
|
||||||
assert(gs->writable);
|
assert(gs->writable);
|
||||||
|
|
||||||
if (!append_msg(gs->fd, gossip_msg, timestamp, zombie, spam, &gs->len)) {
|
if (!append_msg(gs->fd, gossip_msg, timestamp, zombie, spam, dying, &gs->len)) {
|
||||||
status_broken("Failed writing to gossip store: %s",
|
status_broken("Failed writing to gossip store: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (addendum && !append_msg(gs->fd, addendum, 0, false, false, &gs->len)) {
|
if (addendum && !append_msg(gs->fd, addendum, 0, false, false, false, &gs->len)) {
|
||||||
status_broken("Failed writing addendum to gossip store: %s",
|
status_broken("Failed writing addendum to gossip store: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
@@ -576,7 +578,7 @@ u64 gossip_store_add_private_update(struct gossip_store *gs, const u8 *update)
|
|||||||
/* A local update for an unannounced channel: not broadcastable, but
|
/* A local update for an unannounced channel: not broadcastable, but
|
||||||
* otherwise the same as a normal channel_update */
|
* otherwise the same as a normal channel_update */
|
||||||
const u8 *pupdate = towire_gossip_store_private_update(tmpctx, update);
|
const u8 *pupdate = towire_gossip_store_private_update(tmpctx, update);
|
||||||
return gossip_store_add(gs, pupdate, 0, false, false, NULL);
|
return gossip_store_add(gs, pupdate, 0, false, false, false, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gossip_store_mark_dying(struct gossip_store *gs,
|
void gossip_store_mark_dying(struct gossip_store *gs,
|
||||||
@@ -684,7 +686,7 @@ void gossip_store_mark_channel_deleted(struct gossip_store *gs,
|
|||||||
const struct short_channel_id *scid)
|
const struct short_channel_id *scid)
|
||||||
{
|
{
|
||||||
gossip_store_add(gs, towire_gossip_store_delete_chan(tmpctx, scid),
|
gossip_store_add(gs, towire_gossip_store_delete_chan(tmpctx, scid),
|
||||||
0, false, false, NULL);
|
0, false, false, false, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mark_zombie(struct gossip_store *gs,
|
static void mark_zombie(struct gossip_store *gs,
|
||||||
|
|||||||
@@ -38,14 +38,14 @@ u64 gossip_store_add_private_update(struct gossip_store *gs, const u8 *update);
|
|||||||
* @gs: gossip store
|
* @gs: gossip store
|
||||||
* @gossip_msg: the gossip message to insert.
|
* @gossip_msg: the gossip message to insert.
|
||||||
* @timestamp: the timestamp for filtering of this messsage.
|
* @timestamp: the timestamp for filtering of this messsage.
|
||||||
* @push: true if this should be sent to peers despite any timestamp filters.
|
|
||||||
* @spam: true if this message is rate-limited and squelched to peers.
|
|
||||||
* @zombie: true if this channel is missing a current channel_update.
|
* @zombie: true if this channel is missing a current channel_update.
|
||||||
|
* @spam: true if this message is rate-limited and squelched to peers.
|
||||||
|
* @dying: true if this message is for a dying channel.
|
||||||
* @addendum: another message to append immediately after this
|
* @addendum: another message to append immediately after this
|
||||||
* (for appending amounts to channel_announcements for internal use).
|
* (for appending amounts to channel_announcements for internal use).
|
||||||
*/
|
*/
|
||||||
u64 gossip_store_add(struct gossip_store *gs, const u8 *gossip_msg,
|
u64 gossip_store_add(struct gossip_store *gs, const u8 *gossip_msg,
|
||||||
u32 timestamp, bool zombie, bool spam,
|
u32 timestamp, bool zombie, bool spam, bool dying,
|
||||||
const u8 *addendum);
|
const u8 *addendum);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -465,6 +465,7 @@ static void force_node_announce_rexmit(struct routing_state *rstate,
|
|||||||
node->bcast.timestamp,
|
node->bcast.timestamp,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
NULL);
|
NULL);
|
||||||
if (node->rgraph.index == initial_bcast_index){
|
if (node->rgraph.index == initial_bcast_index){
|
||||||
node->rgraph.index = node->bcast.index;
|
node->rgraph.index = node->bcast.index;
|
||||||
@@ -478,6 +479,7 @@ static void force_node_announce_rexmit(struct routing_state *rstate,
|
|||||||
node->rgraph.timestamp,
|
node->rgraph.timestamp,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -847,6 +849,7 @@ static void add_channel_announce_to_broadcast(struct routing_state *rstate,
|
|||||||
chan->bcast.timestamp,
|
chan->bcast.timestamp,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
addendum);
|
addendum);
|
||||||
rstate->local_channel_announced |= is_local;
|
rstate->local_channel_announced |= is_local;
|
||||||
}
|
}
|
||||||
@@ -1315,6 +1318,16 @@ static void delete_spam_update(struct routing_state *rstate,
|
|||||||
hc->rgraph.timestamp = hc->bcast.timestamp;
|
hc->rgraph.timestamp = hc->bcast.timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_chan_dying(struct routing_state *rstate,
|
||||||
|
const struct short_channel_id *scid)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < tal_count(rstate->dying_channels); i++) {
|
||||||
|
if (short_channel_id_eq(&rstate->dying_channels[i].scid, scid))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool routing_add_channel_update(struct routing_state *rstate,
|
bool routing_add_channel_update(struct routing_state *rstate,
|
||||||
const u8 *update TAKES,
|
const u8 *update TAKES,
|
||||||
u32 index,
|
u32 index,
|
||||||
@@ -1339,6 +1352,7 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
|||||||
struct amount_sat sat;
|
struct amount_sat sat;
|
||||||
bool spam;
|
bool spam;
|
||||||
bool zombie;
|
bool zombie;
|
||||||
|
bool dying;
|
||||||
|
|
||||||
/* Make sure we own msg, even if we don't save it. */
|
/* Make sure we own msg, even if we don't save it. */
|
||||||
if (taken(update))
|
if (taken(update))
|
||||||
@@ -1360,6 +1374,7 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
|||||||
uc = NULL;
|
uc = NULL;
|
||||||
sat = chan->sat;
|
sat = chan->sat;
|
||||||
zombie = is_chan_zombie(chan);
|
zombie = is_chan_zombie(chan);
|
||||||
|
dying = is_chan_dying(rstate, &short_channel_id);
|
||||||
} else {
|
} else {
|
||||||
/* Maybe announcement was waiting for this update? */
|
/* Maybe announcement was waiting for this update? */
|
||||||
uc = get_unupdated_channel(rstate, &short_channel_id);
|
uc = get_unupdated_channel(rstate, &short_channel_id);
|
||||||
@@ -1369,6 +1384,7 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
|||||||
sat = uc->sat;
|
sat = uc->sat;
|
||||||
/* When loading zombies from the store. */
|
/* When loading zombies from the store. */
|
||||||
zombie = force_zombie_flag;
|
zombie = force_zombie_flag;
|
||||||
|
dying = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reject update if the `htlc_maximum_msat` is greater
|
/* Reject update if the `htlc_maximum_msat` is greater
|
||||||
@@ -1531,7 +1547,7 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
|||||||
chan->bcast.index =
|
chan->bcast.index =
|
||||||
gossip_store_add(rstate->gs, zombie_announcement,
|
gossip_store_add(rstate->gs, zombie_announcement,
|
||||||
chan->bcast.timestamp,
|
chan->bcast.timestamp,
|
||||||
false, false, zombie_addendum);
|
false, false, false, zombie_addendum);
|
||||||
/* Deletion of the old addendum is optional. */
|
/* Deletion of the old addendum is optional. */
|
||||||
/* This opposing channel_update has been stashed away. Now that
|
/* This opposing channel_update has been stashed away. Now that
|
||||||
* there are two valid updates, this one gets restored. */
|
* there are two valid updates, this one gets restored. */
|
||||||
@@ -1554,12 +1570,12 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
|||||||
chan->half[!direction].bcast.index =
|
chan->half[!direction].bcast.index =
|
||||||
gossip_store_add(rstate->gs, zombie_update[0],
|
gossip_store_add(rstate->gs, zombie_update[0],
|
||||||
chan->half[!direction].bcast.timestamp,
|
chan->half[!direction].bcast.timestamp,
|
||||||
false, false, NULL);
|
false, false, false, NULL);
|
||||||
if (zombie_update[1])
|
if (zombie_update[1])
|
||||||
chan->half[!direction].rgraph.index =
|
chan->half[!direction].rgraph.index =
|
||||||
gossip_store_add(rstate->gs, zombie_update[1],
|
gossip_store_add(rstate->gs, zombie_update[1],
|
||||||
chan->half[!direction].rgraph.timestamp,
|
chan->half[!direction].rgraph.timestamp,
|
||||||
false, true, NULL);
|
false, true, false, NULL);
|
||||||
else
|
else
|
||||||
chan->half[!direction].rgraph.index = chan->half[!direction].bcast.index;
|
chan->half[!direction].rgraph.index = chan->half[!direction].bcast.index;
|
||||||
|
|
||||||
@@ -1577,7 +1593,7 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
|||||||
} else {
|
} else {
|
||||||
hc->rgraph.index
|
hc->rgraph.index
|
||||||
= gossip_store_add(rstate->gs, update, timestamp,
|
= gossip_store_add(rstate->gs, update, timestamp,
|
||||||
zombie, spam, NULL);
|
zombie, spam, dying, NULL);
|
||||||
if (hc->bcast.timestamp > rstate->last_timestamp
|
if (hc->bcast.timestamp > rstate->last_timestamp
|
||||||
&& hc->bcast.timestamp < time_now().ts.tv_sec)
|
&& hc->bcast.timestamp < time_now().ts.tv_sec)
|
||||||
rstate->last_timestamp = hc->bcast.timestamp;
|
rstate->last_timestamp = hc->bcast.timestamp;
|
||||||
@@ -1596,8 +1612,9 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_peer_debug(source_peer,
|
status_peer_debug(source_peer,
|
||||||
"Received %schannel_update for channel %s/%d now %s",
|
"Received %schannel_update for %schannel %s/%d now %s",
|
||||||
ignore_timestamp ? "(forced) " : "",
|
ignore_timestamp ? "(forced) " : "",
|
||||||
|
dying ? "dying ": "",
|
||||||
type_to_string(tmpctx, struct short_channel_id,
|
type_to_string(tmpctx, struct short_channel_id,
|
||||||
&short_channel_id),
|
&short_channel_id),
|
||||||
channel_flags & 0x01,
|
channel_flags & 0x01,
|
||||||
@@ -1899,7 +1916,7 @@ bool routing_add_node_announcement(struct routing_state *rstate,
|
|||||||
} else {
|
} else {
|
||||||
node->rgraph.index
|
node->rgraph.index
|
||||||
= gossip_store_add(rstate->gs, msg, timestamp,
|
= gossip_store_add(rstate->gs, msg, timestamp,
|
||||||
false, spam, NULL);
|
false, spam, false, NULL);
|
||||||
if (node->bcast.timestamp > rstate->last_timestamp
|
if (node->bcast.timestamp > rstate->last_timestamp
|
||||||
&& node->bcast.timestamp < time_now().ts.tv_sec)
|
&& node->bcast.timestamp < time_now().ts.tv_sec)
|
||||||
rstate->last_timestamp = node->bcast.timestamp;
|
rstate->last_timestamp = node->bcast.timestamp;
|
||||||
@@ -2131,7 +2148,7 @@ bool routing_add_private_channel(struct routing_state *rstate,
|
|||||||
u8 *msg = towire_gossip_store_private_channel(tmpctx,
|
u8 *msg = towire_gossip_store_private_channel(tmpctx,
|
||||||
capacity,
|
capacity,
|
||||||
chan_ann);
|
chan_ann);
|
||||||
index = gossip_store_add(rstate->gs, msg, 0, false, false,
|
index = gossip_store_add(rstate->gs, msg, 0, false, false, false,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
chan->bcast.index = index;
|
chan->bcast.index = index;
|
||||||
@@ -2277,7 +2294,7 @@ void routing_channel_spent(struct routing_state *rstate,
|
|||||||
|
|
||||||
/* Save to gossip_store in case we restart */
|
/* Save to gossip_store in case we restart */
|
||||||
msg = towire_gossip_store_chan_dying(tmpctx, &chan->scid, deadline);
|
msg = towire_gossip_store_chan_dying(tmpctx, &chan->scid, deadline);
|
||||||
index = gossip_store_add(rstate->gs, msg, 0, false, false, NULL);
|
index = gossip_store_add(rstate->gs, msg, 0, false, false, false, NULL);
|
||||||
|
|
||||||
/* Mark it dying, so we don't gossip it */
|
/* Mark it dying, so we don't gossip it */
|
||||||
gossip_store_mark_dying(rstate->gs, &chan->bcast,
|
gossip_store_mark_dying(rstate->gs, &chan->bcast,
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ bool cupdate_different(struct gossip_store *gs UNNEEDED,
|
|||||||
{ fprintf(stderr, "cupdate_different called!\n"); abort(); }
|
{ fprintf(stderr, "cupdate_different called!\n"); abort(); }
|
||||||
/* Generated stub for gossip_store_add */
|
/* Generated stub for gossip_store_add */
|
||||||
u64 gossip_store_add(struct gossip_store *gs UNNEEDED, const u8 *gossip_msg UNNEEDED,
|
u64 gossip_store_add(struct gossip_store *gs UNNEEDED, const u8 *gossip_msg UNNEEDED,
|
||||||
u32 timestamp UNNEEDED, bool zombie UNNEEDED, bool spam UNNEEDED,
|
u32 timestamp UNNEEDED, bool zombie UNNEEDED, bool spam UNNEEDED, bool dying UNNEEDED,
|
||||||
const u8 *addendum UNNEEDED)
|
const u8 *addendum UNNEEDED)
|
||||||
{ fprintf(stderr, "gossip_store_add called!\n"); abort(); }
|
{ fprintf(stderr, "gossip_store_add called!\n"); abort(); }
|
||||||
/* Generated stub for gossip_store_add_private_update */
|
/* Generated stub for gossip_store_add_private_update */
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ bool cupdate_different(struct gossip_store *gs UNNEEDED,
|
|||||||
{ fprintf(stderr, "cupdate_different called!\n"); abort(); }
|
{ fprintf(stderr, "cupdate_different called!\n"); abort(); }
|
||||||
/* Generated stub for gossip_store_add */
|
/* Generated stub for gossip_store_add */
|
||||||
u64 gossip_store_add(struct gossip_store *gs UNNEEDED, const u8 *gossip_msg UNNEEDED,
|
u64 gossip_store_add(struct gossip_store *gs UNNEEDED, const u8 *gossip_msg UNNEEDED,
|
||||||
u32 timestamp UNNEEDED, bool zombie UNNEEDED, bool spam UNNEEDED,
|
u32 timestamp UNNEEDED, bool zombie UNNEEDED, bool spam UNNEEDED, bool dying UNNEEDED,
|
||||||
const u8 *addendum UNNEEDED)
|
const u8 *addendum UNNEEDED)
|
||||||
{ fprintf(stderr, "gossip_store_add called!\n"); abort(); }
|
{ fprintf(stderr, "gossip_store_add called!\n"); abort(); }
|
||||||
/* Generated stub for gossip_store_add_private_update */
|
/* Generated stub for gossip_store_add_private_update */
|
||||||
|
|||||||
Reference in New Issue
Block a user