diff --git a/resources/charts/bitcoincore/charts/cln/templates/pod.yaml b/resources/charts/bitcoincore/charts/cln/templates/pod.yaml index b2d651173..59d212d0e 100644 --- a/resources/charts/bitcoincore/charts/cln/templates/pod.yaml +++ b/resources/charts/bitcoincore/charts/cln/templates/pod.yaml @@ -40,13 +40,7 @@ spec: command: - /bin/sh - -c - - | - lightningd --conf=/root/.lightning/config & - sleep 1 - lightning-cli createrune > /working/rune.json - echo "Here is the rune file contents" - cat /working/rune.json - wait + - lightningd --conf=/root/.lightning/config livenessProbe: {{- toYaml .Values.livenessProbe | nindent 8 }} readinessProbe: diff --git a/resources/charts/bitcoincore/charts/cln/values.yaml b/resources/charts/bitcoincore/charts/cln/values.yaml index d34144100..eaae7d2a3 100644 --- a/resources/charts/bitcoincore/charts/cln/values.yaml +++ b/resources/charts/bitcoincore/charts/cln/values.yaml @@ -71,6 +71,16 @@ readinessProbe: - "/bin/sh" - "-c" - "lightning-cli getinfo 2>/dev/null | grep -q 'id' || exit 1" +startupProbe: + failureThreshold: 10 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 60 + exec: + command: + - "/bin/sh" + - "-c" + - "lightning-cli createrune > /working/rune.json" # Additional volumes on the output Deployment definition. volumes: diff --git a/resources/scenarios/ln_framework/ln.py b/resources/scenarios/ln_framework/ln.py index f11c28cbf..68039ae74 100644 --- a/resources/scenarios/ln_framework/ln.py +++ b/resources/scenarios/ln_framework/ln.py @@ -161,7 +161,7 @@ def __init__(self, pod_name, ip_address): def reset_connection(self): self.conn = http.client.HTTPSConnection( - host=self.name, port=3010, timeout=5, context=INSECURE_CONTEXT + host=self.name, port=3010, timeout=60, context=INSECURE_CONTEXT ) def setRune(self, rune): @@ -185,7 +185,6 @@ def post(self, uri, data=None): post_header["Content-Length"] = str(len(body)) post_header["Content-Type"] = "application/json" self.reset_connection() - self.log.info(f"CLN POST headers: {post_header}") self.conn.request( method="POST", url=uri, @@ -220,9 +219,11 @@ def createrune(self): def newaddress(self): self.createrune() - response = self.post("/v1/newaddr") + response = self.post("/v1/newaddr", data={"addresstype": "p2tr"}) res = json.loads(response) - return res["bech32"] + if "p2tr" in res: + return res["p2tr"] + raise Exception(res) def uri(self): res = json.loads(self.post("/v1/getinfo")) @@ -298,7 +299,7 @@ def __init__(self, pod_name, ip_address, admin_macaroon_hex): def reset_connection(self): self.conn = http.client.HTTPSConnection( - host=self.name, port=8080, timeout=5, context=INSECURE_CONTEXT + host=self.name, port=8080, timeout=60, context=INSECURE_CONTEXT ) def get(self, uri): @@ -337,9 +338,14 @@ def post(self, uri, data): return stream def newaddress(self): - response = self.get("/v1/newaddress") + # Taproot signatures are a fixed length which improves + # the accuracy of fee estimation, and therefore our + # channel ID determinism. + response = self.get("/v1/newaddress?type=TAPROOT_PUBKEY") res = json.loads(response) - return res["address"] + if "address" in res: + return res["address"] + raise Exception(res) def walletbalance(self) -> int: res = self.get("/v1/balance/blockchain") diff --git a/test/data/ln/network.yaml b/test/data/ln/network.yaml index e0761f8f5..a5e10ad7c 100644 --- a/test/data/ln/network.yaml +++ b/test/data/ln/network.yaml @@ -2,6 +2,9 @@ nodes: - name: tank-0000 addnode: - tank-0001 + ln: + lnd: false + cln: true - name: tank-0001 addnode: - tank-0002 diff --git a/test/ln_basic_test.py b/test/ln_basic_test.py index d21e1a45d..64d6d2d03 100755 --- a/test/ln_basic_test.py +++ b/test/ln_basic_test.py @@ -61,28 +61,24 @@ def test_admin_macaroons(self): # These tanks all use the same default macaroon root key, meaning the macaroons # generated at ~/.lnd/.../admin.macaroon in each lnd container are authorized # to make requests to each other. - info = json.loads( - self.warnet("ln rpc tank-0000-ln --rpcserver=tank-0001-ln.default:10009 getinfo") - ) - info["alias"] = "tank-0001-ln" info = json.loads( self.warnet("ln rpc tank-0001-ln --rpcserver=tank-0002-ln.default:10009 getinfo") ) - info["alias"] = "tank-0002-ln" + assert info["alias"] == "tank-0002-ln" info = json.loads( self.warnet("ln rpc tank-0002-ln --rpcserver=tank-0005-ln.default:10009 getinfo") ) - info["alias"] = "tank-0005-ln" + assert info["alias"] == "tank-0005-ln" self.log.info("Testing lnd nodes with unique macaroon root key can NOT query each other") # These tanks are configured with unique macaroon root keys try: - self.warnet("ln rpc tank-0000-ln --rpcserver=tank-0003-ln.default:10009 getinfo") + self.warnet("ln rpc tank-0001-ln --rpcserver=tank-0003-ln.default:10009 getinfo") raise AssertionError("That should not have worked!") except Exception as e: assert "verification failed: signature mismatch after caveat verification" in str(e) try: - self.warnet("ln rpc tank-0000-ln --rpcserver=tank-0004-ln.default:10009 getinfo") + self.warnet("ln rpc tank-0001-ln --rpcserver=tank-0004-ln.default:10009 getinfo") raise AssertionError("That should not have worked!") except Exception as e: assert "verification failed: signature mismatch after caveat verification" in str(e) @@ -94,13 +90,27 @@ def test_admin_macaroons(self): def fund_wallets(self): for ln in self.lns: - addr = json.loads(self.warnet(f"ln rpc {ln} newaddress p2wkh"))["address"] + if ln == "tank-0000-ln": + # cln + addr = json.loads(self.warnet(f"ln rpc {ln} newaddr p2tr"))["p2tr"] + else: + # lnd + addr = json.loads(self.warnet(f"ln rpc {ln} newaddress p2tr"))["address"] self.warnet(f"bitcoin rpc tank-0000 sendtoaddress {addr} 10") self.wait_for_predicate( lambda: json.loads(self.warnet("bitcoin rpc tank-0000 getmempoolinfo"))["size"] == len(self.lns) ) self.warnet("bitcoin rpc tank-0000 -generate 1") + # cln takes a long time to register its own balance? + self.wait_for_predicate( + lambda: len( + json.loads(self.warnet("ln rpc tank-0000-ln bkpr-listbalances"))["accounts"][0][ + "balances" + ] + ) + > 0 + ) def manual_open_channels(self): self.fund_wallets() @@ -118,11 +128,9 @@ def manual_open_channels(self): host2 = self.warnet("ln host tank-0002-ln") sleep(1) - print( - self.warnet( - f"ln rpc tank-0000-ln openchannel --node_key {pk1} --local_amt 100000 --connect {host1}" - ) - ) + print(self.warnet(f"ln rpc tank-0000-ln connect {pk1} {host1}")) + print(self.warnet(f"ln rpc tank-0000-ln fundchannel {pk1} 100000")) + print( self.warnet( f"ln rpc tank-0001-ln openchannel --node_key {pk2} --local_amt 100000 --connect {host2}" @@ -138,7 +146,13 @@ def manual_open_channels(self): def wait_for_gossip_sync(self, nodes, expected): while len(nodes) > 0: for node in nodes: - chs = json.loads(self.warnet(f"ln rpc {node} describegraph"))["edges"] + if node == "tank-0000-ln": + # cln + chs = json.loads(self.warnet(f"ln rpc {node} listchannels"))["channels"] + chs = [ch for ch in chs if ch["direction"] == 1] + else: + # lnd + chs = json.loads(self.warnet(f"ln rpc {node} describegraph"))["edges"] if len(chs) >= expected: nodes.remove(node) sleep(1) @@ -147,7 +161,12 @@ def pay_invoice(self, sender: str, recipient: str): init_balance = int(json.loads(self.warnet(f"ln rpc {recipient} channelbalance"))["balance"]) inv = json.loads(self.warnet(f"ln rpc {recipient} addinvoice --amt 1000")) print(inv) - print(self.warnet(f"ln rpc {sender} payinvoice -f {inv['payment_request']}")) + if sender == "tank-0000-ln": + # cln + print(self.warnet(f"ln rpc {sender} pay {inv['payment_request']}")) + else: + # lnd + print(self.warnet(f"ln rpc {sender} payinvoice -f {inv['payment_request']}")) def wait_for_success(): return (