diff --git a/resources/images/commander/Dockerfile b/resources/images/commander/Dockerfile index 4a4744717..4d526b0a9 100644 --- a/resources/images/commander/Dockerfile +++ b/resources/images/commander/Dockerfile @@ -3,3 +3,4 @@ FROM python:3.12-slim # Python dependencies RUN pip install --no-cache-dir kubernetes +RUN pip install --no-cache-dir pyln-proto \ No newline at end of file diff --git a/resources/scenarios/test_scenarios/pyln_connect.py b/resources/scenarios/test_scenarios/pyln_connect.py new file mode 100644 index 000000000..e089977a6 --- /dev/null +++ b/resources/scenarios/test_scenarios/pyln_connect.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 + +from io import BytesIO + +from commander import Commander +from pyln.proto.message import Message, MessageNamespace +from pyln.proto.wire import PrivateKey, PublicKey, connect + + +class PyLNConnect(Commander): + def set_test_params(self): + self.num_nodes = 0 + + def run_test(self): + ln = self.lns["tank-0000-ln"] + ln.createrune() + uri = ln.uri() + pk, host = uri.split("@") + host, port = host.split(":") + + ls_privkey = PrivateKey( + bytes.fromhex("1111111111111111111111111111111111111111111111111111111111111111") + ) + remote_pubkey = PublicKey(bytes.fromhex(pk)) + + lc = connect(ls_privkey, remote_pubkey, host, port) + + # Send an init message, with no global features, and 0b10101010 as local + # features. + # From BOLT1: + # type: 16 (init) + # data: + # [u16:gflen] + # [gflen*byte:globalfeatures] + # [u16:flen] + # [flen*byte:features] + # [init_tlvs:tlvs] + lc.send_message(b"\x00\x10\x00\x00\x00\x01\xaa") + + # Import the BOLT#1 init message namesapce + ns = MessageNamespace( + [ + "msgtype,init,16", + "msgdata,init,gflen,u16,", + "msgdata,init,globalfeatures,byte,gflen", + "msgdata,init,flen,u16,", + "msgdata,init,features,byte,flen", + ] + ) + # read reply from peer + msg = lc.read_message() + self.log.info(f"Got message bytes: {msg.hex()}") + # interpret reply from peer + stream = BytesIO(msg) + msg = Message.read(ns, stream) + self.log.info(f"Decoded message type: {msg.messagetype} content: {msg.to_py()}") + + +def main(): + PyLNConnect().main() + + +if __name__ == "__main__": + main() diff --git a/test/ln_basic_test.py b/test/ln_basic_test.py index 8e9f4dd2f..068d7ea71 100755 --- a/test/ln_basic_test.py +++ b/test/ln_basic_test.py @@ -34,6 +34,9 @@ def run_test(self): # Wait for all nodes to wake up. ln_init will start automatically self.setup_network() + # Test pyln-proto package in scenario + self.test_pyln_scenario() + # Test manually configured macroons self.test_admin_macaroons() @@ -56,6 +59,12 @@ def setup_network(self): self.log.info("Setting up network") stream_command(f"warnet deploy {self.network_dir}") + def test_pyln_scenario(self): + self.log.info("Running pyln_connect scenario") + scenario_file = self.scen_dir / "test_scenarios" / "pyln_connect.py" + self.log.info(f"Running scenario from: {scenario_file}") + stream_command(f"warnet run {scenario_file} --source_dir={self.scen_dir} --debug") + def test_admin_macaroons(self): self.log.info("Testing lnd nodes with same macaroon root key can query each other") # These tanks all use the same default macaroon root key, meaning the macaroons