From 0fddb06915a0bfcec6e0a0ed706cd01a5235e49b Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 29 Oct 2022 04:09:40 +1030 Subject: [PATCH] plugins/sql: add bkpr-listaccountevents and bkpr-listincome support. This *would* be a 1-line change (add it to Makefile) except that we previously assumed a "list" prefix on commands. These use the default refreshing, but they could be done better using the time-range parameters. Suggested-by: @niftynei Signed-off-by: Rusty Russell --- doc/lightning-sql.7.md | 32 +++++++++++++++++++++++- plugins/Makefile | 2 +- plugins/sql.c | 40 ++++++++++++++++++++++++------ tests/test_plugin.py | 56 +++++++++++++++++++++++++++++++++++++++++- tools/flattenschema.py | 4 +-- 5 files changed, 121 insertions(+), 13 deletions(-) diff --git a/doc/lightning-sql.7.md b/doc/lightning-sql.7.md index f2108960fcb4..cb504aa772fa 100644 --- a/doc/lightning-sql.7.md +++ b/doc/lightning-sql.7.md @@ -61,6 +61,36 @@ Note that most column names reflect the JSON field names, with the exception of Sub-arrays are represented in their own tables, and sub-objects are flattened with `_`. The following tables are currently supported: +- bkpr_accountevents (see lightning-bkpr-listaccountevents(7)) + - `account` (type `string`, sqltype `TEXT`) + - `type` (type `string`, sqltype `TEXT`) + - `tag` (type `string`, sqltype `TEXT`) + - `credit_msat` (type `msat`, sqltype `INTEGER`) + - `debit_msat` (type `msat`, sqltype `INTEGER`) + - `currency` (type `string`, sqltype `TEXT`) + - `timestamp` (type `u32`, sqltype `INTEGER`) + - `outpoint` (type `string`, sqltype `TEXT`) + - `blockheight` (type `u32`, sqltype `INTEGER`) + - `origin` (type `string`, sqltype `TEXT`) + - `payment_id` (type `hex`, sqltype `BLOB`) + - `txid` (type `txid`, sqltype `BLOB`) + - `description` (type `string`, sqltype `TEXT`) + - `fees_msat` (type `msat`, sqltype `INTEGER`) + - `is_rebalance` (type `boolean`, sqltype `INTEGER`) + - `part_id` (type `u32`, sqltype `INTEGER`) + +- bkpr_income (see lightning-bkpr-listincome(7)) + - `account` (type `string`, sqltype `TEXT`) + - `tag` (type `string`, sqltype `TEXT`) + - `credit_msat` (type `msat`, sqltype `INTEGER`) + - `debit_msat` (type `msat`, sqltype `INTEGER`) + - `currency` (type `string`, sqltype `TEXT`) + - `timestamp` (type `u32`, sqltype `INTEGER`) + - `description` (type `string`, sqltype `TEXT`) + - `outpoint` (type `string`, sqltype `TEXT`) + - `txid` (type `txid`, sqltype `BLOB`) + - `payment_id` (type `hex`, sqltype `BLOB`) + - channels indexed by `short_channel_id` (see lightning-listchannels(7)) - `source` (type `pubkey`, sqltype `BLOB`) - `destination` (type `pubkey`, sqltype `BLOB`) @@ -270,4 +300,4 @@ RESOURCES --------- Main web site: -[comment]: # ( SHA256STAMP:03aee4b1270fce52618a6261f79308927e18df1f490df0da3972840d7f9df1cf) +[comment]: # ( SHA256STAMP:86fec37b6a343e04c2d8f482692aab62e2ba0f3d1196ddd052e06f13952fa6d2) diff --git a/plugins/Makefile b/plugins/Makefile index 684fa98256a0..a87fa167237d 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -204,7 +204,7 @@ plugins/fetchinvoice: $(PLUGIN_FETCHINVOICE_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_CO plugins/funder: bitcoin/psbt.o common/psbt_open.o $(PLUGIN_FUNDER_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) # This covers all the low-level list RPCs which return simple arrays of matching name (FIXME: NOT listsendpays!) -SQL_LISTRPCS := listchannels listforwards listhtlcs listinvoices listnodes listoffers listpeers listtransactions listsendpays +SQL_LISTRPCS := listchannels listforwards listhtlcs listinvoices listnodes listoffers listpeers listtransactions listsendpays bkpr-listaccountevents bkpr-listincome SQL_LISTRPCS_SCHEMAS := $(foreach l,$(SQL_LISTRPCS),doc/schemas/$l.schema.json) plugins/sql-flatschema_gen.h: plugins/Makefile tools/flattenschema.py $(SQL_LISTRPCS_SCHEMAS) @$(call VERBOSE,GEN $@, tools/flattenschema.py $(SQL_LISTRPCS_SCHEMAS) | sed 's/\(.*\)/"\1\\n"/' > $@) diff --git a/plugins/sql.c b/plugins/sql.c index 9aa2aa81d1da..4467cbbf22a7 100644 --- a/plugins/sql.c +++ b/plugins/sql.c @@ -149,6 +149,8 @@ struct column { }; struct table_desc { + /* e.g. listpeers */ + const char *cmdname; /* e.g. peers for listpeers */ const char *name; /* e.g. "payments" for listsendpays */ @@ -618,8 +620,7 @@ static struct command_result *default_refresh(struct command *cmd, struct db_query *dbq) { struct out_req *req; - req = jsonrpc_request_start(cmd->plugin, cmd, - tal_fmt(tmpctx, "list%s", td->name), + req = jsonrpc_request_start(cmd->plugin, cmd, td->cmdname, default_list_done, forward_error, dbq); return send_outreq(cmd->plugin, req); @@ -1096,11 +1097,32 @@ static const char *db_column_name(const tal_t *ctx, const char *name) return tal_strdup(ctx, name); } +/* Remove 'list', turn - into _ in name */ +static const char *db_table_name(const tal_t *ctx, const char *cmdname) +{ + const char *list = strstr(cmdname, "list"); + char *ret = tal_arr(ctx, char, strlen(cmdname) + 1), *dst = ret; + const char *src = cmdname; + + while (*src) { + if (src == list) + src += strlen("list"); + else if (cisalnum(*src)) + *(dst++) = *(src++); + else { + (*dst++) = '_'; + src++; + } + } + *dst = '\0'; + return ret; +} + static const char *start_new_table_desc(const tal_t *ctx, struct table_desc **tdp, struct table_desc *parent, bool is_subobject, - const char *name TAKES, + const char *cmdname TAKES, const char *arrname TAKES, struct command_result * (*refresh)(struct command *, @@ -1114,7 +1136,8 @@ static const char *start_new_table_desc(const tal_t *ctx, return err; *tdp = tal(NULL, struct table_desc); - (*tdp)->name = tal_strdup(*tdp, name); + (*tdp)->cmdname = tal_strdup(*tdp, cmdname); + (*tdp)->name = db_table_name(*tdp, cmdname); (*tdp)->parent = parent; (*tdp)->is_subobject = is_subobject; (*tdp)->arrname = tal_strdup(*tdp, arrname); @@ -1147,9 +1170,10 @@ static const char *init_tablemap(const tal_t *ctx) if (!streq(sub[2], "array")) continue; + /* FIXME: add specialized refreshers for bkpraccountevents and bkprincome */ err = start_new_table_desc(ctx, &td, NULL, false, sub[0], sub[1], - streq(sub[0], "channels") ? channels_refresh - : streq(sub[0], "nodes") ? nodes_refresh + streq(sub[0], "listchannels") ? channels_refresh + : streq(sub[0], "listnodes") ? nodes_refresh : default_refresh); if (err) return err; @@ -1317,8 +1341,8 @@ static bool print_one_table(const char *member, if (td->parent) return true; - printf("- %s%s (see lightning-list%s(7))\n", - member, fmt_indexes(tmpctx, member), member); + printf("- %s%s (see lightning-%s(7))\n", + member, fmt_indexes(tmpctx, member), td->cmdname); for (size_t i = 0; i < tal_count(td->columns); i++) { const char *origin; diff --git a/tests/test_plugin.py b/tests/test_plugin.py index ee05512d3280..d2d30c0e0346 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -3506,7 +3506,61 @@ def test_sql(node_factory, bitcoind): {'name': 'type', 'type': 'string'}, {'name': 'channel', - 'type': 'short_channel_id'}]}} + 'type': 'short_channel_id'}]}, + 'bkpr_accountevents': { + 'columns': [{'name': 'account', + 'type': 'string'}, + {'name': 'type', + 'type': 'string'}, + {'name': 'tag', + 'type': 'string'}, + {'name': 'credit_msat', + 'type': 'msat'}, + {'name': 'debit_msat', + 'type': 'msat'}, + {'name': 'currency', + 'type': 'string'}, + {'name': 'timestamp', + 'type': 'u32'}, + {'name': 'outpoint', + 'type': 'string'}, + {'name': 'blockheight', + 'type': 'u32'}, + {'name': 'origin', + 'type': 'string'}, + {'name': 'payment_id', + 'type': 'hex'}, + {'name': 'txid', + 'type': 'txid'}, + {'name': 'description', + 'type': 'string'}, + {'name': 'fees_msat', + 'type': 'msat'}, + {'name': 'is_rebalance', + 'type': 'boolean'}, + {'name': 'part_id', + 'type': 'u32'}]}, + 'bkpr_income': { + 'columns': [{'name': 'account', + 'type': 'string'}, + {'name': 'tag', + 'type': 'string'}, + {'name': 'credit_msat', + 'type': 'msat'}, + {'name': 'debit_msat', + 'type': 'msat'}, + {'name': 'currency', + 'type': 'string'}, + {'name': 'timestamp', + 'type': 'u32'}, + {'name': 'description', + 'type': 'string'}, + {'name': 'outpoint', + 'type': 'string'}, + {'name': 'txid', + 'type': 'txid'}, + {'name': 'payment_id', + 'type': 'hex'}]}} # Very rough checks of other list commands (make sure l2 has one of each) l2.rpc.offer(1, 'desc') diff --git a/tools/flattenschema.py b/tools/flattenschema.py index c9689b250a3a..57b9a77e55fe 100755 --- a/tools/flattenschema.py +++ b/tools/flattenschema.py @@ -34,8 +34,8 @@ def flatten_schema(schema, prefixes): parsed_args = parser.parse_args() for schemafile in parsed_args.schemafile: - # Get basename of file, e.g. listfoo -> foo. - prefix = os.path.basename(schemafile).split('.')[0][4:] + # Get basename of file, e.g. listfoo + prefix = os.path.basename(schemafile).split('.')[0] with open(schemafile, "r") as f: schema = json.load(f) # Python 3.6+ dicts maintain order, so use it to de-dup.