Skip to content

Commit 4eafc1a

Browse files
committed
chanbackup: cache available peers.
We already get the connected hook, so in there we can add to a hash table of suitable peers. Rather than subscribe to disconnection, we simply remove the peer if a sendcustommsg fails. This does make after_send_scb_single() a bit more complex, since it needs this specific node_id: we use a `struct info` per node and a pointer to a shared "idx" reference counter. Signed-off-by: Rusty Russell <[email protected]>
1 parent bda52c3 commit 4eafc1a

File tree

1 file changed

+49
-14
lines changed

1 file changed

+49
-14
lines changed

plugins/chanbackup.c

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,22 @@ HTABLE_DEFINE_NODUPS_TYPE(struct peer_backup,
5151
peer_backup_eq_node_id,
5252
backup_map);
5353

54+
HTABLE_DEFINE_NODUPS_TYPE(struct node_id,
55+
node_id_keyof,
56+
node_id_hash,
57+
node_id_eq,
58+
peer_map);
59+
5460
struct chanbackup {
5561
bool peer_backup;
5662
/* Global secret object to keep the derived encryption key for the SCB */
5763
struct secret secret;
5864

5965
/* Cache of backups for each peer we know about */
6066
struct backup_map *backups;
67+
68+
/* Cache of known peers which support backups (for sending) */
69+
struct peer_map *peers;
6170
};
6271

6372
static struct chanbackup *chanbackup(struct plugin *plugin)
@@ -77,6 +86,19 @@ static struct peer_backup *add_to_backup_map(struct chanbackup *cb,
7786
return pb;
7887
}
7988

89+
static void remove_peer(struct plugin *plugin, const struct node_id *node_id)
90+
{
91+
struct chanbackup *cb = chanbackup(plugin);
92+
struct node_id *peer;
93+
94+
/* Eliminate it (probably it's disconnected) */
95+
peer = peer_map_get(cb->peers, node_id);
96+
if (peer) {
97+
peer_map_del(cb->peers, peer);
98+
tal_free(peer);
99+
}
100+
}
101+
80102
/* Helper to fetch out SCB from the RPC call */
81103
static bool json_to_scb_chan(const char *buffer,
82104
const jsmntok_t *tok,
@@ -406,7 +428,7 @@ static struct command_result
406428
const char *method,
407429
const char *buf,
408430
const jsmntok_t *params,
409-
void *cb_arg UNUSED)
431+
struct node_id *node_id)
410432
{
411433
plugin_log(cmd->plugin, LOG_DBG, "Sent their peer storage!");
412434
return command_hook_success(cmd);
@@ -417,9 +439,10 @@ static struct command_result
417439
const char *method,
418440
const char *buf,
419441
const jsmntok_t *params,
420-
void *cb_arg UNUSED)
442+
struct node_id *node_id)
421443
{
422444
plugin_log(cmd->plugin, LOG_DBG, "Unable to send Peer storage!");
445+
remove_peer(cmd->plugin, node_id);
423446
return command_hook_success(cmd);
424447
}
425448

@@ -450,7 +473,7 @@ static struct command_result *peer_after_send_scb(struct command *cmd,
450473
"sendcustommsg",
451474
peer_after_send_their_peer_strg,
452475
peer_after_send_their_peer_strg_err,
453-
NULL);
476+
nodeid);
454477

455478
json_add_node_id(req->js, "node_id", nodeid);
456479
json_add_hex_talarr(req->js, "msg", msg);
@@ -466,11 +489,13 @@ static struct command_result *peer_after_send_scb_failed(struct command *cmd,
466489
{
467490
plugin_log(cmd->plugin, LOG_DBG, "Peer storage send failed %.*s!",
468491
json_tok_full_len(params), json_tok_full(buf, params));
492+
remove_peer(cmd->plugin, nodeid);
469493
return command_hook_success(cmd);
470494
}
471495

472496
struct info {
473-
size_t idx;
497+
size_t *idx;
498+
struct node_id node_id;
474499
};
475500

476501
/* We refresh scb from both channel_state_changed notification and
@@ -491,7 +516,7 @@ static struct command_result *after_send_scb_single(struct command *cmd,
491516
struct info *info)
492517
{
493518
plugin_log(cmd->plugin, LOG_TRACE, "Peer storage sent!");
494-
if (--info->idx != 0)
519+
if (--(*info->idx) != 0)
495520
return command_still_pending(cmd);
496521

497522
return notification_or_hook_done(cmd);
@@ -504,7 +529,8 @@ static struct command_result *after_send_scb_single_fail(struct command *cmd,
504529
struct info *info)
505530
{
506531
plugin_log(cmd->plugin, LOG_DBG, "Peer storage send failed!");
507-
if (--info->idx != 0)
532+
remove_peer(cmd->plugin, &info->node_id);
533+
if (--(*info->idx) != 0)
508534
return command_still_pending(cmd);
509535

510536
return notification_or_hook_done(cmd);
@@ -519,7 +545,7 @@ static struct command_result *after_listpeers(struct command *cmd,
519545
const jsmntok_t *peers, *peer;
520546
struct out_req *req;
521547
size_t i;
522-
struct info *info = tal(cmd, struct info);
548+
size_t *idx = tal(cmd, size_t);
523549
bool is_connected;
524550
u8 *serialise_scb;
525551

@@ -540,7 +566,7 @@ static struct command_result *after_listpeers(struct command *cmd,
540566

541567
peers = json_get_member(buf, params, "peers");
542568

543-
info->idx = 0;
569+
*idx = 0;
544570
json_for_each_arr(i, peer, peers) {
545571
const char *err;
546572
u8 *features;
@@ -557,25 +583,26 @@ static struct command_result *after_listpeers(struct command *cmd,
557583
/* We shouldn't have to check, but LND hangs up? */
558584
if (feature_offered(features, OPT_PROVIDE_STORAGE)) {
559585
const jsmntok_t *nodeid;
560-
struct node_id node_id;
586+
struct info *info = tal(cmd, struct info);
561587

588+
info->idx = idx;
562589
nodeid = json_get_member(buf, peer, "id");
563-
json_to_node_id(buf, nodeid, &node_id);
590+
json_to_node_id(buf, nodeid, &info->node_id);
564591

565592
req = jsonrpc_request_start(cmd,
566593
"sendcustommsg",
567594
after_send_scb_single,
568595
after_send_scb_single_fail,
569596
info);
570597

571-
json_add_node_id(req->js, "node_id", &node_id);
598+
json_add_node_id(req->js, "node_id", &info->node_id);
572599
json_add_hex_talarr(req->js, "msg", serialise_scb);
573-
info->idx++;
600+
(*info->idx)++;
574601
send_outreq(req);
575602
}
576603
}
577604

578-
if (info->idx == 0)
605+
if (*idx == 0)
579606
return notification_or_hook_done(cmd);
580607
return command_still_pending(cmd);
581608
}
@@ -674,8 +701,9 @@ static struct command_result *peer_connected(struct command *cmd,
674701
u8 *serialise_scb;
675702
const char *err;
676703
u8 *features;
704+
struct chanbackup *cb = chanbackup(cmd->plugin);
677705

678-
if (!chanbackup(cmd->plugin)->peer_backup)
706+
if (!cb->peer_backup)
679707
return command_hook_success(cmd);
680708

681709
serialise_scb = towire_peer_storage(cmd,
@@ -697,6 +725,10 @@ static struct command_result *peer_connected(struct command *cmd,
697725
return command_hook_success(cmd);
698726
}
699727

728+
/* Remember this peer for future sends */
729+
if (!peer_map_get(cb->peers, node_id))
730+
peer_map_add(cb->peers, tal_dup(cb->peers, struct node_id, node_id));
731+
700732
req = jsonrpc_request_start(cmd,
701733
"sendcustommsg",
702734
peer_after_send_scb,
@@ -978,6 +1010,8 @@ static void setup_backup_map(struct command *init_cmd,
9781010

9791011
cb->backups = tal(cb, struct backup_map);
9801012
backup_map_init(cb->backups);
1013+
cb->peers = tal(cb, struct peer_map);
1014+
peer_map_init(cb->peers);
9811015

9821016
json_out_start(params, NULL, '{');
9831017
json_out_start(params, "key", '[');
@@ -1023,6 +1057,7 @@ static void chanbackup_mark_mem(struct plugin *plugin,
10231057
{
10241058
const struct chanbackup *cb = chanbackup(plugin);
10251059
memleak_scan_htable(memtable, &cb->backups->raw);
1060+
memleak_scan_htable(memtable, &cb->peers->raw);
10261061
}
10271062

10281063
static const char *init(struct command *init_cmd,

0 commit comments

Comments
 (0)