lightningd: speed mapping from coinmoves table to channel for listcoinmoves.

Iterating through every peer and channel every time can be very slow
for large nodes, when calling wallet_coinmoves_extract for listcoinmoves.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2025-08-19 10:30:45 +09:30
parent f7e9af23c1
commit 233628ad48
6 changed files with 55 additions and 15 deletions

View File

@@ -312,6 +312,20 @@ void channel_add_old_scid(struct channel *channel,
chanmap_add(channel->peer->ld, channel, old_scid);
}
static void remove_from_dbid_map(struct channel *channel)
{
if (!channel_dbid_map_del(channel->peer->ld->channels_by_dbid, channel))
abort();
}
void add_channel_to_dbid_map(struct lightningd *ld,
struct channel *channel)
{
assert(channel->dbid != 0);
channel_dbid_map_add(ld->channels_by_dbid, channel);
tal_add_destructor(channel, remove_from_dbid_map);
}
struct channel *new_unsaved_channel(struct peer *peer,
u32 feerate_base,
u32 feerate_ppm)
@@ -698,6 +712,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
channel->rr_number = peer->ld->rr_counter++;
tal_add_destructor(channel, destroy_channel);
add_channel_to_dbid_map(peer->ld, channel);
list_head_init(&channel->inflights);
channel->closer = closer;
@@ -842,20 +857,7 @@ struct channel *any_channel_by_scid(struct lightningd *ld,
struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid)
{
struct peer *p;
struct channel *chan;
struct peer_node_id_map_iter it;
/* FIXME: Support lookup by id directly! */
for (p = peer_node_id_map_first(ld->peers, &it);
p;
p = peer_node_id_map_next(ld->peers, &it)) {
list_for_each(&p->channels, chan, list) {
if (chan->dbid == dbid)
return chan;
}
}
return NULL;
return channel_dbid_map_get(ld->channels_by_dbid, dbid);
}
struct channel *channel_by_cid(struct lightningd *ld,

View File

@@ -784,6 +784,27 @@ static inline bool channel_state_open_uncommitted(enum channel_state state)
abort();
}
static inline size_t channel_dbid_hash(u64 dbid)
{
return siphash24(siphash_seed(), &dbid, sizeof(dbid));
}
static u64 channel_dbid(const struct channel *channel)
{
assert(channel->dbid);
return channel->dbid;
}
static bool channel_dbid_eq(const struct channel *channel, u64 dbid)
{
return channel->dbid == dbid;
}
/* Defines struct channel_dbid_map */
HTABLE_DEFINE_NODUPS_TYPE(struct channel,
channel_dbid, channel_dbid_hash, channel_dbid_eq,
channel_dbid_map);
void add_channel_to_dbid_map(struct lightningd *ld, struct channel *channel);
void channel_set_owner(struct channel *channel, struct subd *owner);

View File

@@ -1446,6 +1446,7 @@ wallet_commit_channel(struct lightningd *ld,
channel_info->old_remote_per_commit = channel_info->remote_per_commit;
/* Promote the unsaved_dbid to the dbid */
assert(channel->dbid == 0);
assert(channel->unsaved_dbid != 0);
channel->dbid = channel->unsaved_dbid;
channel->unsaved_dbid = 0;
@@ -1524,6 +1525,9 @@ wallet_commit_channel(struct lightningd *ld,
/* Now we finally put it in the database. */
wallet_channel_insert(ld->wallet, channel);
/* So we can find it by the newly-assigned dbid */
add_channel_to_dbid_map(ld, channel);
/* Open attempt to channel's inflights */
inflight = new_inflight(channel,
NULL,

View File

@@ -213,6 +213,10 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
ld->channels_by_scid = tal(ld, struct channel_scid_map);
channel_scid_map_init(ld->channels_by_scid);
/*~ Coin movements in db are indexed by the channel dbid. */
ld->channels_by_dbid = tal(ld, struct channel_dbid_map);
channel_dbid_map_init(ld->channels_by_dbid);
/*~ For multi-part payments, we need to keep some incoming payments
* in limbo until we get all the parts, or we time them out. */
ld->htlc_sets = tal(ld, struct htlc_set_map);

View File

@@ -218,6 +218,9 @@ struct lightningd {
/* Here are all our channels and their aliases */
struct channel_scid_map *channels_by_scid;
/* Open channels by dbid */
struct channel_dbid_map *channels_by_dbid;
/* Outstanding connect commands. */
struct list_head connects;