diff --git a/doc/lightning-listconfigs.7.md b/doc/lightning-listconfigs.7.md index d021677d1..acb1b41e8 100644 --- a/doc/lightning-listconfigs.7.md +++ b/doc/lightning-listconfigs.7.md @@ -45,6 +45,7 @@ On success, an object is returned, containing: - **disable-mpp** (object, optional): - **set** (boolean): `true` if set in config or cmdline - **source** (string): source of configuration setting + - **plugin** (string, optional): plugin which registered this configuration setting - **mainnet** (object, optional): - **set** (boolean): `true` if set in config or cmdline - **source** (string): source of configuration setting @@ -446,4 +447,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:1702f7c62fe10d63612fbbf56eeaf043cdfef6fa874d4fdbdcb81bbbbe5c98d8) +[comment]: # ( SHA256STAMP:2b3588b395919162c122cd386f0f4b320d906d0190e706bfa1b68db4126e7ee2) diff --git a/doc/schemas/listconfigs.schema.json b/doc/schemas/listconfigs.schema.json index 844c60c28..900dbbcf3 100644 --- a/doc/schemas/listconfigs.schema.json +++ b/doc/schemas/listconfigs.schema.json @@ -65,6 +65,10 @@ "source": { "type": "string", "description": "source of configuration setting" + }, + "plugin": { + "type": "string", + "description": "plugin which registered this configuration setting" } } }, diff --git a/lightningd/options.c b/lightningd/options.c index e047973b7..f81ea1e75 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -2066,6 +2066,7 @@ static void json_add_config(struct lightningd *ld, json_object_start(response, names[0]); json_add_bool(response, "set", cv != NULL); json_add_source(response, "source", cv); + json_add_config_plugin(response, ld->plugins, "plugin", ot); json_object_end(response); return; } @@ -2089,6 +2090,7 @@ static void json_add_config(struct lightningd *ld, json_add_source(response, NULL, cv); } json_array_end(response); + json_add_config_plugin(response, ld->plugins, "plugin", ot); json_object_end(response); return; } @@ -2101,6 +2103,7 @@ static void json_add_config(struct lightningd *ld, json_object_start(response, names[0]); json_add_configval(response, configval_fieldname(ot), ot, val); json_add_source(response, "source", cv); + json_add_config_plugin(response, ld->plugins, "plugin", ot); json_object_end(response); } diff --git a/lightningd/plugin.c b/lightningd/plugin.c index 4b8a0a4f9..81a936a30 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -1366,6 +1366,29 @@ static struct plugin_opt *plugin_opt_find(const struct plugin *plugin, return NULL; } +void json_add_config_plugin(struct json_stream *stream, + const struct plugins *plugins, + const char *fieldname, + const struct opt_table *ot) +{ + struct plugin *plugin; + + /* Shortcut */ + if (!is_plugin_opt(ot)) + return; + + /* Find the plugin that registered this RPC call */ + list_for_each(&plugins->plugins, plugin, list) { + struct plugin_opt *popt = plugin_opt_find(plugin, ot->names+2); + if (popt) { + json_add_string(stream, fieldname, plugin->cmd); + return; + } + } + + /* Reaching here is possible, if a plugin was stopped! */ +} + /* Start command might have included plugin-specific parameters. * We make sure they *are* parameters for this plugin, then add them * to our configvars. */ diff --git a/lightningd/plugin.h b/lightningd/plugin.h index 5ba750d9d..587a214be 100644 --- a/lightningd/plugin.h +++ b/lightningd/plugin.h @@ -358,4 +358,11 @@ void plugins_set_builtin_plugins_dir(struct plugins *plugins, /* Is this option for a plugin? */ bool is_plugin_opt(const struct opt_table *ot); + +/* Add this field if this ot is owned by a plugin */ +void json_add_config_plugin(struct json_stream *stream, + const struct plugins *plugins, + const char *fieldname, + const struct opt_table *ot); + #endif /* LIGHTNING_LIGHTNINGD_PLUGIN_H */ diff --git a/tests/test_misc.py b/tests/test_misc.py index d2626912e..759340985 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -738,6 +738,7 @@ def test_listconfigs(node_factory, bitcoind, chainparams): c = configs[name] assert c['source'] == 'cmdline' assert c[valfield] == val + assert 'plugin' not in c # These are aliases, but we don't print the (unofficial!) wumbo. assert 'wumbo' not in configs diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 2113cea51..a5c3a85d4 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -2441,6 +2441,7 @@ def test_dynamic_args(node_factory): assert l1.rpc.call("hello") == "Test arg parsing world" assert l1.rpc.listconfigs('greeting')['configs']['greeting']['value_str'] == 'Test arg parsing' + assert l1.rpc.listconfigs('greeting')['configs']['greeting']['plugin'] == plugin_path l1.rpc.plugin_stop(plugin_path) assert 'greeting' not in l1.rpc.listconfigs()['configs'] @@ -4166,6 +4167,7 @@ def test_plugin_persist_option(node_factory): c = l1.rpc.listconfigs('greeting')['configs']['greeting'] assert c['source'] == "cmdline" assert c['value_str'] == "Static option" + assert c['plugin'] == plugin_path l1.rpc.plugin_stop(plugin_path) assert 'greeting' not in l1.rpc.listconfigs()['configs'] @@ -4174,6 +4176,7 @@ def test_plugin_persist_option(node_factory): c = l1.rpc.listconfigs('greeting')['configs']['greeting'] assert c['source'] == "cmdline" assert c['value_str'] == "Static option" + assert c['plugin'] == plugin_path assert l1.rpc.call("hello") == "Static option world" l1.rpc.plugin_stop(plugin_path) assert 'greeting' not in l1.rpc.listconfigs()['configs'] @@ -4183,6 +4186,7 @@ def test_plugin_persist_option(node_factory): c = l1.rpc.listconfigs('greeting')['configs']['greeting'] assert c['source'] == "pluginstart" assert c['value_str'] == "Dynamic option" + assert c['plugin'] == plugin_path assert l1.rpc.call("hello") == "Dynamic option world" l1.rpc.plugin_stop(plugin_path) assert 'greeting' not in l1.rpc.listconfigs()['configs'] @@ -4192,4 +4196,5 @@ def test_plugin_persist_option(node_factory): c = l1.rpc.listconfigs('greeting')['configs']['greeting'] assert c['source'] == "cmdline" assert c['value_str'] == "Static option" + assert c['plugin'] == plugin_path assert l1.rpc.call("hello") == "Static option world"