bwatch: add watch_found and watch_revert notifications
What changed, and why it matters
This commit adds two internal notification functions inside Core Lightning's new block-watching plugin. They are not yet connected to anything; the commit message says they will be wired up later. There is no user-facing change and no security fix or vulnerability present in the diff.
No security action required. Treat as normal feature/refactoring commit. Review the subsequent commits that wire these notifications to ensure watch_found/watch_revert state handling is robust against reorgs and duplicate notifications.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch introduces bwatch_send_watch_found() and bwatch_send_watch_revert() in plugins/bwatch/bwatch_interface.c/h. Both send JSON-RPC notifications to lightningd via an auxiliary command so they do not block the main poll command. watch_found reports a watched transaction (or SCID absence) with block height, owners, txindex and optional output index; watch_revert tells a single owner that a prior watch_found was rolled back during a reorg. The generic notify_ack callback is moved earlier in the file. No handlers for these notifications exist yet and the commit explicitly states wiring is deferred to subsequent commits.
Changed components
plugins/bwatch/bwatch_interface.cplugins/bwatch/bwatch_interface.hInspect captured patch +82 / −15
diff --git a/plugins/bwatch/bwatch_interface.c b/plugins/bwatch/bwatch_interface.c
index 623046a5..7248fe0f 100644
--- a/plugins/bwatch/bwatch_interface.c
+++ b/plugins/bwatch/bwatch_interface.c
@@ -4,6 +4,75 @@
#include <common/json_stream.h>
#include <plugins/bwatch/bwatch_interface.h>
+/*
+ * ============================================================================
+ * SENDING WATCH_FOUND NOTIFICATIONS
+ * ============================================================================
+ */
+
+/* Callback for watch_found RPC.
+ * watch_found notifications are sent on an aux command so they cannot
+ * interfere with the poll command lifetime. */
+static struct command_result *notify_ack(struct command *cmd,
+ const char *method UNUSED,
+ const char *buf UNUSED,
+ const jsmntok_t *result UNUSED,
+ void *arg UNUSED)
+{
+ return aux_command_done(cmd);
+}
+
+/* Send watch_found notification to lightningd. */
+void bwatch_send_watch_found(struct command *cmd,
+ const struct bitcoin_tx *tx,
+ u32 blockheight,
+ const struct watch *w,
+ u32 txindex,
+ u32 index)
+{
+ struct command *aux = aux_command(cmd);
+ struct out_req *req;
+
+ req = jsonrpc_request_start(aux, "watch_found",
+ notify_ack, notify_ack, NULL);
+ /* tx==NULL signals "not found" for WATCH_SCID; omit tx+txindex so
+ * json_watch_found passes tx=NULL down to the handler. */
+ if (tx) {
+ json_add_tx(req->js, "tx", tx);
+ json_add_u32(req->js, "txindex", txindex);
+ if (index != UINT32_MAX)
+ json_add_u32(req->js, "index", index);
+ }
+ json_add_u32(req->js, "blockheight", blockheight);
+
+ /* Add owners array */
+ json_array_start(req->js, "owners");
+ for (size_t i = 0; i < tal_count(w->owners); i++)
+ json_add_string(req->js, NULL, w->owners[i]);
+ json_array_end(req->js);
+
+ /* Tests (and operators) key off this line; keep wording stable. */
+ plugin_log(cmd->plugin, LOG_DBG,
+ "watch_found at block %u", blockheight);
+
+ send_outreq(req);
+}
+
+/* Tell one owner that a previously-reported watch_found was rolled back. */
+void bwatch_send_watch_revert(struct command *cmd,
+ const char *owner,
+ u32 blockheight)
+{
+ struct command *aux = aux_command(cmd);
+ struct out_req *req;
+
+ req = jsonrpc_request_start(aux, "watch_revert",
+ notify_ack, notify_ack, NULL);
+ json_add_string(req->js, "owner", owner);
+ json_add_u32(req->js, "blockheight", blockheight);
+ send_outreq(req);
+}
+
/*
* ============================================================================
* SENDING BLOCK_PROCESSED NOTIFICATION
@@ -82,17 +151,6 @@ struct command_result *bwatch_send_block_processed(struct command *cmd)
* ============================================================================
*/
-/* Generic fire-and-forget ack: aux notifications don't gate the poll, so
- * we just close the aux command on either success or error. */
-static struct command_result *notify_ack(struct command *cmd,
- const char *method UNUSED,
- const char *buf UNUSED,
- const jsmntok_t *result UNUSED,
- void *arg UNUSED)
-{
- return aux_command_done(cmd);
-}
-
/* Notify watchman that a block was rolled back so it can update and persist
* its tip. Fire-and-forget via aux_command — the poll timer doesn't depend
* on the ack. Crash safety: if we crash before the ack, watchman's stale
diff --git a/plugins/bwatch/bwatch_interface.h b/plugins/bwatch/bwatch_interface.h
index 30bd1252..092d3f21 100644
--- a/plugins/bwatch/bwatch_interface.h
+++ b/plugins/bwatch/bwatch_interface.h
@@ -4,10 +4,19 @@
#include "config.h"
#include <plugins/bwatch/bwatch.h>
-/* Outward-facing interface from bwatch to lightningd.
- *
- * Subsequent commits add the watch_found / watch_revert notifications
- * and the addwatch / delwatch / listwatch RPC commands. */
+/* Outward-facing interface from bwatch to lightningd. */
+
+/* Send watch_found notification to lightningd */
+void bwatch_send_watch_found(struct command *cmd,
+ const struct bitcoin_tx *tx,
+ u32 blockheight,
+ const struct watch *w,
+ u32 txindex,
+ u32 index);
+
+void bwatch_send_watch_revert(struct command *cmd,
+ const char *owner,
+ u32 blockheight);
/* Send a block_processed RPC to watchman after a new block has been
* persisted. The next poll is started from the ack callback so we don't
Why this scored 15/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.