lightningd: `delnetworkevent` support
What changed, and why it matters
This commit adds a new administrative JSON-RPC command called `delnetworkevent` that lets a node operator delete a single diagnostic network event from the local database by its index. It is intended for housekeeping (for example, the autoclean plugin) and does not affect live channels or funds. There is no indication in the commit that this fixes a security bug; it appears to be a routine feature addition.
No security action required beyond normal code review. Operators should ensure RPC access remains authenticated and restricted as with all administrative commands.
Security signals we found
New RPC command added with explicit non-security purpose
Uses existing prepared-statement parameter binding (db_bind_u64) for the index
No SQL injection or type-confusion signals in the diff
No changelog or commit message claims security relevance
Evidence from the diff
The patch introduces delnetworkevent RPC, a new error code DELNETWORKEVENT_NOT_FOUND (1402), a wallet helper wallet_network_event_delete(), and a wait notification for deletions. The command takes a created_index (u64), deletes the matching row from the network_events table, and emits a wait index-deleted event. The schema explicitly states these entries are only for analysis and removal has no effect on node operation. No input sanitization issues, injection vectors, or authorization bypasses are visible in the diff.
Changed components
lightningd JSON-RPC interfacewallet/wallet.cwallet/walletrpc.ccommon/jsonrpc_errors.hdoc/schemas/delnetworkevent.jsonInspect captured patch +180 / −1
diff --git a/common/jsonrpc_errors.h b/common/jsonrpc_errors.h
index 48ff0788..d3fe80d5 100644
--- a/common/jsonrpc_errors.h
+++ b/common/jsonrpc_errors.h
@@ -129,8 +129,9 @@ enum jsonrpc_errcode {
/* Errors from signmessage command */
SIGNMESSAGE_PUBKEY_NOT_FOUND = 1301,
- /* Errors from delforward command */
+ /* Errors from del commands */
DELFORWARD_NOT_FOUND = 1401,
+ DELNETWORKEVENT_NOT_FOUND = 1402,
/* Errors from runes */
RUNE_NOT_AUTHORIZED = 1501,
diff --git a/contrib/msggen/msggen/schema.json b/contrib/msggen/msggen/schema.json
index f3000854..d1927242 100644
--- a/contrib/msggen/msggen/schema.json
+++ b/contrib/msggen/msggen/schema.json
@@ -10344,6 +10344,50 @@
}
]
},
+ "delnetworkevent.json": {
+ "$schema": "../rpc-schema-draft.json",
+ "type": "object",
+ "rpc": "delnetworkevent",
+ "title": "Command for removing a listnetworkevents entry",
+ "description": [
+ "The **delnetworkevent** RPC command removes a single event from **listnetworkevents**, using the uniquely-identifying *created_index*.",
+ "",
+ "This command is mainly used by the *autoclean* plugin (see lightningd-config(7)), as these database entries are only kept for your own analysis, removing them has no effect on the running of your node."
+ ],
+ "request": {
+ "required": [
+ "created_index"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "created_index": {
+ "type": "u64",
+ "description": [
+ "The unique created_index of the entry.."
+ ]
+ }
+ }
+ },
+ "response": {
+ "required": [],
+ "additionalProperties": false,
+ "properties": {}
+ },
+ "errors": [
+ "The following errors may be reported:",
+ "",
+ "- 1402: The listnetworkevents specified does not exist."
+ ],
+ "author": [
+ "Rusty Russell <<rusty@rustcorp.com.au>> is mainly responsible."
+ ],
+ "see_also": [
+ "lightning-autoclean(7)"
+ ],
+ "resources": [
+ "Main web site: <https://github.com/ElementsProject/lightning>"
+ ]
+ },
"delpay.json": {
"$schema": "../rpc-schema-draft.json",
"type": "object",
diff --git a/doc/schemas/delnetworkevent.json b/doc/schemas/delnetworkevent.json
new file mode 100644
index 00000000..0272e91d
--- /dev/null
+++ b/doc/schemas/delnetworkevent.json
@@ -0,0 +1,44 @@
+{
+ "$schema": "../rpc-schema-draft.json",
+ "type": "object",
+ "rpc": "delnetworkevent",
+ "title": "Command for removing a listnetworkevents entry",
+ "description": [
+ "The **delnetworkevent** RPC command removes a single event from **listnetworkevents**, using the uniquely-identifying *created_index*.",
+ "",
+ "This command is mainly used by the *autoclean* plugin (see lightningd-config(7)), as these database entries are only kept for your own analysis, removing them has no effect on the running of your node."
+ ],
+ "request": {
+ "required": [
+ "created_index"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "created_index": {
+ "type": "u64",
+ "description": [
+ "The unique created_index of the entry.."
+ ]
+ }
+ }
+ },
+ "response": {
+ "required": [],
+ "additionalProperties": false,
+ "properties": {}
+ },
+ "errors": [
+ "The following errors may be reported:",
+ "",
+ "- 1402: The listnetworkevents specified does not exist."
+ ],
+ "author": [
+ "Rusty Russell <<rusty@rustcorp.com.au>> is mainly responsible."
+ ],
+ "see_also": [
+ "lightning-autoclean(7)"
+ ],
+ "resources": [
+ "Main web site: <https://github.com/ElementsProject/lightning>"
+ ]
+}
diff --git a/tests/test_connection.py b/tests/test_connection.py
index 226b9506..bc609cfd 100644
--- a/tests/test_connection.py
+++ b/tests/test_connection.py
@@ -5015,3 +5015,34 @@ def test_networkevents(node_factory, executor):
failevents = [n for n in l2.rpc.listnetworkevents()['networkevents'] if n['type'] == 'connect_fail']
assert failevents[-1]['connect_attempted'] is False
+
+ fut = executor.submit(l1.rpc.wait, 'networkevents', 'deleted', 1)
+ time.sleep(1)
+ l1.rpc.delnetworkevent(8)
+ assert l1.rpc.listnetworkevents(start=8) == {'networkevents': []}
+
+ res = fut.result(TIMEOUT)
+ assert res == {'subsystem': 'networkevents',
+ 'deleted': 1,
+ 'networkevents': {'created_index': 8}}
+
+ with pytest.raises(RpcError, match="Could not find that networkevent") as err:
+ l1.rpc.delnetworkevent(8)
+ DELNETWORKEVENT_NOT_FOUND = 1402
+ assert err.value.error['code'] == DELNETWORKEVENT_NOT_FOUND
+
+ l1.rpc.delnetworkevent(3)
+ with l1.rpc.reply_filter({'networkevents': [{"created_index": True, "type": True}]}):
+ assert l1.rpc.listnetworkevents() == {'networkevents':
+ [{'created_index': 1,
+ 'type': 'connect'},
+ {'created_index': 2,
+ 'type': 'ping'},
+ {'created_index': 4,
+ 'type': 'connect_fail'},
+ {'created_index': 5,
+ 'type': 'connect_fail'},
+ {'created_index': 6,
+ 'type': 'connect_fail'},
+ {'created_index': 7,
+ 'type': 'connect'}]}
diff --git a/wallet/wallet.c b/wallet/wallet.c
index b4982fb2..780aba24 100644
--- a/wallet/wallet.c
+++ b/wallet/wallet.c
@@ -7552,6 +7552,13 @@ static u64 network_event_index_created(struct lightningd *ld,
WAIT_INDEX_CREATED);
}
+static void network_event_index_deleted(struct lightningd *ld,
+ u64 created_index)
+{
+ network_event_index_inc(ld, &created_index, NULL, NULL,
+ WAIT_INDEX_DELETED);
+}
+
/* Put the next network event into the db */
void wallet_save_network_event(struct lightningd *ld,
const struct node_id *peer_id,
@@ -7587,6 +7594,30 @@ void wallet_save_network_event(struct lightningd *ld,
db_exec_prepared_v2(take(stmt));
}
+bool wallet_network_event_delete(struct wallet *w, u64 created_index)
+{
+ struct db_stmt *stmt;
+ bool changed;
+
+ stmt = db_prepare_v2(w->db,
+ SQL("DELETE FROM network_events"
+ " WHERE id = ?"));
+ db_bind_u64(stmt, created_index);
+ db_exec_prepared_v2(stmt);
+
+ changed = db_count_changes(stmt) != 0;
+ tal_free(stmt);
+
+ if (changed) {
+ /* FIXME: We don't set other details here, since that
+ * would need an extra lookup */
+ network_event_index_deleted(w->ld, created_index);
+ }
+
+ return changed;
+
+}
+
struct missing {
size_t num_found;
struct missing_addr *addrs;
diff --git a/wallet/wallet.h b/wallet/wallet.h
index 1835af77..5b33dfce 100644
--- a/wallet/wallet.h
+++ b/wallet/wallet.h
@@ -1921,6 +1921,9 @@ struct db_stmt *wallet_network_events_first(struct wallet *w,
struct db_stmt *wallet_network_events_next(struct wallet *w,
struct db_stmt *stmt);
+/* Delete one entry. Returns false if it doesn't exist. */
+bool wallet_network_event_delete(struct wallet *w, u64 created_index);
+
/**
* Extract a network event from the db.
* @ctx: the tal ctx to allocate off
diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c
index e7c44611..e3ecb56a 100644
--- a/wallet/walletrpc.c
+++ b/wallet/walletrpc.c
@@ -1301,3 +1301,28 @@ static const struct json_command listnetworkevents_cmd = {
json_listnetworkevents
};
AUTODATA(json_command, &listnetworkevents_cmd);
+
+static struct command_result *json_delnetworkevent(struct command *cmd,
+ const char *buffer,
+ const jsmntok_t *obj UNNEEDED,
+ const jsmntok_t *params)
+{
+ u64 *created_index;
+
+ if (!param(cmd, buffer, params,
+ p_req("created_index", param_u64, &created_index),
+ NULL))
+ return command_param_failed();
+
+ if (!wallet_network_event_delete(cmd->ld->wallet, *created_index))
+ return command_fail(cmd, DELNETWORKEVENT_NOT_FOUND,
+ "Could not find that networkevent");
+
+ return command_success(cmd, json_stream_success(cmd));
+}
+
+static const struct json_command delnetworkevent_command = {
+ "delnetworkevent",
+ json_delnetworkevent,
+};
+AUTODATA(json_command, &delnetworkevent_command);
Why this scored 24/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.