Skip to content

Commit d4253fc

Browse files
committed
lightningd: keep closed channels in memory.
They're small, and this will allow us to efficiently respond to reestablish on them. Signed-off-by: Rusty Russell <[email protected]>
1 parent 1903d74 commit d4253fc

11 files changed

+118
-22
lines changed

lightningd/channel.c

+2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ void delete_channel(struct channel *channel STEALS, bool completely_eliminate)
9999
/* Never open at all, not ours. */
100100
if (completely_eliminate)
101101
wallet_channel_delete(ld->wallet, channel);
102+
else
103+
wallet_load_one_closed_channel(ld->wallet, ld->closed_channels, channel->dbid);
102104
}
103105

104106
/* Tell the hsm to forget the channel, needs to be after it's

lightningd/closed_channel.c

+13-6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
#include <lightningd/peer_control.h>
1111
#include <wallet/wallet.h>
1212

13+
size_t hash_cid(const struct channel_id *cid)
14+
{
15+
return siphash24(siphash_seed(), cid->id, sizeof(cid->id));
16+
}
17+
1318
static void json_add_closed_channel(struct json_stream *response,
1419
const char *fieldname,
1520
const struct closed_channel *channel)
@@ -90,7 +95,8 @@ static struct command_result *json_listclosedchannels(struct command *cmd,
9095
{
9196
struct node_id *peer_id;
9297
struct json_stream *response;
93-
struct closed_channel **chans;
98+
struct closed_channel *cc;
99+
struct closed_channel_map_iter it;
94100

95101
if (!param(cmd, buffer, params,
96102
p_opt("id", param_node_id, &peer_id),
@@ -100,15 +106,16 @@ static struct command_result *json_listclosedchannels(struct command *cmd,
100106
response = json_stream_success(cmd);
101107
json_array_start(response, "closedchannels");
102108

103-
chans = wallet_load_closed_channels(cmd, cmd->ld->wallet);
104-
for (size_t i = 0; i < tal_count(chans); i++) {
109+
for (cc = closed_channel_map_first(cmd->ld->closed_channels, &it);
110+
cc;
111+
cc = closed_channel_map_next(cmd->ld->closed_channels, &it)) {
105112
if (peer_id) {
106-
if (!chans[i]->peer_id)
113+
if (!cc->peer_id)
107114
continue;
108-
if (!node_id_eq(chans[i]->peer_id, peer_id))
115+
if (!node_id_eq(cc->peer_id, peer_id))
109116
continue;
110117
}
111-
json_add_closed_channel(response, NULL, chans[i]);
118+
json_add_closed_channel(response, NULL, cc);
112119
}
113120
json_array_end(response);
114121

lightningd/closed_channel.h

+15
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,19 @@ struct closed_channel {
3030
u64 last_stable_connection;
3131
};
3232

33+
static inline const struct channel_id *keyof_closed_channel(const struct closed_channel *cc)
34+
{
35+
return &cc->cid;
36+
}
37+
38+
size_t hash_cid(const struct channel_id *cid);
39+
40+
static inline bool closed_channel_eq_cid(const struct closed_channel *cc, const struct channel_id *cid)
41+
{
42+
return channel_id_eq(cid, &cc->cid);
43+
}
44+
45+
HTABLE_DEFINE_NODUPS_TYPE(struct closed_channel, keyof_closed_channel, hash_cid, closed_channel_eq_cid,
46+
closed_channel_map);
47+
3348
#endif /* LIGHTNING_LIGHTNINGD_CLOSED_CHANNEL_H */

lightningd/lightningd.c

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include <lightningd/channel.h>
6868
#include <lightningd/channel_control.h>
6969
#include <lightningd/channel_gossip.h>
70+
#include <lightningd/closed_channel.h>
7071
#include <lightningd/coin_mvts.h>
7172
#include <lightningd/connect_control.h>
7273
#include <lightningd/gossip_control.h>
@@ -212,6 +213,11 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
212213
ld->htlc_sets = tal(ld, struct htlc_set_map);
213214
htlc_set_map_init(ld->htlc_sets);
214215

216+
/*~ We keep a map of closed channels. Mainly so we can respond to peers
217+
* who talk to us about long-closed channels. */
218+
ld->closed_channels = tal(ld, struct closed_channel_map);
219+
closed_channel_map_init(ld->closed_channels);
220+
215221
/*~ We have a multi-entry log-book infrastructure: we define a 10MB log
216222
* book to hold all the entries (and trims as necessary), and multiple
217223
* log objects which each can write into it, each with a unique

lightningd/lightningd.h

+3
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,9 @@ struct lightningd {
280280
/* Contains the codex32 string used with --recover flag */
281281
char *recover;
282282

283+
/* Any channels which are already closed */
284+
struct closed_channel_map *closed_channels;
285+
283286
/* 2, unless overridden by --dev-fd-limit-multiplier */
284287
u32 fd_limit_multiplier;
285288

lightningd/memdump.c

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <gossipd/gossipd_wiregen.h>
1212
#include <hsmd/hsmd_wiregen.h>
1313
#include <lightningd/chaintopology.h>
14+
#include <lightningd/closed_channel.h>
1415
#include <lightningd/hsm_control.h>
1516
#include <lightningd/jsonrpc.h>
1617
#include <lightningd/lightningd.h>
@@ -201,6 +202,7 @@ static bool lightningd_check_leaks(struct command *cmd)
201202
memleak_scan_htable(memtable, &ld->htlc_sets->raw);
202203
memleak_scan_htable(memtable, &ld->peers->raw);
203204
memleak_scan_htable(memtable, &ld->peers_by_dbid->raw);
205+
memleak_scan_htable(memtable, &ld->closed_channels->raw);
204206
wallet_memleak_scan(memtable, ld->wallet);
205207

206208
/* Now delete ld and those which it has pointers to. */

lightningd/test/run-find_my_abspath.c

+3
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ void handle_early_opts(struct lightningd *ld UNNEEDED, int argc UNNEEDED, char *
120120
/* Generated stub for handle_opts */
121121
void handle_opts(struct lightningd *ld UNNEEDED)
122122
{ fprintf(stderr, "handle_opts called!\n"); abort(); }
123+
/* Generated stub for hash_cid */
124+
size_t hash_cid(const struct channel_id *cid UNNEEDED)
125+
{ fprintf(stderr, "hash_cid called!\n"); abort(); }
123126
/* Generated stub for hash_htlc_key */
124127
size_t hash_htlc_key(const struct htlc_key *htlc_key UNNEEDED)
125128
{ fprintf(stderr, "hash_htlc_key called!\n"); abort(); }

wallet/test/run-db.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ void get_channel_basepoints(struct lightningd *ld UNNEEDED,
112112
struct basepoints *local_basepoints UNNEEDED,
113113
struct pubkey *local_funding_pubkey UNNEEDED)
114114
{ fprintf(stderr, "get_channel_basepoints called!\n"); abort(); }
115+
/* Generated stub for hash_cid */
116+
size_t hash_cid(const struct channel_id *cid UNNEEDED)
117+
{ fprintf(stderr, "hash_cid called!\n"); abort(); }
115118
/* Generated stub for htlc_in_check */
116119
struct htlc_in *htlc_in_check(const struct htlc_in *hin UNNEEDED, const char *abortstr UNNEEDED)
117120
{ fprintf(stderr, "htlc_in_check called!\n"); abort(); }
@@ -285,8 +288,7 @@ struct peer *new_peer(struct lightningd *ld UNNEEDED, u64 dbid UNNEEDED,
285288
bool connected_incoming UNNEEDED)
286289
{ fprintf(stderr, "new_peer called!\n"); abort(); }
287290
/* Generated stub for notify_chain_mvt */
288-
void notify_chain_mvt(struct lightningd *ld UNNEEDED,
289-
const struct chain_coin_mvt *chain_mvt UNNEEDED)
291+
void notify_chain_mvt(struct lightningd *ld UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED)
290292
{ fprintf(stderr, "notify_chain_mvt called!\n"); abort(); }
291293
/* Generated stub for notify_forward_event */
292294
void notify_forward_event(struct lightningd *ld UNNEEDED,

wallet/test/run-wallet.c

+8-5
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,9 @@ u32 get_block_height(const struct chain_topology *topo UNNEEDED)
380380
/* Generated stub for get_network_blockheight */
381381
u32 get_network_blockheight(const struct chain_topology *topo UNNEEDED)
382382
{ fprintf(stderr, "get_network_blockheight called!\n"); abort(); }
383+
/* Generated stub for hash_cid */
384+
size_t hash_cid(const struct channel_id *cid UNNEEDED)
385+
{ fprintf(stderr, "hash_cid called!\n"); abort(); }
383386
/* Generated stub for hsmd_wire_name */
384387
const char *hsmd_wire_name(int e UNNEEDED)
385388
{ fprintf(stderr, "hsmd_wire_name called!\n"); abort(); }
@@ -701,12 +704,10 @@ struct uncommitted_channel *new_uncommitted_channel(struct peer *peer UNNEEDED)
701704
bool node_announcement_same(const u8 *nann1 UNNEEDED, const u8 *nann2 UNNEEDED)
702705
{ fprintf(stderr, "node_announcement_same called!\n"); abort(); }
703706
/* Generated stub for notify_chain_mvt */
704-
void notify_chain_mvt(struct lightningd *ld UNNEEDED,
705-
const struct chain_coin_mvt *chain_mvt UNNEEDED)
707+
void notify_chain_mvt(struct lightningd *ld UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED)
706708
{ fprintf(stderr, "notify_chain_mvt called!\n"); abort(); }
707709
/* Generated stub for notify_channel_mvt */
708-
void notify_channel_mvt(struct lightningd *ld UNNEEDED,
709-
const struct channel_coin_mvt *chan_mvt UNNEEDED)
710+
void notify_channel_mvt(struct lightningd *ld UNNEEDED, const struct channel_coin_mvt *mvt UNNEEDED)
710711
{ fprintf(stderr, "notify_channel_mvt called!\n"); abort(); }
711712
/* Generated stub for notify_channel_open_failed */
712713
void notify_channel_open_failed(struct lightningd *ld UNNEEDED,
@@ -2118,7 +2119,7 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx)
21182119

21192120
/* do inflights get cleared when the channel is closed?*/
21202121
dbid = chan->dbid;
2121-
delete_channel(chan, false); /* Also clears up peer! */
2122+
delete_channel(chan, true); /* Also clears up peer! */
21222123
CHECK_MSG(count_inflights(w, dbid) == 0, "inflights cleaned up");
21232124
db_commit_transaction(w->db);
21242125
CHECK_MSG(!wallet_err, wallet_err);
@@ -2364,6 +2365,8 @@ int main(int argc, const char *argv[])
23642365
ld->htlcs_out = tal(ld, struct htlc_out_map);
23652366
htlc_out_map_init(ld->htlcs_out);
23662367
list_head_init(&ld->wait_commands);
2368+
ld->closed_channels = tal(ld, struct closed_channel_map);
2369+
closed_channel_map_init(ld->closed_channels);
23672370

23682371
/* We do a runtime test here, so we still check compile! */
23692372
if (HAVE_SQLITE3) {

wallet/wallet.c

+46-6
Original file line numberDiff line numberDiff line change
@@ -2069,11 +2069,10 @@ static struct closed_channel *wallet_stmt2closed_channel(const tal_t *ctx,
20692069
return cc;
20702070
}
20712071

2072-
struct closed_channel **wallet_load_closed_channels(const tal_t *ctx,
2073-
struct wallet *w)
2072+
void wallet_load_closed_channels(struct wallet *w,
2073+
struct closed_channel_map *cc_map)
20742074
{
20752075
struct db_stmt *stmt;
2076-
struct closed_channel **chans = tal_arr(ctx, struct closed_channel *, 0);
20772076

20782077
/* We load all channels */
20792078
stmt = db_prepare_v2(w->db, SQL("SELECT "
@@ -2107,12 +2106,53 @@ struct closed_channel **wallet_load_closed_channels(const tal_t *ctx,
21072106
db_query_prepared(stmt);
21082107

21092108
while (db_step(stmt)) {
2110-
struct closed_channel *cc = wallet_stmt2closed_channel(chans,
2109+
struct closed_channel *cc = wallet_stmt2closed_channel(cc_map,
21112110
w, stmt);
2112-
tal_arr_expand(&chans, cc);
2111+
closed_channel_map_add(cc_map, cc);
21132112
}
21142113
tal_free(stmt);
2115-
return chans;
2114+
}
2115+
2116+
void wallet_load_one_closed_channel(struct wallet *w,
2117+
struct closed_channel_map *cc_map,
2118+
u64 wallet_id)
2119+
{
2120+
struct db_stmt *stmt;
2121+
2122+
stmt = db_prepare_v2(w->db, SQL("SELECT "
2123+
" p.node_id"
2124+
", full_channel_id"
2125+
", scid"
2126+
", alias_local"
2127+
", alias_remote"
2128+
", funder"
2129+
", closer"
2130+
", channel_flags"
2131+
", next_index_local"
2132+
", next_index_remote"
2133+
", next_htlc_id"
2134+
", funding_tx_id"
2135+
", funding_tx_outnum"
2136+
", funding_satoshi"
2137+
", push_msatoshi"
2138+
", msatoshi_local"
2139+
", msatoshi_to_us_min"
2140+
", msatoshi_to_us_max"
2141+
", last_tx"
2142+
", channel_type"
2143+
", state_change_reason"
2144+
", lease_commit_sig"
2145+
", last_stable_connection"
2146+
" FROM channels"
2147+
" LEFT JOIN peers p ON p.id = peer_id"
2148+
" WHERE channels.id = ?;"));
2149+
db_bind_u64(stmt, wallet_id);
2150+
db_query_prepared(stmt);
2151+
2152+
db_step(stmt);
2153+
closed_channel_map_add(cc_map,
2154+
wallet_stmt2closed_channel(cc_map, w, stmt));
2155+
tal_free(stmt);
21162156
}
21172157

21182158
static void set_max_channel_dbid(struct wallet *w)

wallet/wallet.h

+16-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct amount_msat;
2121
struct invoices;
2222
struct channel;
2323
struct channel_inflight;
24+
struct closed_channel_map;
2425
struct htlc_in;
2526
struct htlc_in_map;
2627
struct htlc_out;
@@ -733,13 +734,25 @@ bool wallet_init_channels(struct wallet *w);
733734

734735
/**
735736
* wallet_load_closed_channels -- Loads dead channels.
736-
* @ctx: context to allocate returned array from
737737
* @w: wallet to load from
738+
* @cc_map: the map to fill
738739
*
739740
* These will be all state CLOSED.
740741
*/
741-
struct closed_channel **wallet_load_closed_channels(const tal_t *ctx,
742-
struct wallet *w);
742+
void wallet_load_closed_channels(struct wallet *w,
743+
struct closed_channel_map *cc_map);
744+
745+
/**
746+
* wallet_load_one_closed_channel -- Loads one single (just-closed) channel.
747+
* @w: wallet to load from
748+
* @cc_map: the map to fill
749+
* @wallet_id: the id of the channel.
750+
*
751+
* Must be newly closed via wallet_channel_close().
752+
*/
753+
void wallet_load_one_closed_channel(struct wallet *w,
754+
struct closed_channel_map *cc_map,
755+
u64 wallet_id);
743756

744757
/**
745758
* wallet_channel_stats_incr_* - Increase channel statistics.

0 commit comments

Comments
 (0)