gossipd: remove routing.c and other unused functions.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-01-31 16:14:13 +10:30
parent c286241ab3
commit f7b7cf3719
9 changed files with 107 additions and 2346 deletions

View File

@ -7,11 +7,10 @@ GOSSIPD_HEADERS_WSRC := gossipd/gossipd_wiregen.h \
gossipd/gossip_store.h \
gossipd/gossmap_manage.h \
gossipd/queries.h \
gossipd/routing.h \
gossipd/txout_failures.h \
gossipd/sigcheck.h \
gossipd/seeker.h
GOSSIPD_HEADERS := $(GOSSIPD_HEADERS_WSRC) gossipd/broadcast.h
GOSSIPD_HEADERS := $(GOSSIPD_HEADERS_WSRC)
GOSSIPD_SRC := $(GOSSIPD_HEADERS_WSRC:.h=.c)
GOSSIPD_OBJS := $(GOSSIPD_SRC:.c=.o)

View File

@ -1,20 +0,0 @@
#ifndef LIGHTNING_GOSSIPD_BROADCAST_H
#define LIGHTNING_GOSSIPD_BROADCAST_H
#include "config.h"
#include <ccan/short_types/short_types.h>
/* This is nested inside a node, chan or half_chan; rewriting the store can
* cause it to change! */
struct broadcastable {
/* This is also the offset within the gossip_store; even with 1M
* channels we still have a factor of 8 before this wraps. */
u32 index;
u32 timestamp;
};
static inline void broadcastable_init(struct broadcastable *bcast)
{
bcast->index = 0;
}
#endif /* LIGHTNING_GOSSIPD_BROADCAST_H */

View File

@ -8,7 +8,6 @@
#include <common/status.h>
#include <errno.h>
#include <fcntl.h>
#include <gossipd/broadcast.h>
#include <gossipd/gossip_store.h>
#include <gossipd/gossip_store_wiregen.h>
#include <gossipd/gossipd.h>
@ -391,149 +390,6 @@ u64 gossip_store_add(struct gossip_store *gs, const u8 *gossip_msg,
return off;
}
void gossip_store_mark_dying(struct gossip_store *gs,
const struct broadcastable *bcast,
int type)
{
const u8 *msg;
be16 flags;
/* Should never get here during loading! */
assert(gs->writable);
/* Should never try to overwrite version */
assert(bcast->index);
/* Sanity check, that this is a channel announcement */
msg = gossip_store_get(tmpctx, gs, bcast->index);
if (fromwire_peektype(msg) != type) {
status_broken("gossip_store incorrect dying msg not %u @%u of %"PRIu64": %s",
type, bcast->index, gs->len, tal_hex(tmpctx, msg));
return;
}
if (pread(gs->fd, &flags, sizeof(flags), bcast->index) != sizeof(flags)) {
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Could not read to mark dying at %u/%"PRIu64": %s",
bcast->index, gs->len, strerror(errno));
}
flags |= cpu_to_be16(GOSSIP_STORE_DYING_BIT);
if (pwrite(gs->fd, &flags, sizeof(flags), bcast->index) != sizeof(flags))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed writing flags to dying @%u: %s",
bcast->index, strerror(errno));
}
/* Returns index of following entry. */
static u32 flag_by_index(struct gossip_store *gs, u32 index, int flag, int type)
{
struct {
beint16_t beflags;
beint16_t belen;
} hdr;
/* Should never get here during loading! */
assert(gs->writable);
/* Should never try to overwrite version */
assert(index);
/* FIXME: debugging a gs->len overrun issue reported in #6270 */
if (pread(gs->fd, &hdr, sizeof(hdr), index) != sizeof(hdr)) {
status_broken("gossip_store pread fail during flag %u @%u type: %i"
" gs->len: %"PRIu64, flag, index, type, gs->len);
return index;
}
if (index + sizeof(struct gossip_hdr) +
be16_to_cpu(hdr.belen) > gs->len) {
status_broken("gossip_store overrun during flag-%u @%u type: %i"
" gs->len: %"PRIu64, flag, index, type, gs->len);
return index;
}
const u8 *msg = gossip_store_get(tmpctx, gs, index);
if(fromwire_peektype(msg) != type) {
status_broken("asked to flag-%u type %i @%u but store contains "
"%i (gs->len=%"PRIu64"): %s",
flag, type, index, fromwire_peektype(msg),
gs->len, tal_hex(tmpctx, msg));
return index;
}
assert((be16_to_cpu(hdr.beflags) & flag) == 0);
hdr.beflags |= cpu_to_be16(flag);
if (pwrite(gs->fd, &hdr.beflags, sizeof(hdr.beflags), index) != sizeof(hdr.beflags))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed writing flags to delete @%u: %s",
index, strerror(errno));
return index + sizeof(struct gossip_hdr) + be16_to_cpu(hdr.belen);
}
void gossip_store_del(struct gossip_store *gs,
u64 offset,
int type)
{
u32 next_index;
assert(offset > sizeof(struct gossip_hdr));
next_index = flag_by_index(gs, offset - sizeof(struct gossip_hdr),
GOSSIP_STORE_DELETED_BIT,
type);
/* For a channel_announcement, we need to delete amount too */
if (type == WIRE_CHANNEL_ANNOUNCEMENT)
flag_by_index(gs, next_index,
GOSSIP_STORE_DELETED_BIT,
WIRE_GOSSIP_STORE_CHANNEL_AMOUNT);
}
void gossip_store_flag(struct gossip_store *gs,
u64 offset,
u16 flag,
int type)
{
assert(offset > sizeof(struct gossip_hdr));
flag_by_index(gs, offset - sizeof(struct gossip_hdr), flag, type);
}
void gossip_store_delete(struct gossip_store *gs,
struct broadcastable *bcast,
int type)
{
if (!bcast->index)
return;
gossip_store_del(gs, bcast->index + sizeof(struct gossip_hdr), type);
/* Reset index. */
bcast->index = 0;
}
void gossip_store_mark_channel_deleted(struct gossip_store *gs,
const struct short_channel_id *scid)
{
gossip_store_add(gs, towire_gossip_store_delete_chan(tmpctx, scid),
0, false, NULL);
}
u32 gossip_store_get_timestamp(struct gossip_store *gs, u64 offset)
{
struct gossip_hdr hdr;
assert(offset > sizeof(struct gossip_hdr));
if (pread(gs->fd, &hdr, sizeof(hdr), offset - sizeof(hdr)) != sizeof(hdr)) {
status_broken("gossip_store overrun during get_timestamp @%"PRIu64
" gs->len: %"PRIu64, offset, gs->len);
return 0;
}
return be32_to_cpu(hdr.timestamp);
}
static const u8 *gossip_store_get_with_hdr(const tal_t *ctx,
struct gossip_store *gs,
u64 offset,
@ -575,6 +431,111 @@ static const u8 *gossip_store_get_with_hdr(const tal_t *ctx,
return msg;
}
static bool check_msg_type(struct gossip_store *gs, u32 index, int flag, int type)
{
struct gossip_hdr hdr;
const u8 *msg = gossip_store_get_with_hdr(tmpctx, gs, index, &hdr);
if (fromwire_peektype(msg) == type)
return true;
status_broken("asked to flag-%u type %i @%u but store contains "
"%i (gs->len=%"PRIu64"): %s",
flag, type, index, fromwire_peektype(msg),
gs->len, tal_hex(tmpctx, msg));
return false;
}
/* Returns index of following entry. */
static u32 flag_by_index(struct gossip_store *gs, u32 index, int flag, int type)
{
struct {
beint16_t beflags;
beint16_t belen;
} hdr;
/* Should never get here during loading! */
assert(gs->writable);
/* Should never try to overwrite version */
assert(index);
/* FIXME: debugging a gs->len overrun issue reported in #6270 */
if (pread(gs->fd, &hdr, sizeof(hdr), index) != sizeof(hdr)) {
status_broken("gossip_store pread fail during flag %u @%u type: %i"
" gs->len: %"PRIu64, flag, index, type, gs->len);
return index;
}
if (index + sizeof(struct gossip_hdr) +
be16_to_cpu(hdr.belen) > gs->len) {
status_broken("gossip_store overrun during flag-%u @%u type: %i"
" gs->len: %"PRIu64, flag, index, type, gs->len);
return index;
}
if (!check_msg_type(gs, index, flag, type))
return index;
assert((be16_to_cpu(hdr.beflags) & flag) == 0);
hdr.beflags |= cpu_to_be16(flag);
if (pwrite(gs->fd, &hdr.beflags, sizeof(hdr.beflags), index) != sizeof(hdr.beflags))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed writing flags to delete @%u: %s",
index, strerror(errno));
return index + sizeof(struct gossip_hdr) + be16_to_cpu(hdr.belen);
}
void gossip_store_del(struct gossip_store *gs,
u64 offset,
int type)
{
u32 next_index;
assert(offset > sizeof(struct gossip_hdr));
next_index = flag_by_index(gs, offset - sizeof(struct gossip_hdr),
GOSSIP_STORE_DELETED_BIT,
type);
/* For a channel_announcement, we need to delete amount too */
if (type == WIRE_CHANNEL_ANNOUNCEMENT)
flag_by_index(gs, next_index,
GOSSIP_STORE_DELETED_BIT,
WIRE_GOSSIP_STORE_CHANNEL_AMOUNT);
}
void gossip_store_flag(struct gossip_store *gs,
u64 offset,
u16 flag,
int type)
{
assert(offset > sizeof(struct gossip_hdr));
flag_by_index(gs, offset - sizeof(struct gossip_hdr), flag, type);
}
void gossip_store_mark_channel_deleted(struct gossip_store *gs,
const struct short_channel_id *scid)
{
gossip_store_add(gs, towire_gossip_store_delete_chan(tmpctx, scid),
0, false, NULL);
}
u32 gossip_store_get_timestamp(struct gossip_store *gs, u64 offset)
{
struct gossip_hdr hdr;
assert(offset > sizeof(struct gossip_hdr));
if (pread(gs->fd, &hdr, sizeof(hdr), offset - sizeof(hdr)) != sizeof(hdr)) {
status_broken("gossip_store overrun during get_timestamp @%"PRIu64
" gs->len: %"PRIu64, offset, gs->len);
return 0;
}
return be32_to_cpu(hdr.timestamp);
}
void gossip_store_set_timestamp(struct gossip_store *gs, u64 offset, u32 timestamp)
{
struct gossip_hdr hdr;
@ -598,27 +559,6 @@ void gossip_store_set_timestamp(struct gossip_store *gs, u64 offset, u32 timesta
offset, strerror(errno));
}
const u8 *gossip_store_get(const tal_t *ctx,
struct gossip_store *gs,
u64 offset)
{
struct gossip_hdr hdr;
return gossip_store_get_with_hdr(ctx, gs, offset, &hdr);
}
int gossip_store_readonly_fd(struct gossip_store *gs)
{
int fd = open(GOSSIP_STORE_FILENAME, O_RDONLY);
/* Skip over version header */
if (fd != -1 && lseek(fd, 1, SEEK_SET) != 1) {
close_noerr(fd);
fd = -1;
}
return fd;
}
u32 gossip_store_load(struct gossip_store *gs)
{
struct gossip_hdr hdr;

View File

@ -42,15 +42,6 @@ u64 gossip_store_add(struct gossip_store *gs, const u8 *gossip_msg,
const u8 *addendum);
/**
* Delete the broadcast associated with this (if any).
*
* In developer mode, checks that type is correct.
*/
void gossip_store_delete(struct gossip_store *gs,
struct broadcastable *bcast,
int type);
/**
* Delete the record at this offset (offset is that of
* record, not header, unlike bcast->index!).
@ -79,26 +70,6 @@ void gossip_store_flag(struct gossip_store *gs,
void gossip_store_mark_channel_deleted(struct gossip_store *gs,
const struct short_channel_id *scid);
/**
* Mark this channel_announcement/channel_update as dying.
*
* We'll clean it up in 12 blocks, but this tells connectd not to gossip
* about it.
*/
void gossip_store_mark_dying(struct gossip_store *gs,
const struct broadcastable *bcast,
int type);
/**
* Direct store accessor: loads gossip msg back from store.
*
* Caller must ensure offset != 0. Never returns NULL.
*/
const u8 *gossip_store_get(const tal_t *ctx,
struct gossip_store *gs,
u64 offset);
/**
* Direct store accessor: get timestamp header for a record.
*
@ -113,12 +84,4 @@ u32 gossip_store_get_timestamp(struct gossip_store *gs, u64 offset);
*/
void gossip_store_set_timestamp(struct gossip_store *gs, u64 offset, u32 timestamp);
/**
* Get a readonly fd for the gossip_store.
* @gs: the gossip store.
*
* Returns -1 on failure, and sets errno.
*/
int gossip_store_readonly_fd(struct gossip_store *gs);
#endif /* LIGHTNING_GOSSIPD_GOSSIP_STORE_H */

View File

@ -26,13 +26,13 @@
#include <common/wireaddr.h>
#include <connectd/connectd_gossipd_wiregen.h>
#include <errno.h>
#include <gossipd/gossip_store.h>
#include <gossipd/gossip_store_wiregen.h>
#include <gossipd/gossipd.h>
#include <gossipd/gossipd_peerd_wiregen.h>
#include <gossipd/gossipd_wiregen.h>
#include <gossipd/gossmap_manage.h>
#include <gossipd/queries.h>
#include <gossipd/routing.h>
#include <gossipd/seeker.h>
#include <sodium/crypto_aead_chacha20poly1305.h>

View File

@ -148,11 +148,6 @@ void queue_peer_msg(struct daemon *daemon,
const struct node_id *peer,
const u8 *msg TAKES);
/* Queue a gossip_store message for the peer: the subdaemon on the
* other end simply forwards it to the peer. */
void queue_peer_from_store(struct peer *peer,
const struct broadcastable *bcast);
/* We have an update for one of our channels (or unknown). */
void tell_lightningd_peer_update(struct daemon *daemon,
const struct node_id *source_peer,

View File

@ -53,10 +53,6 @@ bool query_short_channel_ids(struct daemon *daemon,
const u8 *query_flags,
void (*cb)(struct peer *peer_, bool complete));
struct io_plan *dev_query_channel_range(struct io_conn *conn,
struct daemon *daemon,
const u8 *msg);
/* This is a testing hack to allow us to artificially lower the maximum bytes
* of short_channel_ids we'll encode, using dev_set_max_scids_encode_size. */
void dev_set_max_scids_encode_size(struct daemon *daemon, const u8 *msg);

File diff suppressed because it is too large Load Diff

View File

@ -1,350 +0,0 @@
#ifndef LIGHTNING_GOSSIPD_ROUTING_H
#define LIGHTNING_GOSSIPD_ROUTING_H
#include "config.h"
#include <bitcoin/pubkey.h>
#include <ccan/crypto/siphash24/siphash24.h>
#include <ccan/htable/htable_type.h>
#include <ccan/intmap/intmap.h>
#include <ccan/time/time.h>
#include <common/amount.h>
#include <common/gossip_constants.h>
#include <common/node_id.h>
#include <common/route.h>
#include <gossipd/broadcast.h>
#include <gossipd/gossip_store.h>
#include <gossipd/gossipd.h>
#include <wire/onion_wire.h>
#include <wire/wire.h>
struct daemon;
struct peer;
struct routing_state;
struct half_chan {
/* Timestamp and index into store file - safe to broadcast */
struct broadcastable bcast;
};
struct chan {
struct short_channel_id scid;
/*
* half[0]->src == nodes[0] half[0]->dst == nodes[1]
* half[1]->src == nodes[1] half[1]->dst == nodes[0]
*/
struct half_chan half[2];
/* node[0].id < node[1].id */
struct node *nodes[2];
/* Timestamp and index into store file */
struct broadcastable bcast;
struct amount_sat sat;
};
/* Use this instead of tal_free(chan)! */
void free_chan(struct routing_state *rstate, struct chan *chan);
static inline bool is_halfchan_defined(const struct half_chan *hc)
{
return hc->bcast.index != 0;
}
/* Container for per-node channel pointers. Better cache performance
* than uintmap, and we don't need ordering. */
static inline const struct short_channel_id *chan_map_scid(const struct chan *c)
{
return &c->scid;
}
static inline size_t hash_scid(const struct short_channel_id *scid)
{
/* scids cost money to generate, so simple hash works here */
return (scid->u64 >> 32) ^ (scid->u64 >> 16) ^ scid->u64;
}
static inline bool chan_eq_scid(const struct chan *c,
const struct short_channel_id *scid)
{
return short_channel_id_eq(scid, &c->scid);
}
HTABLE_DEFINE_TYPE(struct chan, chan_map_scid, hash_scid, chan_eq_scid, chan_map);
struct node {
struct node_id id;
/* Timestamp and index into store file */
struct broadcastable bcast;
/* Channels connecting us to other nodes */
/* For a small number of channels (by far the most common) we
* use a simple array, with empty buckets NULL. For larger, we use a
* proper hash table, with the extra allocations that implies.
*
* As of November 2022, 5 or 6 gives the optimal size.
*/
struct chan *chan_arr[6];
/* If we have more than that, we use a hash. */
struct chan_map *chan_map;
};
const struct node_id *node_map_keyof_node(const struct node *n);
size_t node_map_hash_key(const struct node_id *pc);
bool node_map_node_eq(const struct node *n, const struct node_id *pc);
HTABLE_DEFINE_TYPE(struct node, node_map_keyof_node, node_map_hash_key, node_map_node_eq, node_map);
/* We've unpacked and checked its signatures, now we wait for master to tell
* us the txout to check */
struct pending_cannouncement {
/* Unpacked fields here */
/* also the key in routing_state->pending_cannouncements */
struct short_channel_id short_channel_id;
struct node_id node_id_1;
struct node_id node_id_2;
struct pubkey bitcoin_key_1;
struct pubkey bitcoin_key_2;
struct node_id *source_peer;
/* The raw bits */
const u8 *announce;
/* Deferred updates, if we received them while waiting for
* this (one for each direction) */
const u8 *updates[2];
/* Peers responsible */
struct node_id *update_source_peer[2];
/* Only ever replace with newer updates */
u32 update_timestamps[2];
};
static inline const struct short_channel_id *panding_cannouncement_map_scid(
const struct pending_cannouncement *pending_ann)
{
return &pending_ann->short_channel_id;
}
static inline size_t hash_pending_cannouncement_scid(
const struct short_channel_id *scid)
{
/* like hash_scid() for struct chan above */
return (scid->u64 >> 32) ^ (scid->u64 >> 16) ^ scid->u64;
}
static inline bool pending_cannouncement_eq_scid(
const struct pending_cannouncement *pending_ann,
const struct short_channel_id *scid)
{
return short_channel_id_eq(scid, &pending_ann->short_channel_id);
}
HTABLE_DEFINE_TYPE(struct pending_cannouncement, panding_cannouncement_map_scid,
hash_pending_cannouncement_scid, pending_cannouncement_eq_scid,
pending_cannouncement_map);
struct pending_node_map;
struct unupdated_channel;
/* If you know n is one end of the channel, get index of src == n */
static inline int half_chan_idx(const struct node *n, const struct chan *chan)
{
int idx = (chan->nodes[1] == n);
assert(chan->nodes[0] == n || chan->nodes[1] == n);
return idx;
}
struct routing_state {
struct daemon *daemon;
/* All known nodes. */
struct node_map *nodes;
/* node_announcements which are waiting on pending_cannouncement */
struct pending_node_map *pending_node_map;
/* channel_announcement which are pending short_channel_id lookup */
struct pending_cannouncement_map *pending_cannouncements;
/* A map of channels indexed by short_channel_ids */
UINTMAP(struct chan *) chanmap;
/* A map of channel_announcements indexed by short_channel_ids:
* we haven't got a channel_update for these yet. */
UINTMAP(struct unupdated_channel *) unupdated_chanmap;
/* Cache for txout queries that failed. Allows us to skip failed
* checks if we get another announcement for the same scid. */
struct txout_failures *txf;
/* Channels which are closed, but we're waiting 12 blocks */
struct dying_channel *dying_channels;
};
/* Which direction are we? False if neither. */
static inline bool local_direction(struct routing_state *rstate,
const struct chan *chan,
int *direction)
{
for (int dir = 0; dir <= 1; (dir)++) {
if (node_id_eq(&chan->nodes[dir]->id, &rstate->daemon->id)) {
if (direction)
*direction = dir;
return true;
}
}
return false;
}
static inline struct chan *
get_channel(const struct routing_state *rstate,
const struct short_channel_id *scid)
{
return uintmap_get(&rstate->chanmap, scid->u64);
}
struct routing_state *new_routing_state(const tal_t *ctx,
struct daemon *daemon);
/**
* Add a new bidirectional channel from id1 to id2 with the given
* short_channel_id and capacity to the local network view. The channel may not
* already exist, and might create the node entries for the two endpoints, if
* they do not exist yet.
*/
struct chan *new_chan(struct routing_state *rstate,
const struct short_channel_id *scid,
const struct node_id *id1,
const struct node_id *id2,
struct amount_sat sat);
/* Handlers for incoming messages */
/**
* handle_channel_announcement -- Check channel announcement is valid
*
* Returns error message if we should fail channel. Make *scid non-NULL
* (for checking) if we extracted a short_channel_id, otherwise ignore.
*/
u8 *handle_channel_announcement(struct routing_state *rstate,
const u8 *announce TAKES,
u32 current_blockheight,
const struct short_channel_id **scid,
const struct node_id *source_peer TAKES);
/**
* handle_pending_cannouncement -- handle channel_announce once we've
* completed short_channel_id lookup. Returns true if handling created
* a new channel.
*/
bool handle_pending_cannouncement(struct daemon *daemon,
struct routing_state *rstate,
const struct short_channel_id *scid,
const struct amount_sat sat,
const u8 *txscript);
/* Iterate through channels in a node */
struct chan *first_chan(const struct node *node, struct chan_map_iter *i);
struct chan *next_chan(const struct node *node, struct chan_map_iter *i);
/* Returns NULL if all OK, otherwise an error for the peer which sent.
* If the error is that the channel is unknown, fills in *unknown_scid
* (if not NULL). */
u8 *handle_channel_update(struct routing_state *rstate, const u8 *update TAKES,
const struct node_id *source_peer TAKES,
struct short_channel_id *unknown_scid,
bool force);
/* Returns NULL if all OK, otherwise an error for the peer which sent.
* If was_unknown is not NULL, sets it to true if that was the reason for
* the error: the node was unknown to us. */
u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann,
const struct node_id *source_peer TAKES,
bool *was_unknown);
/* Get a node: use this instead of node_map_get() */
struct node *get_node(struct routing_state *rstate,
const struct node_id *id);
void route_prune(struct routing_state *rstate);
/**
* Add a channel_announcement to the network view without checking it
*
* Directly add the channel to the local network, without checking it first. Use
* this only for messages from trusted sources. Untrusted sources should use the
* @see{handle_channel_announcement} entrypoint to check before adding.
*
* index is usually 0, in which case it's set by insert_broadcast adding it
* to the store.
*
* source_peer is an optional peer responsible for this.
*/
bool routing_add_channel_announcement(struct routing_state *rstate,
const u8 *msg TAKES,
struct amount_sat sat,
u32 index,
const struct node_id *source_peer TAKES);
/**
* Add a channel_update without checking for errors
*
* Used to actually insert the information in the channel update into the local
* network view. Only use this for messages that are known to be good. For
* untrusted source, requiring verification please use
* @see{handle_channel_update}
*/
bool routing_add_channel_update(struct routing_state *rstate,
const u8 *update TAKES,
u32 index,
const struct node_id *source_peer TAKES,
bool ignore_timestamp);
/**
* Add a node_announcement to the network view without checking it
*
* Directly add the node being announced to the network view, without verifying
* it. This must be from a trusted source, e.g., gossip_store. For untrusted
* sources (peers) please use @see{handle_node_announcement}.
*/
bool routing_add_node_announcement(struct routing_state *rstate,
const u8 *msg TAKES,
u32 index,
const struct node_id *source_peer TAKES,
bool *was_unknown);
/**
* Add to rstate->dying_channels
*
* Exposed here for when we load the gossip_store.
*/
void remember_chan_dying(struct routing_state *rstate,
const struct short_channel_id *scid,
u32 deadline_blockheight,
u64 index);
/**
* When a channel's funding has been spent.
*/
void routing_channel_spent(struct routing_state *rstate,
u32 current_blockheight,
struct chan *chan);
/**
* Clean up any dying channels.
*
* This finally deletes channel past their deadline.
*/
void routing_expire_channels(struct routing_state *rstate, u32 blockheight);
/* Does this node have public channels? */
bool node_has_broadcastable_channels(const struct node *node);
/* Returns an error string if there are unfinalized entries after load */
const char *unfinalized_entries(const tal_t *ctx, struct routing_state *rstate);
void remove_all_gossip(struct routing_state *rstate);
#endif /* LIGHTNING_GOSSIPD_ROUTING_H */