lightningd/common: Added --recover flag to populate HSM_secret with appropriate secret through a valid codex32 secret.

This commit is contained in:
adi2011 2023-07-31 09:03:33 +09:30 committed by Rusty Russell
parent 3b848d84d1
commit 581677691d
2 changed files with 80 additions and 0 deletions

View file

@ -84,6 +84,7 @@ LIGHTNINGD_COMMON_OBJS := \
common/bolt11_json.o \
common/bolt12.o \
common/bolt12_merkle.o \
common/codex32.o \
common/channel_config.o \
common/channel_id.o \
common/channel_type.o \

View file

@ -4,11 +4,15 @@
#include <ccan/err/err.h>
#include <ccan/json_escape/json_escape.h>
#include <ccan/mem/mem.h>
#include <ccan/noerr/noerr.h>
#include <ccan/opt/opt.h>
#include <ccan/opt/private.h>
#include <ccan/read_write_all/read_write_all.h>
#include <ccan/str/hex/hex.h>
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/tal/path/path.h>
#include <ccan/tal/str/str.h>
#include <common/codex32.h>
#include <common/configdir.h>
#include <common/configvar.h>
#include <common/features.h>
@ -20,6 +24,7 @@
#include <common/wireaddr.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <hsmd/hsmd_wiregen.h>
#include <lightningd/chaintopology.h>
#include <lightningd/hsm_control.h>
@ -1253,6 +1258,74 @@ static char *opt_set_announce_dns(const char *optarg, struct lightningd *ld)
return opt_set_bool_arg(optarg, &ld->announce_dns);
}
static char *opt_set_codex32(const char *arg, struct lightningd *ld)
{
const uint8_t *payload;
char *err;
struct codex32 *parts = codex32_decode(tmpctx, arg, &err);
if (!parts) {
return err;
}
if (parts->type != CODEX32_ENCODING_SECRET) {
return tal_fmt(tmpctx, "Not a valid codex32 secret!");
}
payload = codex32_decode_payload(tmpctx, parts);
if (tal_bytelen(payload) != 32) {
return tal_fmt(tmpctx, "Expected 32 Byte secret: %s",
tal_hexstr(tmpctx,
payload,
tal_bytelen(payload)));
}
/* Checks if hsm_secret exists */
int fd = open("hsm_secret", O_CREAT|O_EXCL|O_WRONLY, 0400);
if (fd < 0) {
/* Don't do anything if the file already exists. */
if (errno == EEXIST)
return tal_fmt(tmpctx, "hsm_secret already exists!");
return tal_fmt(tmpctx, "Creating hsm_secret: %s",
strerror(errno));
}
if (!write_all(fd, payload, tal_count(payload))) {
unlink_noerr("hsm_secret");
return tal_fmt(tmpctx, "Writing HSM: %s",
strerror(errno));
}
/*~ fsync (mostly!) ensures that the file has reached the disk. */
if (fsync(fd) != 0) {
unlink_noerr("hsm_secret");
return tal_fmt(tmpctx, "fsync: %s", strerror(errno));
}
/*~ This should never fail if fsync succeeded. But paranoia good, and
* bugs exist. */
if (close(fd) != 0) {
unlink_noerr("hsm_secret");
return tal_fmt(tmpctx, "closing: %s", strerror(errno));
}
/*~ We actually need to sync the *directory itself* to make sure the
* file exists! You're only allowed to open directories read-only in
* modern Unix though. */
fd = open(".", O_RDONLY);
if (fd < 0) {
unlink_noerr("hsm_secret");
return tal_fmt(tmpctx, "opening: %s", strerror(errno));
}
if (fsync(fd) != 0) {
unlink_noerr("hsm_secret");
return tal_fmt(tmpctx, "fsyncdir: %s", strerror(errno));
}
close(fd);
return NULL;
}
static void register_opts(struct lightningd *ld)
{
/* This happens before plugins started */
@ -1300,6 +1373,11 @@ static void register_opts(struct lightningd *ld)
&ld->wallet_dsn,
"Location of the wallet database.");
opt_register_early_arg("--recover", opt_set_codex32, NULL,
ld,
"Populate hsm_secret with the given codex32 secret"
" and starts the node in `offline` mode.");
/* This affects our features, so set early. */
opt_register_early_noarg("--large-channels|--wumbo",
opt_set_wumbo, ld,
@ -1964,6 +2042,7 @@ bool is_known_opt_cb_arg(char *(*cb_arg)(const char *, void *))
|| cb_arg == (void *)opt_set_db_upgrade
|| cb_arg == (void *)arg_log_to_file
|| cb_arg == (void *)opt_add_accept_htlc_tlv
|| cb_arg == (void *)opt_set_codex32
#if DEVELOPER
|| cb_arg == (void *)opt_subd_dev_disconnect
|| cb_arg == (void *)opt_force_featureset