bcli: refactor `wait_and_check_bitcoind` and `run_bitcoin_cli` to use shared execution
What changed, and why it matters
This is a routine code cleanup in Core Lightning's bitcoin-cli plugin. It pulls out duplicated code for running bitcoin-cli into a single shared helper function, with no intended behavior change. There is no indication this fixes or introduces a security vulnerability.
No security action required; treat as normal maintenance refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors plugins/bcli.c so that run_bitcoin_cli and wait_and_check_bitcoind both call a new execute_bitcoin_cli helper. The helper handles pipecmdarr, stdin writes, output capture, and waitpid. wait_and_check_bitcoind loses its inline duplicate of that logic and now passes NULL for stdinargs because -rpcwait flags are command-line arguments. Error handling is slightly restructured: the old code checked WIFEXITED/WEXITSTATUS and produced specific timeout messages; the new code checks res->exitstatus directly and emits equivalent messages. No functional change is evident from the diff.
Changed components
plugins/bcli.cInspect captured patch +42 / −51
diff --git a/plugins/bcli.c b/plugins/bcli.c
index b914714d..c9ca1ec8 100644
--- a/plugins/bcli.c
+++ b/plugins/bcli.c
@@ -148,23 +148,18 @@ static char *args_string(const tal_t *ctx, const char **args, const char **stdin
return ret;
}
-/* Synchronous execution of bitcoin-cli.
+/* Execute bitcoin-cli with pre-built command and optional stdin args.
* Returns result with output and exit status. */
static struct bcli_result *
-run_bitcoin_cliv(const tal_t *ctx,
- struct plugin *plugin,
- const char *method,
- va_list ap)
+execute_bitcoin_cli(const tal_t *ctx,
+ struct plugin *plugin,
+ const char **cmd,
+ const char **stdinargs)
{
int in, from, status;
pid_t child;
- const char **stdinargs;
- const char **cmd;
struct bcli_result *res;
- stdinargs = tal_arr(ctx, const char *, 0);
- cmd = gather_argsv(ctx, &stdinargs, method, ap);
-
child = pipecmdarr(&in, &from, &from, cast_const2(char **, cmd));
if (child < 0)
plugin_err(plugin, "%s exec failed: %s", cmd[0], strerror(errno));
@@ -175,9 +170,11 @@ run_bitcoin_cliv(const tal_t *ctx,
write_all(in, "\n", 1);
}
/* Send any additional stdin args */
- for (size_t i = 0; i < tal_count(stdinargs); i++) {
- write_all(in, stdinargs[i], strlen(stdinargs[i]));
- write_all(in, "\n", 1);
+ if (stdinargs) {
+ for (size_t i = 0; i < tal_count(stdinargs); i++) {
+ write_all(in, stdinargs[i], strlen(stdinargs[i]));
+ write_all(in, "\n", 1);
+ }
}
close(in);
@@ -205,6 +202,23 @@ run_bitcoin_cliv(const tal_t *ctx,
return res;
}
+/* Synchronous execution of bitcoin-cli.
+ * Returns result with output and exit status. */
+static struct bcli_result *
+run_bitcoin_cliv(const tal_t *ctx,
+ struct plugin *plugin,
+ const char *method,
+ va_list ap)
+{
+ const char **stdinargs;
+ const char **cmd;
+
+ stdinargs = tal_arr(ctx, const char *, 0);
+ cmd = gather_argsv(ctx, &stdinargs, method, ap);
+
+ return execute_bitcoin_cli(ctx, plugin, cmd, stdinargs);
+}
+
static LAST_ARG_NULL struct bcli_result *
run_bitcoin_cli(const tal_t *ctx,
struct plugin *plugin,
@@ -757,51 +771,28 @@ static void parse_getnetworkinfo_result(struct plugin *p, const char *buf)
static void wait_and_check_bitcoind(struct plugin *p)
{
- int in, from, status;
- pid_t child;
- const char **cmd = gather_args(
- bitcoind, NULL, "-rpcwait", "-rpcwaittimeout=30", "getnetworkinfo", NULL);
- char *output = NULL;
-
- child = pipecmdarr(&in, &from, &from, cast_const2(char **, cmd));
-
- if (bitcoind->rpcpass)
- write_all(in, bitcoind->rpcpass, strlen(bitcoind->rpcpass));
-
- close(in);
-
- if (child < 0) {
- if (errno == ENOENT)
- bitcoind_failure(
- p,
- "bitcoin-cli not found. Is bitcoin-cli "
- "(part of Bitcoin Core) available in your PATH?");
- plugin_err(p, "%s exec failed: %s", cmd[0], strerror(errno));
- }
-
- output = grab_fd_str(cmd, from);
- close(from);
+ struct bcli_result *res;
+ const char **cmd;
- waitpid(child, &status, 0);
+ /* Special case: -rpcwait flags go on command line, not stdin */
+ cmd = gather_args(bitcoind, NULL, "-rpcwait", "-rpcwaittimeout=30",
+ "getnetworkinfo", NULL);
+ res = execute_bitcoin_cli(bitcoind, p, cmd, NULL);
- if (!WIFEXITED(status))
- bitcoind_failure(p, tal_fmt(bitcoind, "Death of %s: signal %i",
- cmd[0], WTERMSIG(status)));
-
- if (WEXITSTATUS(status) != 0) {
- if (WEXITSTATUS(status) == 1)
- bitcoind_failure(p,
- "RPC connection timed out. Could "
- "not connect to bitcoind using "
- "bitcoin-cli. Is bitcoind running?");
+ if (res->exitstatus == 1)
+ bitcoind_failure(p,
+ "RPC connection timed out. Could "
+ "not connect to bitcoind using "
+ "bitcoin-cli. Is bitcoind running?");
+ if (res->exitstatus != 0)
bitcoind_failure(p,
tal_fmt(bitcoind, "%s exited with code %i: %s",
- cmd[0], WEXITSTATUS(status), output));
- }
+ res->args, res->exitstatus, res->output));
- parse_getnetworkinfo_result(p, output);
+ parse_getnetworkinfo_result(p, res->output);
tal_free(cmd);
+ tal_free(res);
}
static void memleak_mark_bitcoind(struct plugin *p, struct htable *memtable)
Why this scored 13/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.