diff --git a/doc/lightning-listconfigs.7.md b/doc/lightning-listconfigs.7.md index 3232d88a0fb9..fe99657469a3 100644 --- a/doc/lightning-listconfigs.7.md +++ b/doc/lightning-listconfigs.7.md @@ -62,6 +62,7 @@ On success, an object is returned, containing: - **experimental-offers** (boolean, optional): `experimental-offers` field from config or cmdline, or default - **experimental-shutdown-wrong-funding** (boolean, optional): `experimental-shutdown-wrong-funding` field from config or cmdline, or default - **experimental-websocket-port** (u16, optional): `experimental-websocket-port` field from config or cmdline, or default +- **experimental-peer-storage** (boolean, optional): `experimental-peer-storage` field from config or cmdline, or default *(added v23.02)* - **database-upgrade** (boolean, optional): `database-upgrade` field from config or cmdline - **rgb** (hex, optional): `rgb` field from config or cmdline, or default (always 6 characters) - **alias** (string, optional): `alias` field from config or cmdline, or default @@ -223,4 +224,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:581225b26efd84bfa99dc98e7a91e6fae11ef0b11939031d3da07f751f6d8f87) +[comment]: # ( SHA256STAMP:1088401b9aeae1e079dab550d3b035ef82195f0466ad471bc7373386182f37dc) diff --git a/doc/lightningd-config.5.md b/doc/lightningd-config.5.md index f5037669ef2a..0621ccb72e91 100644 --- a/doc/lightningd-config.5.md +++ b/doc/lightningd-config.5.md @@ -714,6 +714,12 @@ connections on that port, on any IPv4 and IPv6 addresses you listen to ([bolt][bolt] #891). The normal protocol is expected to be sent over WebSocket binary frames once the connection is upgraded. +* **experimental-peer-storage** + + Specifying this option means we will store up to 64k of encrypted +data for our peers, and give them our (encrypted!) backup data to +store as well, based on a protocol similar to [bolt][bolt] #881. + BUGS ---- diff --git a/doc/schemas/listconfigs.schema.json b/doc/schemas/listconfigs.schema.json index 8149e40c1627..b2ebdd003c68 100644 --- a/doc/schemas/listconfigs.schema.json +++ b/doc/schemas/listconfigs.schema.json @@ -137,6 +137,11 @@ "type": "u16", "description": "`experimental-websocket-port` field from config or cmdline, or default" }, + "experimental-peer-storage": { + "type": "boolean", + "added": "v23.02", + "description": "`experimental-peer-storage` field from config or cmdline, or default" + }, "database-upgrade": { "type": "boolean", "description": "`database-upgrade` field from config or cmdline" diff --git a/lightningd/options.c b/lightningd/options.c index 380de41464bd..475c0d387cc5 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -1078,6 +1078,15 @@ static char *opt_set_shutdown_wrong_funding(struct lightningd *ld) return NULL; } +static char *opt_set_peer_storage(struct lightningd *ld) +{ + feature_set_or(ld->our_features, + take(feature_set_for_feature(NULL, OPT_PROVIDE_PEER_BACKUP_STORAGE))); + feature_set_or(ld->our_features, + take(feature_set_for_feature(NULL, OPT_WANT_PEER_BACKUP_STORAGE))); + return NULL; +} + static char *opt_set_offers(struct lightningd *ld) { ld->config.exp_offers = true; @@ -1156,6 +1165,9 @@ static void register_opts(struct lightningd *ld) opt_register_early_noarg("--experimental-shutdown-wrong-funding", opt_set_shutdown_wrong_funding, ld, "EXPERIMENTAL: allow shutdown with alternate txids"); + opt_register_early_noarg("--experimental-peer-storage", + opt_set_peer_storage, ld, + "EXPERIMENTAL: enable peer backup storage and restore"); opt_register_early_arg("--announce-addr-dns", opt_set_bool_arg, opt_show_bool, &ld->announce_dns, @@ -1641,6 +1653,11 @@ static void add_config(struct lightningd *ld, feature_offered(ld->our_features ->bits[INIT_FEATURE], OPT_SHUTDOWN_WRONG_FUNDING)); + } else if (opt->cb == (void *)opt_set_peer_storage) { + json_add_bool(response, name0, + feature_offered(ld->our_features + ->bits[INIT_FEATURE], + OPT_PROVIDE_PEER_BACKUP_STORAGE)); } else if (opt->cb == (void *)plugin_opt_flag_set) { /* Noop, they will get added below along with the * OPT_HASARG options. */ diff --git a/plugins/chanbackup.c b/plugins/chanbackup.c index 8f8ea93ea3eb..bf906b7edc76 100644 --- a/plugins/chanbackup.c +++ b/plugins/chanbackup.c @@ -30,6 +30,7 @@ /* Global secret object to keep the derived encryption key for the SCB */ static struct secret secret; +static bool peer_backup; /* Helper to fetch out SCB from the RPC call */ static bool json_to_scb_chan(const char *buffer, @@ -530,6 +531,9 @@ static struct command_result *peer_connected(struct command *cmd, u8 *serialise_scb; const char *err; + if (!peer_backup) + return command_hook_success(cmd); + serialise_scb = towire_peer_storage(cmd, get_file_data(tmpctx, cmd->plugin)); node_id = tal(cmd, struct node_id); @@ -592,13 +596,15 @@ static struct command_result *handle_your_peer_storage(struct command *cmd, { struct node_id node_id; u8 *payload, *payload_deserialise; - const char *err = json_scan(cmd, buf, params, - "{payload:%,peer_id:%}", - JSON_SCAN_TAL(cmd, - json_tok_bin_from_hex, - &payload), - JSON_SCAN(json_to_node_id, - &node_id)); + const char *err; + + if (!peer_backup) + return command_hook_success(cmd); + + err = json_scan(cmd, buf, params, + "{payload:%,peer_id:%}", + JSON_SCAN_TAL(cmd, json_tok_bin_from_hex, &payload), + JSON_SCAN(json_to_node_id, &node_id)); if (err) { plugin_err(cmd->plugin, "`your_peer_storage` response did not scan %s: %.*s", @@ -737,6 +743,14 @@ static const char *init(struct plugin *p, struct scb_chan **scb_chan; const char *info = "scb secret"; u8 *info_hex = tal_dup_arr(tmpctx, u8, (u8*)info, strlen(info), 0); + u8 *features; + + /* Figure out if they specified --experimental-peer-storage */ + rpc_scan(p, "getinfo", + take(json_out_obj(NULL, NULL, NULL)), + "{our_features:{init:%}}", + JSON_SCAN_TAL(tmpctx, json_tok_bin_from_hex, &features)); + peer_backup = feature_offered(features, OPT_WANT_PEER_BACKUP_STORAGE); rpc_scan(p, "staticbackup", take(json_out_obj(NULL, NULL, NULL)), @@ -799,12 +813,8 @@ static const struct plugin_command commands[] = { int main(int argc, char *argv[]) { setup_locale(); - struct feature_set *features = feature_set_for_feature(NULL, OPT_WANT_PEER_BACKUP_STORAGE); - feature_set_or(features, - take(feature_set_for_feature(NULL, - OPT_PROVIDE_PEER_BACKUP_STORAGE))); - plugin_main(argv, init, PLUGIN_STATIC, true, features, + plugin_main(argv, init, PLUGIN_STATIC, true, NULL, commands, ARRAY_SIZE(commands), notifs, ARRAY_SIZE(notifs), hooks, ARRAY_SIZE(hooks), NULL, 0, /* Notification topics we publish */ diff --git a/tests/test_misc.py b/tests/test_misc.py index 1c826fe832e2..d144c66a89aa 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -2510,8 +2510,11 @@ def test_restorefrompeer(node_factory, bitcoind): """ Test restorefrompeer """ - l1, l2 = node_factory.get_nodes(2, opts=[{'allow_broken_log': True, 'may_reconnect': True}, - {'may_reconnect': True}]) + l1, l2 = node_factory.get_nodes(2, [{'allow_broken_log': True, + 'experimental-peer-storage': None, + 'may_reconnect': True}, + {'experimental-peer-storage': None, + 'may_reconnect': True}]) l1.rpc.connect(l2.info['id'], 'localhost', l2.port)