mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 18:11:28 +01:00
gossipd: add shadow structure for local chans.
Normally we'd put a pointer into struct half_chan for local information, but it would be NULL on 99.99% of nodes. Instead, keep a separate hash table. This immediately subsumes the previous "map of local-disabled channels", and will be enhanced further. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
70c4ac6d74
commit
27d9b75456
@ -163,6 +163,10 @@ static void destroy_routing_state(struct routing_state *rstate)
|
||||
chan;
|
||||
chan = uintmap_after(&rstate->chanmap, &idx))
|
||||
free_chan(rstate, chan);
|
||||
|
||||
/* Free up our htables */
|
||||
pending_cannouncement_map_clear(&rstate->pending_cannouncements);
|
||||
local_chan_map_clear(&rstate->local_chan_map);
|
||||
}
|
||||
|
||||
#if DEVELOPER
|
||||
@ -175,6 +179,7 @@ static void memleak_help_routing_tables(struct htable *memtable,
|
||||
memleak_remove_htable(memtable, &rstate->nodes->raw);
|
||||
memleak_remove_htable(memtable, &rstate->pending_node_map->raw);
|
||||
memleak_remove_htable(memtable, &rstate->pending_cannouncements.raw);
|
||||
memleak_remove_htable(memtable, &rstate->local_chan_map.raw);
|
||||
|
||||
for (n = node_map_first(rstate->nodes, &nit);
|
||||
n;
|
||||
@ -204,7 +209,7 @@ struct routing_state *new_routing_state(const tal_t *ctx,
|
||||
|
||||
uintmap_init(&rstate->chanmap);
|
||||
uintmap_init(&rstate->unupdated_chanmap);
|
||||
chan_map_init(&rstate->local_disabled_map);
|
||||
local_chan_map_init(&rstate->local_chan_map);
|
||||
uintmap_init(&rstate->txout_failures);
|
||||
|
||||
rstate->pending_node_map = tal(ctx, struct pending_node_map);
|
||||
@ -388,7 +393,7 @@ static void remove_chan_from_node(struct routing_state *rstate,
|
||||
/* We make sure that free_chan is called on this chan! */
|
||||
static void destroy_chan_check(struct chan *chan)
|
||||
{
|
||||
assert(chan->scid.u64 == (u64)chan);
|
||||
assert(chan->sat.satoshis == (u64)chan); /* Raw: dev-hack */
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -401,11 +406,8 @@ void free_chan(struct routing_state *rstate, struct chan *chan)
|
||||
|
||||
uintmap_del(&rstate->chanmap, chan->scid.u64);
|
||||
|
||||
/* Remove from local_disabled_map if it's there. */
|
||||
chan_map_del(&rstate->local_disabled_map, chan);
|
||||
|
||||
#if DEVELOPER
|
||||
chan->scid.u64 = (u64)chan;
|
||||
chan->sat.satoshis = (u64)chan; /* Raw: dev-hack */
|
||||
#endif
|
||||
tal_free(chan);
|
||||
}
|
||||
@ -431,6 +433,36 @@ static void bad_gossip_order(const u8 *msg, const char *source,
|
||||
details);
|
||||
}
|
||||
|
||||
static void destroy_local_chan(struct local_chan *local_chan,
|
||||
struct routing_state *rstate)
|
||||
{
|
||||
if (!local_chan_map_del(&rstate->local_chan_map, local_chan))
|
||||
abort();
|
||||
}
|
||||
|
||||
static struct local_chan *new_local_chan(struct routing_state *rstate,
|
||||
struct chan *chan)
|
||||
{
|
||||
int direction;
|
||||
struct local_chan *local_chan;
|
||||
|
||||
if (node_id_eq(&chan->nodes[0]->id, &rstate->local_id))
|
||||
direction = 0;
|
||||
else if (node_id_eq(&chan->nodes[1]->id, &rstate->local_id))
|
||||
direction = 1;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
local_chan = tal(chan, struct local_chan);
|
||||
local_chan->chan = chan;
|
||||
local_chan->direction = direction;
|
||||
local_chan->local_disabled = false;
|
||||
|
||||
local_chan_map_add(&rstate->local_chan_map, local_chan);
|
||||
tal_add_destructor2(local_chan, destroy_local_chan, rstate);
|
||||
return local_chan;
|
||||
}
|
||||
|
||||
struct chan *new_chan(struct routing_state *rstate,
|
||||
const struct short_channel_id *scid,
|
||||
const struct node_id *id1,
|
||||
@ -471,6 +503,9 @@ struct chan *new_chan(struct routing_state *rstate,
|
||||
init_half_chan(rstate, chan, !n1idx);
|
||||
|
||||
uintmap_add(&rstate->chanmap, scid->u64, chan);
|
||||
|
||||
/* Initialize shadow structure if it's local */
|
||||
new_local_chan(rstate, chan);
|
||||
return chan;
|
||||
}
|
||||
|
||||
@ -2678,9 +2713,6 @@ void remove_all_gossip(struct routing_state *rstate)
|
||||
/* Now free all the channels. */
|
||||
while ((c = uintmap_first(&rstate->chanmap, &index)) != NULL) {
|
||||
uintmap_del(&rstate->chanmap, index);
|
||||
|
||||
/* Remove from local_disabled_map if it's there. */
|
||||
chan_map_del(&rstate->local_disabled_map, c);
|
||||
tal_free(c);
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,17 @@ struct chan {
|
||||
struct amount_sat sat;
|
||||
};
|
||||
|
||||
/* Shadow structure for local channels: owned by the chan above, but kept
|
||||
* separately to keep `struct chan` minimal since there may be millions
|
||||
* of non-local channels. */
|
||||
struct local_chan {
|
||||
struct chan *chan;
|
||||
int direction;
|
||||
|
||||
/* We soft-disable local channels when a peer disconnects */
|
||||
bool local_disabled;
|
||||
};
|
||||
|
||||
/* Use this instead of tal_free(chan)! */
|
||||
void free_chan(struct routing_state *rstate, struct chan *chan);
|
||||
|
||||
@ -78,7 +89,7 @@ static inline bool is_halfchan_enabled(const struct half_chan *hc)
|
||||
}
|
||||
|
||||
/* Container for per-node channel pointers. Better cache performance
|
||||
* than uintmap, and we don't need ordering. */
|
||||
* 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;
|
||||
@ -98,6 +109,22 @@ static inline bool chan_eq_scid(const struct chan *c,
|
||||
|
||||
HTABLE_DEFINE_TYPE(struct chan, chan_map_scid, hash_scid, chan_eq_scid, chan_map);
|
||||
|
||||
/* Container for local channel pointers. */
|
||||
static inline const struct short_channel_id *local_chan_map_scid(const struct local_chan *local_chan)
|
||||
{
|
||||
return &local_chan->chan->scid;
|
||||
}
|
||||
|
||||
static inline bool local_chan_eq_scid(const struct local_chan *local_chan,
|
||||
const struct short_channel_id *scid)
|
||||
{
|
||||
return short_channel_id_eq(scid, &local_chan->chan->scid);
|
||||
}
|
||||
|
||||
HTABLE_DEFINE_TYPE(struct local_chan,
|
||||
local_chan_map_scid, hash_scid, local_chan_eq_scid,
|
||||
local_chan_map);
|
||||
|
||||
/* 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 allocation that implies. */
|
||||
@ -244,8 +271,8 @@ struct routing_state {
|
||||
* checks if we get another announcement for the same scid. */
|
||||
UINTMAP(bool) txout_failures;
|
||||
|
||||
/* A map of (local) disabled channels by short_channel_ids */
|
||||
struct chan_map local_disabled_map;
|
||||
/* A map of local channels by short_channel_ids */
|
||||
struct local_chan_map local_chan_map;
|
||||
|
||||
#if DEVELOPER
|
||||
/* Override local time for gossip messages */
|
||||
@ -416,26 +443,34 @@ bool handle_local_add_channel(struct routing_state *rstate, const u8 *msg,
|
||||
*/
|
||||
struct timeabs gossip_time_now(const struct routing_state *rstate);
|
||||
|
||||
static inline struct local_chan *is_local_chan(struct routing_state *rstate,
|
||||
const struct chan *chan)
|
||||
{
|
||||
return local_chan_map_get(&rstate->local_chan_map, &chan->scid);
|
||||
}
|
||||
|
||||
/* Because we can have millions of channels, and we only want a local_disable
|
||||
* flag on ones connected to us, we keep a separate hashtable for that flag.
|
||||
*/
|
||||
static inline bool is_chan_local_disabled(struct routing_state *rstate,
|
||||
const struct chan *chan)
|
||||
{
|
||||
return chan_map_get(&rstate->local_disabled_map, &chan->scid) != NULL;
|
||||
struct local_chan *local_chan = is_local_chan(rstate, chan);
|
||||
return local_chan && local_chan->local_disabled;
|
||||
}
|
||||
|
||||
static inline void local_disable_chan(struct routing_state *rstate,
|
||||
const struct chan *chan)
|
||||
{
|
||||
if (!is_chan_local_disabled(rstate, chan))
|
||||
chan_map_add(&rstate->local_disabled_map, chan);
|
||||
struct local_chan *local_chan = is_local_chan(rstate, chan);
|
||||
local_chan->local_disabled = true;
|
||||
}
|
||||
|
||||
static inline void local_enable_chan(struct routing_state *rstate,
|
||||
const struct chan *chan)
|
||||
{
|
||||
chan_map_del(&rstate->local_disabled_map, chan);
|
||||
struct local_chan *local_chan = is_local_chan(rstate, chan);
|
||||
local_chan->local_disabled = false;
|
||||
}
|
||||
|
||||
/* Helper to convert on-wire addresses format to wireaddrs array */
|
||||
|
Loading…
Reference in New Issue
Block a user