Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions resources/charts/bitcoincore/charts/cln/templates/pod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
10 changes: 10 additions & 0 deletions resources/charts/bitcoincore/charts/cln/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
20 changes: 13 additions & 7 deletions resources/scenarios/ln_framework/ln.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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,
Expand Down Expand Up @@ -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"))
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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")
Expand Down
3 changes: 3 additions & 0 deletions test/data/ln/network.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ nodes:
- name: tank-0000
addnode:
- tank-0001
ln:
lnd: false
cln: true
- name: tank-0001
addnode:
- tank-0002
Expand Down
51 changes: 35 additions & 16 deletions test/ln_basic_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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()
Expand All @@ -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}"
Expand All @@ -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)
Expand All @@ -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 (
Expand Down
Loading