Browse Source

chaintopology: check bitcoin plugin commands at startup

Exit early if we won't be able to fully communicate with our Bitcoin
backend.
travis-debug
darosior 5 years ago
committed by Rusty Russell
parent
commit
ae249a2294
  1. 23
      lightningd/bitcoind.c
  2. 2
      lightningd/bitcoind.h
  3. 3
      lightningd/chaintopology.c
  4. 16
      lightningd/plugin.c
  5. 7
      lightningd/plugin.h

23
lightningd/bitcoind.c

@ -7,10 +7,12 @@
#include "bitcoind.h"
#include "lightningd.h"
#include "log.h"
#include <ccan/array_size/array_size.h>
#include <ccan/cast/cast.h>
#include <ccan/io/io.h>
#include <ccan/pipecmd/pipecmd.h>
#include <ccan/str/hex/hex.h>
#include <ccan/str/str.h>
#include <ccan/take/take.h>
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/tal/path/path.h>
@ -22,6 +24,7 @@
#include <errno.h>
#include <inttypes.h>
#include <lightningd/chaintopology.h>
#include <lightningd/plugin.h>
/* Bitcoind's web server has a default of 4 threads, with queue depth 16.
* It will *fail* rather than queue beyond that, so we must not stress it!
@ -30,6 +33,26 @@
*/
#define BITCOIND_MAX_PARALLEL 4
/* The names of the request we can make to our Bitcoin backend. */
static const char *methods[] = {"getchaininfo", "getrawblockbyheight",
"sendrawtransaction", "getutxout",
"getfeerate"};
void bitcoind_check_commands(struct bitcoind *bitcoind)
{
size_t i;
struct plugin *p;
for (i = 0; i < ARRAY_SIZE(methods); i++) {
p = find_plugin_for_command(bitcoind->ld, methods[i]);
if (p == NULL) {
fatal("Could not access the plugin for %s, is a "
"Bitcoin plugin (by default plugins/bcli) "
"registered ?", methods[i]);
}
}
}
/* Add the n'th arg to *args, incrementing n and keeping args of size n+1 */
static void add_arg(const char ***args, const char *arg)
{

2
lightningd/bitcoind.h

@ -182,4 +182,6 @@ void bitcoind_gettxout(struct bitcoind *bitcoind,
void bitcoind_getclientversion(struct bitcoind *bitcoind);
void bitcoind_check_commands(struct bitcoind *bitcoind);
#endif /* LIGHTNING_LIGHTNINGD_BITCOIND_H */

3
lightningd/chaintopology.c

@ -955,6 +955,9 @@ void setup_topology(struct chain_topology *topo,
topo->min_blockheight = min_blockheight;
topo->max_blockheight = max_blockheight;
/* This waits for bitcoind. */
bitcoind_check_commands(topo->bitcoind);
/* Make sure bitcoind is started, and ready */
wait_for_bitcoind(topo->bitcoind);

16
lightningd/plugin.c

@ -611,21 +611,21 @@ static void plugin_rpcmethod_cb(const char *buffer,
command_raw_complete(cmd, response);
}
static struct plugin *find_plugin_for_command(struct command *cmd)
struct plugin *find_plugin_for_command(struct lightningd *ld,
const char *cmd_name)
{
struct plugins *plugins = cmd->ld->plugins;
struct plugins *plugins = ld->plugins;
struct plugin *plugin;
/* Find the plugin that registered this RPC call */
list_for_each(&plugins->plugins, plugin, list) {
for (size_t i=0; i<tal_count(plugin->methods); i++) {
if (streq(cmd->json_cmd->name, plugin->methods[i]))
if (streq(cmd_name, plugin->methods[i]))
return plugin;
}
}
/* This should never happen, it'd mean that a plugin didn't
* cleanup after dying */
abort();
return NULL;
}
static struct command_result *plugin_rpcmethod_dispatch(struct command *cmd,
@ -641,7 +641,9 @@ static struct command_result *plugin_rpcmethod_dispatch(struct command *cmd,
if (cmd->mode == CMD_CHECK)
return command_param_failed();
plugin = find_plugin_for_command(cmd);
plugin = find_plugin_for_command(cmd->ld, cmd->json_cmd->name);
if (!plugin)
fatal("No plugin for %s ?", cmd->json_cmd->name);
/* Find ID again (We've parsed them before, this should not fail!) */
idtok = json_get_member(buffer, toks, "id");

7
lightningd/plugin.h

@ -180,6 +180,13 @@ bool plugin_remove(struct plugins *plugins, const char *name);
*/
void plugin_kill(struct plugin *plugin, char *fmt, ...) PRINTF_FMT(2,3);
/**
* Returns the plugin which registers the command with name {cmd_name}
*/
struct plugin *find_plugin_for_command(struct lightningd *ld,
const char *cmd_name);
/**
* Send the configure message to all plugins.
*

Loading…
Cancel
Save