lightningd: initialize runes way earlier, and add rune_is_ours helper.

We want to access this in db migrations, which happen very early, but
runes_init needs the db, creating a circular dependency which must be
split.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2023-07-25 11:19:43 +09:30
parent a219c99691
commit c4c4768577
4 changed files with 47 additions and 17 deletions

View File

@@ -1059,6 +1059,13 @@ int main(int argc, char *argv[])
* Daemon Software Module. */
ld->bip32_base = hsm_init(ld);
/*~ We have bearer tokens called `runes` you can use to control access. They have
* a fascinating history which I shall not go into now, but they're derived from
* Macaroons which was a over-engineered Googlism.
*
* We need them minimally bootstrapped for our db migration code. */
ld->runes = runes_early_init(ld);
/*~ Our "wallet" code really wraps the db, which is more than a simple
* bitcoin wallet (though it's that too). It also stores channel
* states, invoices, payments, blocks and bitcoin transactions. */
@@ -1120,10 +1127,8 @@ int main(int argc, char *argv[])
else if (max_blockheight != UINT32_MAX)
max_blockheight -= ld->config.rescan;
/*~ We have bearer tokens called `runes` you can use to control access. They have
* a fascinating history which I shall not go into now, but they're derived from
* Macaroons which was a over-engineered Googlism. */
ld->runes = runes_init(ld);
/*~ Finish our runes initialization (includes reading from db) */
runes_finish_init(ld->runes);
/*~ That's all of the wallet db operations for now. */
db_commit_transaction(ld->wallet->db);

View File

@@ -59,6 +59,11 @@ struct runes {
struct usage_table *usage_table;
};
const char *rune_is_ours(struct lightningd *ld, const struct rune *rune)
{
return rune_is_derived(ld->runes->master, rune);
}
#if DEVELOPER
static void memleak_help_usage_table(struct htable *memtable,
struct usage_table *usage_table)
@@ -111,30 +116,36 @@ static const char *rate_limit_check(const tal_t *ctx,
return NULL;
}
struct runes *runes_init(struct lightningd *ld)
/* We need to initialize master runes secret early, so db can use rune_is_ours */
struct runes *runes_early_init(struct lightningd *ld)
{
const u8 *msg;
struct runes *runes = tal(ld, struct runes);
const u8 *data;
struct secret secret;
runes->ld = ld;
runes->next_unique_id = db_get_intvar(ld->wallet->db, "runes_uniqueid", 0);
runes->blacklist = wallet_get_runes_blacklist(runes, ld->wallet);
/* Runes came out of commando, hence the derivation key is 'commando' */
data = tal_dup_arr(tmpctx, u8, (u8 *)"commando", strlen("commando"), 0);
msg = hsm_sync_req(tmpctx, ld, towire_hsmd_derive_secret(tmpctx, data));
if (!fromwire_hsmd_derive_secret_reply(msg, &secret))
fatal("Bad reply from HSM: %s", tal_hex(tmpctx, msg));
runes->ld = ld;
runes->master = rune_new(runes, secret.data, ARRAY_SIZE(secret.data), NULL);
return runes;
}
void runes_finish_init(struct runes *runes)
{
struct lightningd *ld = runes->ld;
runes->next_unique_id = db_get_intvar(ld->wallet->db, "runes_uniqueid", 0);
runes->blacklist = wallet_get_runes_blacklist(runes, ld->wallet);
/* Initialize usage table and start flush timer. */
runes->usage_table = NULL;
flush_usage_table(runes);
return runes;
}
struct rune_and_string {
@@ -281,7 +292,7 @@ static struct command_result *json_add_rune(struct lightningd *ld,
if (is_rune_blacklisted(ld->runes, rune)) {
json_add_bool(js, "blacklisted", true);
}
if (rune_is_derived(ld->runes->master, rune)) {
if (rune_is_ours(ld, rune) != NULL) {
json_add_bool(js, "our_rune", false);
}
json_add_string(js, "unique_id", rune->unique_id);
@@ -757,7 +768,7 @@ static struct command_result *json_checkrune(struct command *cmd,
cinfo.usage = NULL;
strmap_init(&cinfo.cached_params);
err = rune_is_derived(cmd->ld->runes->master, ras->rune);
err = rune_is_ours(cmd->ld, ras->rune);
if (err) {
return command_fail(cmd, RUNE_NOT_AUTHORIZED, "Not authorized: %s", err);
}

View File

@@ -2,6 +2,17 @@
#define LIGHTNING_LIGHTNINGD_RUNES_H
#include "config.h"
struct runes *runes_init(struct lightningd *ld);
struct rune;
/* Initialize ld->runes enough for rune_is_ours(): needs HSM. */
struct runes *runes_early_init(struct lightningd *ld);
/* Finish it: needs db. */
void runes_finish_init(struct runes *runes);
/* Is this rune one of ours? Needed for commando migration.
* Returns NULL if it is, or a string explaining (usually, "Not derived from master").
*/
const char *rune_is_ours(struct lightningd *ld, const struct rune *rune);
#endif /* LIGHTNING_LIGHTNINGD_RUNES_H */

View File

@@ -187,9 +187,12 @@ void plugins_set_builtin_plugins_dir(struct plugins *plugins UNNEEDED,
/* Generated stub for resend_closing_transactions */
void resend_closing_transactions(struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "resend_closing_transactions called!\n"); abort(); }
/* Generated stub for runes_init */
struct runes *runes_init(struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "runes_init called!\n"); abort(); }
/* Generated stub for runes_early_init */
struct runes *runes_early_init(struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "runes_early_init called!\n"); abort(); }
/* Generated stub for runes_finish_init */
void runes_finish_init(struct runes *runes UNNEEDED)
{ fprintf(stderr, "runes_finish_init called!\n"); abort(); }
/* Generated stub for setup_color_and_alias */
void setup_color_and_alias(struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "setup_color_and_alias called!\n"); abort(); }