gossipd: strip private updates from gossip_store on startup.

We rename them to _obs, too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-01-31 13:46:16 +10:30
parent ad4a8a510d
commit f2f43eeffa
8 changed files with 111 additions and 64 deletions

View File

@ -15,7 +15,7 @@ struct gossip_rcvd_filter;
/* First byte of file is the version.
*
* Top three bits mean incompatible change.
* As of this writing, major == 0, minor == 11.
* As of this writing, major == 0, minor == 13.
*/
#define GOSSIP_STORE_MAJOR_VERSION_MASK 0xE0
#define GOSSIP_STORE_MINOR_VERSION_MASK 0x1F

View File

@ -113,12 +113,12 @@ int main(int argc, char *argv[])
printf("t=%u node_announcement: %s\n",
be32_to_cpu(hdr.timestamp),
tal_hex(msg, msg));
} else if (fromwire_gossip_store_private_channel(msg, msg, &sat,
} else if (fromwire_gossip_store_private_channel_obs(msg, msg, &sat,
&inner)) {
printf("private channel_announcement: %s %s\n",
type_to_string(tmpctx, struct amount_sat, &sat),
tal_hex(msg, inner));
} else if (fromwire_gossip_store_private_update(msg, msg,
} else if (fromwire_gossip_store_private_update_obs(msg, msg,
&inner)) {
printf("private channel_update: %s\n",
tal_hex(msg, inner));

View File

@ -720,7 +720,7 @@ static u8 *prev_update(const tal_t *ctx,
chan->half[direction].bcast.index));
/* If it's a private update, unwrap */
if (!fromwire_gossip_store_private_update(ctx, prev, &prev))
if (!fromwire_gossip_store_private_update_obs(ctx, prev, &prev))
tal_steal(ctx, prev);
return prev;
}

View File

@ -17,8 +17,8 @@
#include <wire/peer_wire.h>
#define GOSSIP_STORE_TEMP_FILENAME "gossip_store.tmp"
/* We write it as major version 0, minor version 12 */
#define GOSSIP_STORE_VER ((0 << 5) | 12)
/* We write it as major version 0, minor version 13 */
#define GOSSIP_STORE_VER ((0 << 5) | 13)
struct gossip_store {
/* This is false when we're loading */
@ -107,25 +107,85 @@ static bool append_msg(int fd, const u8 *msg, u32 timestamp,
* v10 removed any remaining non-htlc-max channel_update.
* v11 mandated channel_updates use the htlc_maximum_msat field
* v12 added the zombie flag for expired channel updates
* v13 removed private gossip entries
*/
static bool can_upgrade(u8 oldversion)
{
return oldversion >= 9 && oldversion <= 11;
return oldversion >= 9 && oldversion <= 12;
}
/* On upgrade, do best effort on private channels: hand them to
* lightningd as if we just receive them, before removing from the
* store */
static void give_lightningd_canned_private_update(struct routing_state *rstate,
const u8 *msg)
{
u8 *update;
secp256k1_ecdsa_signature signature;
struct bitcoin_blkid chain_hash;
struct short_channel_id short_channel_id;
u32 timestamp;
u8 message_flags, channel_flags;
u16 cltv_expiry_delta;
struct amount_msat htlc_minimum_msat, htlc_maximum_msat;
u32 fee_base_msat, fee_proportional_millionths;
if (!fromwire_gossip_store_private_update_obs(tmpctx, msg, &update)) {
status_broken("Could not parse private update %s",
tal_hex(tmpctx, msg));
return;
}
if (!fromwire_channel_update(update,
&signature,
&chain_hash,
&short_channel_id,
&timestamp,
&message_flags,
&channel_flags,
&cltv_expiry_delta,
&htlc_minimum_msat,
&fee_base_msat,
&fee_proportional_millionths,
&htlc_maximum_msat)) {
status_broken("Could not parse inner private update %s",
tal_hex(tmpctx, msg));
return;
}
/* From NULL source (i.e. trust us!) */
tell_lightningd_peer_update(rstate,
NULL,
short_channel_id,
fee_base_msat,
fee_proportional_millionths,
cltv_expiry_delta,
htlc_minimum_msat,
htlc_maximum_msat);
}
static bool upgrade_field(u8 oldversion,
struct routing_state *rstate,
u8 **msg)
{
int type = fromwire_peektype(*msg);
assert(can_upgrade(oldversion));
if (oldversion == 10) {
if (oldversion <= 10) {
/* Remove old channel_update with no htlc_maximum_msat */
if (fromwire_peektype(*msg) == WIRE_CHANNEL_UPDATE
if (type == WIRE_CHANNEL_UPDATE
&& tal_bytelen(*msg) == 130) {
*msg = tal_free(*msg);
}
}
if (oldversion <= 12) {
/* Remove private entries */
if (type == WIRE_GOSSIP_STORE_PRIVATE_CHANNEL_OBS) {
*msg = tal_free(*msg);
} else if (type == WIRE_GOSSIP_STORE_PRIVATE_UPDATE_OBS) {
give_lightningd_canned_private_update(rstate, *msg);
*msg = tal_free(*msg);
}
}
return true;
}
@ -468,9 +528,7 @@ bool gossip_store_compact(struct gossip_store *gs)
goto unlink_disable;
/* We track location of all these message types. */
if (msgtype == WIRE_GOSSIP_STORE_PRIVATE_CHANNEL
|| msgtype == WIRE_GOSSIP_STORE_PRIVATE_UPDATE
|| msgtype == WIRE_CHANNEL_ANNOUNCEMENT
if (msgtype == WIRE_CHANNEL_ANNOUNCEMENT
|| msgtype == WIRE_CHANNEL_UPDATE
|| msgtype == WIRE_NODE_ANNOUNCEMENT) {
omap = tal(offmap, struct offset_map);
@ -579,7 +637,7 @@ u64 gossip_store_add_private_update(struct gossip_store *gs, const u8 *update)
{
/* A local update for an unannounced channel: not broadcastable, but
* 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_obs(tmpctx, update);
return gossip_store_add(gs, pupdate, 0, false, false, false, NULL);
}
@ -785,7 +843,7 @@ const u8 *gossip_store_get_private_update(const tal_t *ctx,
const u8 *pmsg = gossip_store_get(tmpctx, gs, offset);
u8 *msg;
if (!fromwire_gossip_store_private_update(ctx, pmsg, &msg))
if (!fromwire_gossip_store_private_update_obs(ctx, pmsg, &msg))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed to decode private update @%"PRIu64": %s",
offset, tal_hex(tmpctx, pmsg));
@ -845,25 +903,6 @@ u32 gossip_store_load(struct routing_state *rstate, struct gossip_store *gs)
spam = (be16_to_cpu(hdr.flags) & GOSSIP_STORE_RATELIMIT_BIT);
switch (fromwire_peektype(msg)) {
case WIRE_GOSSIP_STORE_PRIVATE_CHANNEL: {
u8 *priv_chan_ann;
struct amount_sat sat;
if (!fromwire_gossip_store_private_channel(msg, msg,
&sat,
&priv_chan_ann)) {
bad = "Bad private_channel";
goto badmsg;
}
if (!routing_add_private_channel(rstate, NULL,
sat, priv_chan_ann,
gs->len)) {
bad = "Bad add_private_channel";
goto badmsg;
}
stats[0]++;
break;
}
case WIRE_GOSSIP_STORE_CHANNEL_AMOUNT:
if (!fromwire_gossip_store_channel_amount(msg,
&satoshis)) {
@ -904,12 +943,6 @@ u32 gossip_store_load(struct routing_state *rstate, struct gossip_store *gs)
remember_chan_dying(rstate, &scid, deadline, gs->len);
break;
}
case WIRE_GOSSIP_STORE_PRIVATE_UPDATE:
if (!fromwire_gossip_store_private_update(tmpctx, msg, &msg)) {
bad = "invalid gossip_store_private_update";
goto badmsg;
}
/* fall thru */
case WIRE_CHANNEL_UPDATE:
if (!routing_add_channel_update(rstate,
take(msg), gs->len,
@ -930,6 +963,10 @@ u32 gossip_store_load(struct routing_state *rstate, struct gossip_store *gs)
}
stats[2]++;
break;
/* FIXME: Don't actually put these in! */
case WIRE_GOSSIP_STORE_PRIVATE_CHANNEL_OBS:
case WIRE_GOSSIP_STORE_PRIVATE_UPDATE_OBS:
break;
default:
bad = "Unknown message";
goto badmsg;

View File

@ -9,14 +9,14 @@ msgtype,gossip_store_channel_amount,4101
msgdata,gossip_store_channel_amount,satoshis,amount_sat,
# Mimics a channel_announce, except signatures are all-zero
msgtype,gossip_store_private_channel,4104
msgdata,gossip_store_private_channel,satoshis,amount_sat,
msgdata,gossip_store_private_channel,len,u16,
msgdata,gossip_store_private_channel,announcement,u8,len
msgtype,gossip_store_private_channel_obs,4104
msgdata,gossip_store_private_channel_obs,satoshis,amount_sat,
msgdata,gossip_store_private_channel_obs,len,u16,
msgdata,gossip_store_private_channel_obs,announcement,u8,len
msgtype,gossip_store_private_update,4102
msgdata,gossip_store_private_update,len,u16,
msgdata,gossip_store_private_update,update,u8,len
msgtype,gossip_store_private_update_obs,4102
msgdata,gossip_store_private_update_obs,len,u16,
msgdata,gossip_store_private_update_obs,update,u8,len
msgtype,gossip_store_delete_chan,4103
msgdata,gossip_store_delete_chan,scid,short_channel_id,

1 # gossip_store messages: messages persisted in the gossip_store
9 # Mimics a channel_announce, except signatures are all-zero
10 msgtype,gossip_store_private_channel,4104 msgtype,gossip_store_private_channel_obs,4104
11 msgdata,gossip_store_private_channel,satoshis,amount_sat, msgdata,gossip_store_private_channel_obs,satoshis,amount_sat,
12 msgdata,gossip_store_private_channel,len,u16, msgdata,gossip_store_private_channel_obs,len,u16,
13 msgdata,gossip_store_private_channel,announcement,u8,len msgdata,gossip_store_private_channel_obs,announcement,u8,len
14 msgtype,gossip_store_private_update,4102 msgtype,gossip_store_private_update_obs,4102
15 msgdata,gossip_store_private_update,len,u16, msgdata,gossip_store_private_update_obs,len,u16,
16 msgdata,gossip_store_private_update,update,u8,len msgdata,gossip_store_private_update_obs,update,u8,len
17 msgtype,gossip_store_delete_chan,4103
18 msgdata,gossip_store_delete_chan,scid,short_channel_id,
19 msgtype,gossip_store_ended,4105
20 msgdata,gossip_store_ended,equivalent_offset,u64,
21 msgtype,gossip_store_chan_dying,4106
22 msgdata,gossip_store_chan_dying,scid,short_channel_id,

View File

@ -883,8 +883,8 @@ static void delete_chan_messages_from_store(struct routing_state *rstate,
update_type = WIRE_CHANNEL_UPDATE;
announcment_type = WIRE_CHANNEL_ANNOUNCEMENT;
} else {
update_type = WIRE_GOSSIP_STORE_PRIVATE_UPDATE;
announcment_type = WIRE_GOSSIP_STORE_PRIVATE_CHANNEL;
update_type = WIRE_GOSSIP_STORE_PRIVATE_UPDATE_OBS;
announcment_type = WIRE_GOSSIP_STORE_PRIVATE_CHANNEL_OBS;
}
/* If these aren't in the store, these are noops. */
@ -1333,7 +1333,7 @@ static void delete_spam_update(struct routing_state *rstate,
gossip_store_delete(rstate->gs, &hc->rgraph,
update_is_public
? WIRE_CHANNEL_UPDATE
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE);
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE_OBS);
hc->rgraph.index = hc->bcast.index;
hc->rgraph.timestamp = hc->bcast.timestamp;
}
@ -1348,14 +1348,14 @@ static bool is_chan_dying(struct routing_state *rstate,
return false;
}
static void tell_lightningd_peer_update(struct routing_state *rstate,
const struct node_id *source_peer,
struct short_channel_id scid,
u32 fee_base_msat,
u32 fee_ppm,
u16 cltv_delta,
struct amount_msat htlc_minimum,
struct amount_msat htlc_maximum)
void tell_lightningd_peer_update(struct routing_state *rstate,
const struct node_id *source_peer,
struct short_channel_id scid,
u32 fee_base_msat,
u32 fee_ppm,
u16 cltv_delta,
struct amount_msat htlc_minimum,
struct amount_msat htlc_maximum)
{
struct peer_update remote_update;
u8* msg;
@ -1532,7 +1532,7 @@ bool routing_add_channel_update(struct routing_state *rstate,
gossip_store_delete(rstate->gs, &hc->bcast,
is_chan_public(chan)
? WIRE_CHANNEL_UPDATE
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE);
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE_OBS);
/* Update timestamp(s) */
hc->rgraph.timestamp = timestamp;
@ -1609,7 +1609,7 @@ bool routing_add_channel_update(struct routing_state *rstate,
gossip_store_delete(rstate->gs, &chan->bcast,
is_chan_public(chan)
? WIRE_CHANNEL_ANNOUNCEMENT
: WIRE_GOSSIP_STORE_PRIVATE_CHANNEL);
: WIRE_GOSSIP_STORE_PRIVATE_CHANNEL_OBS);
chan->bcast.index =
gossip_store_add(rstate->gs, zombie_announcement,
chan->bcast.timestamp,
@ -1627,12 +1627,12 @@ bool routing_add_channel_update(struct routing_state *rstate,
gossip_store_delete(rstate->gs, &chan->half[!direction].rgraph,
is_chan_public(chan)
? WIRE_CHANNEL_UPDATE
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE);
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE_OBS);
}
gossip_store_delete(rstate->gs, &chan->half[!direction].bcast,
is_chan_public(chan)
? WIRE_CHANNEL_UPDATE
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE);
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE_OBS);
chan->half[!direction].bcast.index =
gossip_store_add(rstate->gs, zombie_update[0],
chan->half[!direction].bcast.timestamp,
@ -2219,7 +2219,7 @@ bool routing_add_private_channel(struct routing_state *rstate,
/* Create new (unannounced) channel */
chan = new_chan(rstate, &scid, &node_id[0], &node_id[1], capacity);
if (!index) {
u8 *msg = towire_gossip_store_private_channel(tmpctx,
u8 *msg = towire_gossip_store_private_channel_obs(tmpctx,
capacity,
chan_ann);
index = gossip_store_add(rstate->gs, msg, 0, false, false, false,

View File

@ -435,4 +435,14 @@ bool node_has_broadcastable_channels(const struct node *node);
const char *unfinalized_entries(const tal_t *ctx, struct routing_state *rstate);
void remove_all_gossip(struct routing_state *rstate);
/* We have an update for one of our channels (or unknown). */
void tell_lightningd_peer_update(struct routing_state *rstate,
const struct node_id *source_peer,
struct short_channel_id scid,
u32 fee_base_msat,
u32 fee_ppm,
u16 cltv_delta,
struct amount_msat htlc_minimum,
struct amount_msat htlc_maximum);
#endif /* LIGHTNING_GOSSIPD_ROUTING_H */

View File

@ -743,7 +743,7 @@ static bool extract_scid(int gosstore_fd, size_t off, u16 type,
/* For delete_chan scid immediately follows type */
if (type == WIRE_GOSSIP_STORE_DELETE_CHAN)
off += 2;
else if (type == WIRE_GOSSIP_STORE_PRIVATE_UPDATE)
else if (type == WIRE_GOSSIP_STORE_PRIVATE_UPDATE_OBS)
/* Prepend header */
off += 2 + 2 + update_scid_off;
else if (type == WIRE_CHANNEL_UPDATE)
@ -841,7 +841,7 @@ static struct command_result *channels_refresh(struct command *cmd,
/* If we see a channel_announcement, we don't care until we
* see the channel_update */
if (type == WIRE_CHANNEL_UPDATE
|| type == WIRE_GOSSIP_STORE_PRIVATE_UPDATE) {
|| type == WIRE_GOSSIP_STORE_PRIVATE_UPDATE_OBS) {
/* This can fail if entry not fully written yet. */
if (!extract_scid(gosstore_fd, off, type, &scid)) {
gosstore_channels_off = off;