plugins: defer spenderp awaiting-channel recovery
What changed, and why it matters
This change moves a startup recovery task in the 'spenderp' plugin so it runs 180 seconds after startup instead of immediately during plugin initialization. The recovery task signs unsigned PSBTs for channels that are waiting to lock in. The patch is meant to prevent slow wallet signing from blocking other built-in plugins during startup. It is a performance and reliability fix, not a direct security patch, but the original behavior could have caused startup delays or related availability issues.
Treat as a reliability/availability improvement rather than a security fix. Review whether 180 seconds is adequate for all deployment scenarios and ensure the timer callback handles plugin shutdown cleanly. No urgent security action is required based on this diff alone.
Security signals we found
Startup blocking by a plugin could affect node availability
Deferred recovery reduces risk of init-time denial-of-service-like stalls
No input validation, memory safety, or cryptographic changes visible
No explicit vulnerability or exploit path introduced by the diff
Evidence from the diff
The commit modifies plugins/spender/openchannel.c. It converts list_awaiting_channels from a synchronous init-time call into a timer callback scheduled 180 seconds after plugin startup via global_timer. The function still queries listpeerchannels and issues signpsbt requests for channels in AWAITING_LOCKIN with unsigned PSBTs, but now defers that work so it does not block the plugin init handshake. The change is defensive: slow signing on large wallets no longer stalls other builtin plugins’ startup.
Changed components
plugins/spender/openchannel.cspenderp plugin startup sequencechannel funding PSBT recovery for AWAITING_LOCKIN channelsInspect captured patch +16 / −4
diff --git a/plugins/spender/openchannel.c b/plugins/spender/openchannel.c
index 432963d4..2ff5a570 100644
--- a/plugins/spender/openchannel.c
+++ b/plugins/spender/openchannel.c
@@ -1078,15 +1078,20 @@ static struct command_result *signpsbt_done(struct command *aux_cmd,
return send_outreq(req);
}
+/* Delay startup recovery so slow wallet signing does not block other
+ * important plugins from completing their init handshake. */
+#define AWAITING_CHANNELS_RECOVERY_DELAY 180
+
/* If there are any channels with unsigned PSBTs in AWAITING_LOCKIN,
* sign them now (assume we crashed) */
-static void list_awaiting_channels(struct command *init_cmd)
+static struct command_result *list_awaiting_channels(struct command *timer_cmd,
+ void *unused UNUSED)
{
const char *buf;
size_t i;
const jsmntok_t *resp, *t, *channels;
- resp = jsonrpc_request_sync(tmpctx, init_cmd,
+ resp = jsonrpc_request_sync(tmpctx, timer_cmd,
"listpeerchannels",
NULL, &buf);
channels = json_get_member(buf, resp, "channels");
@@ -1113,13 +1118,15 @@ static void list_awaiting_channels(struct command *init_cmd)
continue;
/* Don't do this sync, as it can reasonably fail! */
- aux_cmd = aux_command(init_cmd);
+ aux_cmd = aux_command(timer_cmd);
req = jsonrpc_request_start(aux_cmd, "signpsbt",
signpsbt_done, psbt_error,
tal_dup(aux_cmd, struct channel_id, &cid));
json_add_psbt(req->js, "psbt", psbt);
send_outreq(req);
}
+
+ return timer_complete(timer_cmd);
}
void openchannel_init(struct command *init_cmd, const char *b, const jsmntok_t *t)
@@ -1127,7 +1134,12 @@ void openchannel_init(struct command *init_cmd, const char *b, const jsmntok_t *
/* Initialize our list! */
list_head_init(&mfc_commands);
- list_awaiting_channels(init_cmd);
+ /* Recover any waiting channel funding PSBTs after plugin startup.
+ * Signing can be slow on large wallets, and doing it during init can block
+ * other important builtins from completing their startup handshake. */
+ global_timer(init_cmd->plugin,
+ time_from_sec(AWAITING_CHANNELS_RECOVERY_DELAY),
+ list_awaiting_channels, NULL);
}
const struct plugin_notification openchannel_notifs[] = {
Why this scored 31/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.