mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 09:54:16 +01:00
75362d21c5
Our gossmap_store uncompresser generates nodeids with well-known privkeys, so we can decrypt and respond to HTLCs sent to such nodes. By replacing channeld with a fake, we can connect a node to another node, but then once the channel is established, allow payments to be sent into the generated network, and respond appropriately. This minimal version handles MPP timeouts, but doesn't insert any delays or runtime capacity for channels. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-None: Testing only
135 lines
5.8 KiB
Python
135 lines
5.8 KiB
Python
from fixtures import * # noqa: F401,F403
|
|
from fixtures import TEST_NETWORK
|
|
from pyln.client import RpcError
|
|
from utils import (
|
|
TIMEOUT, first_scid, GenChannel, generate_gossip_store
|
|
)
|
|
|
|
import os
|
|
import pytest
|
|
import subprocess
|
|
from hashlib import sha256
|
|
|
|
|
|
def test_pay_fakenet(node_factory):
|
|
hash1 = sha256(bytes.fromhex('00' + '00' * 31)).hexdigest()
|
|
hash2 = sha256(bytes.fromhex('01' + '00' * 31)).hexdigest()
|
|
failhash = '00' * 32
|
|
|
|
# Create gossip map of channels from l2 (aka nodemap[0])
|
|
gsfile, nodemap = generate_gossip_store([GenChannel(0, 1, capacity_sats=100_000),
|
|
GenChannel(1, 2, capacity_sats=100_000),
|
|
GenChannel(2, 3, capacity_sats=200_000)],
|
|
nodemap={0: '022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59'})
|
|
|
|
# l2 will warn l1 about its invalid gossip: ignore.
|
|
l1, l2 = node_factory.line_graph(2,
|
|
opts=[{'gossip_store_file': gsfile.name,
|
|
'subdaemon': 'channeld:../tests/plugins/channeld_fakenet',
|
|
'allow_warning': 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)
|
|
|
|
# Failure from final (unknown payment hash)
|
|
l1.rpc.sendpay(route=[{'id': l2.info['id'],
|
|
'channel': first_scid(l1, l2),
|
|
'delay': 18 + 6,
|
|
'amount_msat': 1000001},
|
|
{'id': nodemap[1],
|
|
'channel': '0x1x0',
|
|
'delay': 18,
|
|
'amount_msat': 100000}],
|
|
payment_hash=failhash)
|
|
|
|
with pytest.raises(RpcError, match="WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS") as err:
|
|
l1.rpc.waitsendpay(payment_hash=failhash, timeout=TIMEOUT)
|
|
|
|
assert err.value.error['data']['erring_node'] == nodemap[1]
|
|
|
|
# Success from final (known payment hash)
|
|
l1.rpc.sendpay(route=[{'id': l2.info['id'],
|
|
'channel': first_scid(l1, l2),
|
|
'delay': 18 + 6,
|
|
'amount_msat': 1000001},
|
|
{'id': nodemap[1],
|
|
'channel': '0x1x0',
|
|
'delay': 18,
|
|
'amount_msat': 100000}],
|
|
payment_hash=hash1)
|
|
l1.rpc.waitsendpay(payment_hash=hash1, timeout=TIMEOUT)
|
|
|
|
# Failure from node 2 (unknown scid)
|
|
l1.rpc.sendpay(route=[{'id': l2.info['id'],
|
|
'channel': first_scid(l1, l2),
|
|
'delay': 18 + 6 + 6,
|
|
'amount_msat': 1000002},
|
|
{'id': nodemap[1],
|
|
'channel': '0x1x0',
|
|
'delay': 18 + 6,
|
|
'amount_msat': 1000001},
|
|
{'id': nodemap[2],
|
|
'channel': '1x1x0',
|
|
'delay': 18,
|
|
'amount_msat': 1000000},
|
|
{'id': nodemap[3],
|
|
'channel': '0x1x0',
|
|
'delay': 18,
|
|
'amount_msat': 100000}],
|
|
payment_hash=failhash)
|
|
|
|
with pytest.raises(RpcError, match="WIRE_UNKNOWN_NEXT_PEER"):
|
|
l1.rpc.waitsendpay(payment_hash=failhash, timeout=TIMEOUT)
|
|
|
|
# MPP test
|
|
l1.rpc.sendpay(partid=1,
|
|
amount_msat=200000,
|
|
route=[{'id': l2.info['id'],
|
|
'channel': first_scid(l1, l2),
|
|
'delay': 18 + 6,
|
|
'amount_msat': 1000001},
|
|
{'id': nodemap[1],
|
|
'channel': '0x1x0',
|
|
'delay': 18,
|
|
'amount_msat': 100000}],
|
|
payment_hash=hash2,
|
|
payment_secret=hash2)
|
|
with pytest.raises(RpcError, match="WIRE_MPP_TIMEOUT"):
|
|
l1.rpc.waitsendpay(payment_hash=hash2, timeout=60 + TIMEOUT, partid=1)
|
|
|
|
# This one will actually work.
|
|
l1.rpc.sendpay(partid=2,
|
|
groupid=2,
|
|
amount_msat=200000,
|
|
route=[{'id': l2.info['id'],
|
|
'channel': first_scid(l1, l2),
|
|
'delay': 18 + 6,
|
|
'amount_msat': 1000001},
|
|
{'id': nodemap[1],
|
|
'channel': '0x1x0',
|
|
'delay': 18,
|
|
'amount_msat': 100000}],
|
|
payment_hash=hash2,
|
|
payment_secret=hash2)
|
|
|
|
l1.rpc.sendpay(partid=3,
|
|
groupid=2,
|
|
amount_msat=200000,
|
|
route=[{'id': l2.info['id'],
|
|
'channel': first_scid(l1, l2),
|
|
'delay': 18 + 6,
|
|
'amount_msat': 1000001},
|
|
{'id': nodemap[1],
|
|
'channel': '0x1x0',
|
|
'delay': 18,
|
|
'amount_msat': 100000}],
|
|
payment_hash=hash2,
|
|
payment_secret=hash2)
|
|
|
|
l1.rpc.waitsendpay(payment_hash=hash2, timeout=TIMEOUT, partid=2)
|
|
l1.rpc.waitsendpay(payment_hash=hash2, timeout=TIMEOUT, partid=3)
|