From 0440700132144caade6d9c8c9da39e9fa65bd137 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 19 Sep 2024 16:34:20 +0930 Subject: [PATCH] lightningd: move the state changes into `struct channel`. And instead of loading them in listpeerchannels, use them. This means listpeerchannels no longer touches the db. Signed-off-by: Rusty Russell Changelog-Fixed: JSONRPC: `listpeerchannels` (and thus, pay) sped up on very large nodes. --- lightningd/channel.c | 21 +++++++++++++++------ lightningd/channel.h | 6 +++++- lightningd/opening_control.c | 6 ++++-- lightningd/peer_control.c | 14 ++++++-------- wallet/test/run-db.c | 3 ++- wallet/test/run-wallet.c | 3 ++- wallet/wallet.c | 6 +++++- 7 files changed, 39 insertions(+), 20 deletions(-) diff --git a/lightningd/channel.c b/lightningd/channel.c index 1ea3693cde31..646c4f2ed5cd 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -312,6 +312,7 @@ struct channel *new_unsaved_channel(struct peer *peer, channel->stable_conn_timer = NULL; /* Nothing happened yet */ memset(&channel->stats, 0, sizeof(channel->stats)); + channel->state_changes = tal_arr(channel, struct state_change_entry, 0); /* No shachain yet */ channel->their_shachain.id = 0; @@ -448,7 +449,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, /* NULL or stolen */ struct peer_update *peer_update STEALS, u64 last_stable_connection, - const struct channel_stats *stats) + const struct channel_stats *stats, + struct state_change_entry *state_changes STEALS) { struct channel *channel = tal(peer->ld, struct channel); struct amount_msat htlc_min, htlc_max; @@ -606,6 +608,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->last_stable_connection = last_stable_connection; channel->stable_conn_timer = NULL; channel->stats = *stats; + channel->state_changes = tal_steal(channel, state_changes); + /* Populate channel->channel_gossip */ channel_gossip_init(channel, take(peer_update)); @@ -836,8 +840,6 @@ void channel_set_state(struct channel *channel, enum state_change reason, char *why) { - struct timeabs timestamp; - /* set closer, if known */ if (channel_state_closing(state) && channel->closer == NUM_SIDES) { if (reason == REASON_LOCAL) channel->closer = LOCAL; @@ -865,10 +867,17 @@ void channel_set_state(struct channel *channel, /* plugin notification channel_state_changed and DB entry */ if (state != old_state) { /* see issue #4029 */ - timestamp = time_now(); + struct state_change_entry change; + change.timestamp = time_now(); + change.old_state = old_state; + change.new_state = state; + change.cause = reason; + change.message = tal_strdup(channel->state_changes, why); + tal_arr_expand(&channel->state_changes, change); + wallet_state_change_add(channel->peer->ld->wallet, channel->dbid, - timestamp, + change.timestamp, old_state, state, reason, @@ -877,7 +886,7 @@ void channel_set_state(struct channel *channel, &channel->peer->id, &channel->cid, channel->scid, - timestamp, + change.timestamp, old_state, state, reason, diff --git a/lightningd/channel.h b/lightningd/channel.h index 9f1623ad9ab3..864854afa928 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -325,6 +325,9 @@ struct channel { /* Our stats */ struct channel_stats stats; + + /* Our change history. */ + struct state_change_entry *state_changes; }; /* Is channel owned (and should be talking to peer) */ @@ -407,7 +410,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, /* NULL or stolen */ struct peer_update *peer_update STEALS, u64 last_stable_connection, - const struct channel_stats *stats); + const struct channel_stats *stats, + struct state_change_entry *state_changes STEALS); /* new_inflight - Create a new channel_inflight for a channel */ struct channel_inflight *new_inflight(struct channel *channel, diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 197316615661..a52307323605 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -220,7 +220,8 @@ wallet_commit_channel(struct lightningd *ld, ld->config.ignore_fee_limits, NULL, 0, - &zero_channel_stats); + &zero_channel_stats, + tal_arr(NULL, struct state_change_entry, 0)); /* Now we finally put it in the database. */ wallet_channel_insert(ld->wallet, channel); @@ -1598,7 +1599,8 @@ static struct channel *stub_chan(struct command *cmd, false, NULL, 0, - &zero_channel_stats); + &zero_channel_stats, + tal_arr(NULL, struct state_change_entry, 0)); /* We don't want to gossip about this, ever. */ channel->channel_gossip = tal_free(channel->channel_gossip); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 285a209ab6d0..4bace9f47a96 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -820,7 +820,6 @@ static void NON_NULL_ARGS(1, 2, 4, 5) json_add_channel(struct command *cmd, struct lightningd *ld = cmd->ld; struct amount_msat funding_msat; struct amount_sat peer_funded_sats; - struct state_change_entry *state_changes; const struct peer_update *peer_update; u32 feerate; @@ -1161,19 +1160,18 @@ static void NON_NULL_ARGS(1, 2, 4, 5) json_add_channel(struct command *cmd, json_add_num(response, "max_accepted_htlcs", channel->our_config.max_accepted_htlcs); - state_changes = wallet_state_change_get(tmpctx, ld->wallet, channel->dbid); json_array_start(response, "state_changes"); - for (size_t i = 0; i < tal_count(state_changes); i++) { + for (size_t i = 0; i < tal_count(channel->state_changes); i++) { json_object_start(response, NULL); json_add_timeiso(response, "timestamp", - state_changes[i].timestamp); + channel->state_changes[i].timestamp); json_add_string(response, "old_state", - channel_state_str(state_changes[i].old_state)); + channel_state_str(channel->state_changes[i].old_state)); json_add_string(response, "new_state", - channel_state_str(state_changes[i].new_state)); + channel_state_str(channel->state_changes[i].new_state)); json_add_string(response, "cause", - channel_change_state_reason_str(state_changes[i].cause)); - json_add_string(response, "message", state_changes[i].message); + channel_change_state_reason_str(channel->state_changes[i].cause)); + json_add_string(response, "message", channel->state_changes[i].message); json_object_end(response); } json_array_end(response); diff --git a/wallet/test/run-db.c b/wallet/test/run-db.c index 4af4988e7521..445ef118c46b 100644 --- a/wallet/test/run-db.c +++ b/wallet/test/run-db.c @@ -192,7 +192,8 @@ struct channel *new_channel(struct peer *peer UNNEEDED, u64 dbid UNNEEDED, /* NULL or stolen */ struct peer_update *peer_update STEALS UNNEEDED, u64 last_stable_connection UNNEEDED, - const struct channel_stats *stats UNNEEDED) + const struct channel_stats *stats UNNEEDED, + struct state_change_entry *state_changes STEALS UNNEEDED) { fprintf(stderr, "new_channel called!\n"); abort(); } /* Generated stub for new_coin_wallet_deposit */ struct chain_coin_mvt *new_coin_wallet_deposit(const tal_t *ctx UNNEEDED, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 68c961fc3480..0d069701d667 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1997,7 +1997,8 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) false, NULL, 0, - stats); + stats, + tal_arr(NULL, struct state_change_entry, 0)); db_begin_transaction(w->db); CHECK(!wallet_err); wallet_channel_insert(w, chan); diff --git a/wallet/wallet.c b/wallet/wallet.c index fbab37d3dffa..c5b19ea42f6d 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1522,6 +1522,7 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm bool ignore_fee_limits; struct peer_update *remote_update; struct channel_stats stats; + struct state_change_entry *state_changes; peer_dbid = db_col_u64(stmt, "peer_id"); peer = find_peer_by_dbid(w->ld, peer_dbid); @@ -1725,6 +1726,8 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm &stats.out_msatoshi_fulfilled, AMOUNT_MSAT(0)); + /* Stolen by new_channel */ + state_changes = wallet_state_change_get(NULL, w, db_col_u64(stmt, "id")); chan = new_channel(peer, db_col_u64(stmt, "id"), &wshachain, channel_state_in_db(db_col_int(stmt, "state")), @@ -1787,7 +1790,8 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm ignore_fee_limits, remote_update, db_col_u64(stmt, "last_stable_connection"), - &stats); + &stats, + state_changes); if (!wallet_channel_load_inflights(w, chan)) { tal_free(chan);