From 213cbba5bf0a77a11926c3d2f9b4ca9d71bbd502 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 20 Nov 2025 12:07:14 +1030 Subject: [PATCH] lightningd: allow filtering on custommsg hook too. Changelog-Added: Plugins: "filters" can be specified on the `custommsg` hook to limit what message types the hook will be called for. Signed-off-by: Rusty Russell --- doc/developers-guide/plugin-development/hooks.md | 2 +- lightningd/connect_control.c | 12 ++++++------ tests/plugins/custommsg_b.py | 2 +- tests/test_misc.py | 6 ++++++ 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/doc/developers-guide/plugin-development/hooks.md b/doc/developers-guide/plugin-development/hooks.md index 96f1ff1a9..9c2299538 100644 --- a/doc/developers-guide/plugin-development/hooks.md +++ b/doc/developers-guide/plugin-development/hooks.md @@ -585,7 +585,7 @@ Note: The `rpc_command` hook is chainable. If two or more plugins try to replace ### `custommsg` -The `custommsg` plugin hook is the receiving counterpart to the [`sendcustommsg`](ref:sendcustommsg) RPC method and allows plugins to handle messages that are not handled internally. The goal of these two components is to allow the implementation of custom protocols or prototypes on top of a Core Lightning node, without having to change the node's implementation itself. +The `custommsg` plugin hook is the receiving counterpart to the [`sendcustommsg`](ref:sendcustommsg) RPC method and allows plugins to handle messages that are not handled internally. The goal of these two components is to allow the implementation of custom protocols or prototypes on top of a Core Lightning node, without having to change the node's implementation itself. Note that if the hook registration specifies "filters" then that should be a JSON array of message numbers, and the hook will only be called for those. Otherwise, the hook is called for all messages not handled internally. The payload for a call follows this format: diff --git a/lightningd/connect_control.c b/lightningd/connect_control.c index e57bc975a..e374ae961 100644 --- a/lightningd/connect_control.c +++ b/lightningd/connect_control.c @@ -375,11 +375,11 @@ static void custommsg_payload_serialize(struct custommsg_payload *payload, json_add_node_id(stream, "peer_id", &payload->peer_id); } -REGISTER_PLUGIN_HOOK(custommsg, - custommsg_cb, - custommsg_final, - custommsg_payload_serialize, - struct custommsg_payload *); +REGISTER_PLUGIN_HOOK_INTFILTER(custommsg, + custommsg_cb, + custommsg_final, + custommsg_payload_serialize, + struct custommsg_payload *); static void handle_custommsg_in(struct lightningd *ld, const u8 *msg) { @@ -393,7 +393,7 @@ static void handle_custommsg_in(struct lightningd *ld, const u8 *msg) } notify_custommsg(ld, &p->peer_id, p->msg); - plugin_hook_call_custommsg(ld, NULL, p); + plugin_hook_call_custommsg(ld, fromwire_peektype(p->msg), NULL, p); } static void handle_onionmsg_forward_fail(struct lightningd *ld, const u8 *msg) diff --git a/tests/plugins/custommsg_b.py b/tests/plugins/custommsg_b.py index 6282701f4..63ddcaf8d 100755 --- a/tests/plugins/custommsg_b.py +++ b/tests/plugins/custommsg_b.py @@ -4,7 +4,7 @@ from pyln.client import Plugin plugin = Plugin() -@plugin.hook('custommsg') +@plugin.hook('custommsg', filters=[0xaaff]) def on_custommsg(peer_id, payload, plugin, message=None, **kwargs): plugin.log("Got custommessage_b {msg} from peer {peer_id}".format( msg=payload, diff --git a/tests/test_misc.py b/tests/test_misc.py index 6adcfad86..31a9c3c9e 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -2903,6 +2903,12 @@ def test_sendcustommsg(node_factory): msg=msg, peer_id=l2.info['id']), ]) + # custommessage_b plugin only registers for 0xaaff msgs, so it won't see this one: + msg2 = 'aa' + ('fd' * 30) + 'bb' + l2.rpc.sendcustommsg(l4.info['id'], msg2) + l4.daemon.wait_for_log(f'Got custommessage_a {msg2} from peer') + assert not l4.daemon.is_in_log(f'Got custommessage_b {msg2} from peer') + def test_custommsg_triggers_notification(node_factory): """Check that a notification is triggered when a node receives