plugins/bcli: use -rpcwait to simplify waiting for bitcoind to warm up Replaced custom wait logic with the -rpcwait flag in bitcoin-cli to handle waiting for bitcoind to warm up. This simplifies the code and ensures that errors unrelated to warmup are passed up directly without additional checks. Ch
What changed, and why it matters
This change simplifies how Core Lightning's bitcoin-cli plugin waits for the Bitcoin node to finish starting up. It replaces a custom retry loop with bitcoin-cli's built-in -rpcwait flag. The main effect is cleaner code and slightly different error handling when bitcoin-cli cannot connect. There is no direct evidence this fixes an active security vulnerability, but any change in startup error handling can have subtle reliability implications.
Treat as a routine code-quality/refactoring patch. Review whether the 30-second -rpcwaittimeout is appropriate for all deployment environments and whether the new error message accurately covers authentication failures as well as connection failures. No urgent security action is indicated.
Security signals we found
Change in error-handling path during plugin startup
Removal of custom retry loop that distinguished warmup (exit code 28) from other failures
Introduction of -rpcwaittimeout=30, which adds a bounded wait where previously the loop was unbounded
No explicit security framing in commit message or diff
Evidence from the diff
The patch refactors wait_and_check_bitcoind() in plugins/bcli.c. Previously the code repeatedly spawned bitcoin-cli getnetworkinfo, checked for exit code 28 (RPC_IN_WARMUP), and slept for one second between attempts. The new code passes -rpcwait and -rpcwaittimeout=30 to bitcoin-cli, letting bitcoin-cli itself handle warmup polling for up to 30 seconds. The custom waitpid/EINTR loop and printed warmup message are removed. Error paths are simplified: exit code 1 is now reported as an RPC connection timeout, and other non-zero exits are passed through. The change removes a local variable ‘ret’ and reduces code by about 14 lines.
Changed components
plugins/bcli.cwait_and_check_bitcoind() functionCore Lightning startup sequence against bitcoindInspect captured patch +30 / −44
diff --git a/plugins/bcli.c b/plugins/bcli.c
index 9f17282f..fdd5a7c6 100644
--- a/plugins/bcli.c
+++ b/plugins/bcli.c
@@ -1044,59 +1044,45 @@ static void parse_getnetworkinfo_result(struct plugin *p, const char *buf)
static void wait_and_check_bitcoind(struct plugin *p)
{
- int in, from, status, ret;
+ int in, from, status;
pid_t child;
- const char **cmd = gather_args(bitcoind, "getnetworkinfo", NULL);
- bool printed = false;
+ const char **cmd = gather_args(
+ bitcoind, "-rpcwait", "-rpcwaittimeout=30", "getnetworkinfo", NULL);
char *output = NULL;
- for (;;) {
- tal_free(output);
+ child = pipecmdarr(&in, &from, &from, cast_const2(char **, cmd));
- child = pipecmdarr(&in, &from, &from, cast_const2(char **, cmd));
+ if (bitcoind->rpcpass)
+ write_all(in, bitcoind->rpcpass, strlen(bitcoind->rpcpass));
- if (bitcoind->rpcpass)
- write_all(in, bitcoind->rpcpass, strlen(bitcoind->rpcpass));
+ close(in);
- 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));
+ }
- 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(cmd, from);
- output = grab_fd(cmd, from);
-
- while ((ret = waitpid(child, &status, 0)) < 0 && errno == EINTR);
- if (ret != child)
- bitcoind_failure(p, tal_fmt(bitcoind, "Waiting for %s: %s",
- cmd[0], strerror(errno)));
- if (!WIFEXITED(status))
- bitcoind_failure(p, tal_fmt(bitcoind, "Death of %s: signal %i",
- cmd[0], WTERMSIG(status)));
-
- if (WEXITSTATUS(status) == 0)
- break;
-
- /* bitcoin/src/rpc/protocol.h:
- * RPC_IN_WARMUP = -28, //!< Client still warming up
- */
- if (WEXITSTATUS(status) != 28) {
- if (WEXITSTATUS(status) == 1)
- bitcoind_failure(p, "Could not connect to bitcoind using"
- " bitcoin-cli. Is bitcoind running?");
- bitcoind_failure(p, tal_fmt(bitcoind, "%s exited with code %i: %s",
- cmd[0], WEXITSTATUS(status), output));
- }
+ waitpid(child, &status, 0);
- if (!printed) {
- plugin_log(p, LOG_UNUSUAL,
- "Waiting for bitcoind to warm up...");
- printed = true;
- }
- sleep(1);
+ 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?");
+ bitcoind_failure(p,
+ tal_fmt(bitcoind, "%s exited with code %i: %s",
+ cmd[0], WEXITSTATUS(status), output));
}
parse_getnetworkinfo_result(p, output);
Why this scored 19/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.