pytest: test xpay with channeld_fakenet to pay top 100 nodes.

We also put broken status messages for invalid CLTVs and amounts in onions,
to catch them in CI.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-11-17 16:13:06 +10:30
parent e38ef42041
commit 06a9aa8907
2 changed files with 64 additions and 0 deletions

View File

@ -767,6 +767,11 @@ found_next:
fmt_short_channel_id_dir(tmpctx, &scidd));
}
if (payload->outgoing_cltv + c->half[scidd.dir].delay < cltv_expiry) {
status_broken("%s: incoming cltv %u (delay=%u), but outgoing %u",
fmt_short_channel_id_dir(tmpctx, &scidd),
cltv_expiry,
c->half[scidd.dir].delay,
payload->outgoing_cltv);
fail(info, htlc, payload, WIRE_INCORRECT_CLTV_EXPIRY);
return;
}
@ -776,6 +781,13 @@ found_next:
c->half[scidd.dir].proportional_fee))
abort();
if (amount_msat_less(amount, amt_expected)) {
status_broken("%s: expected %s (base=%u, prop=%u), but got %s to fwd %s",
fmt_short_channel_id_dir(tmpctx, &scidd),
fmt_amount_msat(tmpctx, amt_expected),
c->half[scidd.dir].base_fee,
c->half[scidd.dir].proportional_fee,
fmt_amount_msat(tmpctx, amount),
fmt_amount_msat(tmpctx, payload->amt_to_forward));
fail(info, htlc, payload, WIRE_FEE_INSUFFICIENT);
return;
}

View File

@ -8,7 +8,10 @@ from utils import (
import os
import pytest
import subprocess
import sys
from hashlib import sha256
import tempfile
import unittest
def test_pay_fakenet(node_factory):
@ -194,3 +197,52 @@ def test_xpay_simple(node_factory):
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
with pytest.raises(RpcError, match="Already paid"):
l1.rpc.xpay(b11_paid)
@pytest.mark.slow_test
@unittest.skipIf(TEST_NETWORK != 'regtest', '29-way split for node 17 is too dusty on elements')
def test_xpay_fake_channeld(node_factory, bitcoind, chainparams):
outfile = tempfile.NamedTemporaryFile(prefix='gossip-store-')
nodeids = subprocess.check_output(['devtools/gossmap-compress',
'decompress',
'--node-map=3301=022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59',
'tests/data/gossip-store-2024-09-22.compressed',
outfile.name]).decode('utf-8').splitlines()
AMOUNT = 100_000_000
# l2 will warn l1 about its invalid gossip: ignore.
# We throttle l1's gossip to avoid massive log spam.
l1, l2 = node_factory.line_graph(2,
# This is in sats, so 1000x amount we send.
fundamount=AMOUNT,
opts=[{'gossip_store_file': outfile.name,
'subdaemon': 'channeld:../tests/plugins/channeld_fakenet',
'allow_warning': True,
'dev-throttle-gossip': None},
{'allow_bad_gossip': True}])
# l1 needs to know l2's shaseed for the channel so it can make revocations
hsmfile = os.path.join(l2.daemon.lightning_dir, TEST_NETWORK, "hsm_secret")
# Needs peer node id and channel dbid (1, it's the first channel), prints out:
# "shaseed: xxxxxxx\n"
shaseed = subprocess.check_output(["tools/hsmtool", "dumpcommitments", l1.info['id'], "1", "0", hsmfile]).decode('utf-8').strip().partition(": ")[2]
l1.rpc.dev_peer_shachain(l2.info['id'], shaseed)
for n in range(0, 100):
if n in (62, 76, 80, 97):
continue
print(f"PAYING Node #{n}")
preimage_hex = bytes([n]).hex() + '00' * 31
hash_hex = sha256(bytes.fromhex(preimage_hex)).hexdigest()
inv = subprocess.check_output(["devtools/bolt11-cli",
"encode",
n.to_bytes(length=8, byteorder=sys.byteorder).hex() + '01' * 24,
f"currency={chainparams['bip173_prefix']}",
f"p={hash_hex}",
f"s={'00' * 32}",
f"d=Paying node {n}",
f"amount={AMOUNT}msat"]).decode('utf-8').strip()
assert l1.rpc.decode(inv)['payee'] == nodeids[n]
l1.rpc.xpay(inv)