diff --git a/lightningd/runes.c b/lightningd/runes.c index 7150f8d43..dc40acf76 100644 --- a/lightningd/runes.c +++ b/lightningd/runes.c @@ -39,18 +39,9 @@ static bool usage_eq_id(const struct usage *u, u64 id) return u->id == id; } HTABLE_DEFINE_TYPE(struct usage, usage_id, id_hash, usage_eq_id, usage_table); -static struct usage_table *usage_table; - -/* Every minute we forget entries. */ -static void flush_usage_table(struct lightningd *ld) -{ - tal_free(usage_table); - usage_table = notleak(tal(ld, struct usage_table)); - usage_table_init(usage_table); - notleak(new_reltimer(ld->timers, ld, time_from_sec(60), flush_usage_table, ld)); -} struct cond_info { + const struct runes *runes; const struct node_id *peer; const char *buf; const char *method; @@ -61,12 +52,34 @@ struct cond_info { /* This is lightningd->runes */ struct runes { + struct lightningd *ld; struct rune *master; u64 next_unique_id; struct rune_blacklist *blacklist; + struct usage_table *usage_table; }; +#if DEVELOPER +static void memleak_help_usage_table(struct htable *memtable, + struct usage_table *usage_table) +{ + memleak_scan_htable(memtable, &usage_table->raw); +} +#endif /* DEVELOPER */ + +/* Every minute we forget entries. */ +static void flush_usage_table(struct runes *runes) +{ + tal_free(runes->usage_table); + runes->usage_table = tal(runes, struct usage_table); + usage_table_init(runes->usage_table); + memleak_add_helper(runes->usage_table, memleak_help_usage_table); + + notleak(new_reltimer(runes->ld->timers, runes, time_from_sec(60), flush_usage_table, runes)); +} + static const char *rate_limit_check(const tal_t *ctx, + const struct runes *runes, const struct rune *rune, const struct rune_altern *alt, struct cond_info *cinfo) @@ -82,12 +95,12 @@ static const char *rate_limit_check(const tal_t *ctx, /* We cache this: we only add usage counter if whole rune succeeds! */ if (!cinfo->usage) { - cinfo->usage = usage_table_get(usage_table, atol(rune->unique_id)); + cinfo->usage = usage_table_get(runes->usage_table, atol(rune->unique_id)); if (!cinfo->usage) { - cinfo->usage = notleak(tal(usage_table, struct usage)); + cinfo->usage = tal(runes->usage_table, struct usage); cinfo->usage->id = atol(rune->unique_id); cinfo->usage->counter = 0; - usage_table_add(usage_table, cinfo->usage); + usage_table_add(runes->usage_table, cinfo->usage); } } @@ -105,6 +118,7 @@ struct runes *runes_init(struct lightningd *ld) 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); @@ -117,7 +131,8 @@ struct runes *runes_init(struct lightningd *ld) runes->master = rune_new(runes, secret.data, ARRAY_SIZE(secret.data), NULL); /* Initialize usage table and start flush timer. */ - flush_usage_table(ld); + runes->usage_table = NULL; + flush_usage_table(runes); return runes; } @@ -639,7 +654,7 @@ static const char *check_condition(const tal_t *ctx, } else if (streq(alt->fieldname, "pnum")) { return rune_alt_single_int(ctx, alt, (cinfo && cinfo->params) ? cinfo->params->size : 0); } else if (streq(alt->fieldname, "rate")) { - return rate_limit_check(ctx, rune, alt, cinfo); + return rate_limit_check(ctx, cinfo->runes, rune, alt, cinfo); } /* Rest are params looksup: generate this once! */ @@ -714,6 +729,7 @@ static struct command_result *json_checkrune(struct command *cmd, if (is_rune_blacklisted(cmd->ld->runes, ras->rune)) return command_fail(cmd, RUNE_BLACKLISTED, "Not authorized: Blacklisted rune"); + cinfo.runes = cmd->ld->runes; cinfo.peer = nodeid; cinfo.buf = buffer; cinfo.method = method;