mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-24 01:24:26 +01:00
gossipd: erase old entries from the store, don't just append.
We use the high bit of the length field: this way we can still check that the checksums are valid on deleted fields. Once this is done, serially reading the gossip_store file will result in a complete, ordered, minimal gossip broadcast. Also, the horrible corner case where we might try to delete things from the store during load time is completely gone: we only load non-deleted things. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -330,6 +330,9 @@ static void remove_chan_from_node(struct routing_state *rstate,
|
||||
|
||||
/* Last channel? Simply delete node (and associated announce) */
|
||||
if (num_chans == 0) {
|
||||
gossip_store_delete(rstate->broadcasts->gs,
|
||||
&node->bcast,
|
||||
WIRE_NODE_ANNOUNCEMENT);
|
||||
tal_free(node);
|
||||
return;
|
||||
}
|
||||
@@ -337,14 +340,11 @@ static void remove_chan_from_node(struct routing_state *rstate,
|
||||
if (!node->bcast.index)
|
||||
return;
|
||||
|
||||
/* FIXME: Remove when we get rid of WIRE_GOSSIP_STORE_CHANNEL_DELETE.
|
||||
* For the moment, it can cause us to try to write to the store. */
|
||||
(void)WIRE_GOSSIP_STORE_CHANNEL_DELETE;
|
||||
if (gossip_store_loading(rstate->broadcasts->gs))
|
||||
return;
|
||||
|
||||
/* Removed only public channel? Remove node announcement. */
|
||||
if (!node_has_broadcastable_channels(node)) {
|
||||
gossip_store_delete(rstate->broadcasts->gs,
|
||||
&node->bcast,
|
||||
WIRE_NODE_ANNOUNCEMENT);
|
||||
broadcast_del(rstate->broadcasts, &node->bcast);
|
||||
} else if (node_announce_predates_channels(node)) {
|
||||
const u8 *announce;
|
||||
@@ -356,6 +356,9 @@ static void remove_chan_from_node(struct routing_state *rstate,
|
||||
* Move to end (we could, in theory, move to just past next
|
||||
* channel_announce, but we don't care that much about spurious
|
||||
* retransmissions in this corner case */
|
||||
gossip_store_delete(rstate->broadcasts->gs,
|
||||
&node->bcast,
|
||||
WIRE_NODE_ANNOUNCEMENT);
|
||||
broadcast_del(rstate->broadcasts, &node->bcast);
|
||||
insert_broadcast(&rstate->broadcasts, announce, NULL,
|
||||
&node->bcast);
|
||||
@@ -1416,8 +1419,10 @@ bool routing_add_channel_announcement(struct routing_state *rstate,
|
||||
}
|
||||
|
||||
/* Pretend it didn't exist, for the moment. */
|
||||
if (chan)
|
||||
if (chan) {
|
||||
remove_channel_from_store(rstate, chan);
|
||||
free_chan(rstate, chan);
|
||||
}
|
||||
|
||||
uc = tal(rstate, struct unupdated_channel);
|
||||
uc->channel_announce = tal_dup_arr(uc, u8, msg, tal_count(msg), 0);
|
||||
@@ -1836,7 +1841,13 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
||||
message_flags, channel_flags,
|
||||
timestamp, htlc_minimum, htlc_maximum);
|
||||
|
||||
/* Safe even if was never added */
|
||||
/* Safe even if was never added, but if it's a private channel it
|
||||
* would be a WIRE_GOSSIP_STORE_PRIVATE_UPDATE. */
|
||||
gossip_store_delete(rstate->broadcasts->gs,
|
||||
&chan->half[direction].bcast,
|
||||
is_chan_public(chan)
|
||||
? WIRE_CHANNEL_UPDATE
|
||||
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE);
|
||||
broadcast_del(rstate->broadcasts, &chan->half[direction].bcast);
|
||||
|
||||
/* BOLT #7:
|
||||
@@ -1899,6 +1910,28 @@ static const struct node_id *get_channel_owner(struct routing_state *rstate,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void remove_channel_from_store(struct routing_state *rstate,
|
||||
struct chan *chan)
|
||||
{
|
||||
int update_type, announcment_type;
|
||||
|
||||
if (is_chan_public(chan)) {
|
||||
update_type = WIRE_CHANNEL_UPDATE;
|
||||
announcment_type = WIRE_CHANNEL_ANNOUNCEMENT;
|
||||
} else {
|
||||
update_type = WIRE_GOSSIP_STORE_PRIVATE_UPDATE;
|
||||
announcment_type = WIRE_GOSSIPD_LOCAL_ADD_CHANNEL;
|
||||
}
|
||||
|
||||
/* If these aren't in the store, these are noops. */
|
||||
gossip_store_delete(rstate->broadcasts->gs,
|
||||
&chan->bcast, announcment_type);
|
||||
gossip_store_delete(rstate->broadcasts->gs,
|
||||
&chan->half[0].bcast, update_type);
|
||||
gossip_store_delete(rstate->broadcasts->gs,
|
||||
&chan->half[1].bcast, update_type);
|
||||
}
|
||||
|
||||
u8 *handle_channel_update(struct routing_state *rstate, const u8 *update TAKES,
|
||||
const char *source)
|
||||
{
|
||||
@@ -2108,6 +2141,9 @@ bool routing_add_node_announcement(struct routing_state *rstate,
|
||||
}
|
||||
|
||||
/* Harmless if it was never added */
|
||||
gossip_store_delete(rstate->broadcasts->gs,
|
||||
&node->bcast,
|
||||
WIRE_NODE_ANNOUNCEMENT);
|
||||
broadcast_del(rstate->broadcasts, &node->bcast);
|
||||
|
||||
node->bcast.timestamp = timestamp;
|
||||
@@ -2428,8 +2464,10 @@ void route_prune(struct routing_state *rstate)
|
||||
}
|
||||
|
||||
/* Now free all the chans and maybe even nodes. */
|
||||
for (size_t i = 0; i < tal_count(pruned); i++)
|
||||
for (size_t i = 0; i < tal_count(pruned); i++) {
|
||||
remove_channel_from_store(rstate, pruned[i]);
|
||||
free_chan(rstate, pruned[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#if DEVELOPER
|
||||
|
||||
Reference in New Issue
Block a user