diff --git a/contrib/pyln-client/pyln/client/plugin.py b/contrib/pyln-client/pyln/client/plugin.py index d14ae5d3c8bc..59d99bf7886a 100644 --- a/contrib/pyln-client/pyln/client/plugin.py +++ b/contrib/pyln-client/pyln/client/plugin.py @@ -217,13 +217,15 @@ def __init__(self, stdout: Optional[io.TextIOBase] = None, dynamic: bool = True, init_features: Optional[Union[int, str, bytes]] = None, node_features: Optional[Union[int, str, bytes]] = None, - invoice_features: Optional[Union[int, str, bytes]] = None): + invoice_features: Optional[Union[int, str, bytes]] = None, + custom_msgs: Optional[List[int]] = None): self.methods = { 'init': Method('init', self._init, MethodType.RPCMETHOD) } self.options: Dict[str, Dict[str, Any]] = {} self.notification_topics: List[str] = [] + self.custom_msgs = custom_msgs def convert_featurebits( bits: Optional[Union[int, str, bytes]]) -> Optional[str]: @@ -931,6 +933,9 @@ def _getmanifest(self, **kwargs) -> JSONType: if features is not None: manifest['featurebits'] = features + if self.custom_msgs is not None: + manifest['custommessages'] = self.custom_msgs + return manifest def _init(self, options: Dict[str, JSONType], diff --git a/tests/plugins/allow_even_msgs.py b/tests/plugins/allow_even_msgs.py new file mode 100755 index 000000000000..b45c110d2b3b --- /dev/null +++ b/tests/plugins/allow_even_msgs.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +from pyln.client import Plugin + +plugin = Plugin(custom_msgs=[43690]) + + +@plugin.hook('custommsg') +def on_custommsg(peer_id, payload, plugin, message=None, **kwargs): + plugin.log("Got message {}".format(int(payload[:4], 16))) + return {'result': 'continue'} + + +plugin.run() diff --git a/tests/test_misc.py b/tests/test_misc.py index ee59d5b7fa04..9d39f26bc15a 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -3626,3 +3626,35 @@ def test_setconfig(node_factory, bitcoind): assert lines[1].startswith('# Inserted by setconfig ') assert lines[2] == 'min-capacity-sat=400000' assert len(lines) == 3 + + +def test_even_sendcustommsg(node_factory): + l1, l2 = node_factory.get_nodes(2, opts={'log-level': 'io'}) + l1.connect(l2) + + # Even-numbered message + msg = hex(43690)[2:] + ('ff' * 30) + 'bb' + + # l2 will hang up when it gets this. + l1.rpc.sendcustommsg(l2.info['id'], msg) + l2.daemon.wait_for_log(r'\[IN\] {}'.format(msg)) + l1.daemon.wait_for_log('Invalid unknown even msg') + wait_for(lambda: l1.rpc.listpeers(l2.info['id'])['peers'] == []) + + # Now with a plugin which allows it + l1.connect(l2) + l2.rpc.plugin_start(os.path.join(os.getcwd(), "tests/plugins/allow_even_msgs.py")) + + l1.rpc.sendcustommsg(l2.info['id'], msg) + l2.daemon.wait_for_log(r'\[IN\] {}'.format(msg)) + l2.daemon.wait_for_log(r'allow_even_msgs.*Got message 43690') + + # And nobody gets upset + assert only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['connected'] + + # It does if we remove the plugin though! + l2.rpc.plugin_stop("allow_even_msgs.py") + l1.rpc.sendcustommsg(l2.info['id'], msg) + l2.daemon.wait_for_log(r'\[IN\] {}'.format(msg)) + l1.daemon.wait_for_log('Invalid unknown even msg') + wait_for(lambda: l1.rpc.listpeers(l2.info['id'])['peers'] == [])