pyln-testing: add gossip_store_file arg to get_node()

This makes it much easier to use generated gossip_store files.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-09-18 17:07:27 +09:30
parent 5ea049ea12
commit e90be8d957
2 changed files with 23 additions and 37 deletions

View file

@ -1582,7 +1582,7 @@ class NodeFactory(object):
def get_node(self, node_id=None, options=None, dbfile=None, def get_node(self, node_id=None, options=None, dbfile=None,
bkpr_dbfile=None, feerates=(15000, 11000, 7500, 3750), bkpr_dbfile=None, feerates=(15000, 11000, 7500, 3750),
start=True, wait_for_bitcoind_sync=True, may_fail=False, start=True, wait_for_bitcoind_sync=True, may_fail=False,
expect_fail=False, cleandir=True, **kwargs): expect_fail=False, cleandir=True, gossip_store_file=None, **kwargs):
node_id = self.get_node_id() if not node_id else node_id node_id = self.get_node_id() if not node_id else node_id
port = reserve_unused_port() port = reserve_unused_port()
@ -1621,6 +1621,10 @@ class NodeFactory(object):
with lzma.open(os.path.join('tests/data', bkpr_dbfile), 'rb') as f: with lzma.open(os.path.join('tests/data', bkpr_dbfile), 'rb') as f:
out.write(f.read()) out.write(f.read())
if gossip_store_file:
shutil.copy(gossip_store_file, os.path.join(node.daemon.lightning_dir, TEST_NETWORK,
'gossip_store'))
if start: if start:
try: try:
node.start(wait_for_bitcoind_sync) node.start(wait_for_bitcoind_sync)

View file

@ -2,12 +2,10 @@ from fixtures import * # noqa: F401,F403
from pyln.client import RpcError from pyln.client import RpcError
from utils import ( from utils import (
only_one, first_scid, GenChannel, generate_gossip_store, only_one, first_scid, GenChannel, generate_gossip_store,
TEST_NETWORK, sync_blockheight, wait_for sync_blockheight, wait_for
) )
import os
import pytest import pytest
import time import time
import shutil
def test_layers(node_factory): def test_layers(node_factory):
@ -152,7 +150,6 @@ def check_getroute_paths(node,
def test_getroutes(node_factory): def test_getroutes(node_factory):
"""Test getroutes call""" """Test getroutes call"""
l1 = node_factory.get_node(start=False)
gsfile, nodemap = generate_gossip_store([GenChannel(0, 1, forward=GenChannel.Half(propfee=10000)), gsfile, nodemap = generate_gossip_store([GenChannel(0, 1, forward=GenChannel.Half(propfee=10000)),
GenChannel(0, 2, capacity_sats=9000), GenChannel(0, 2, capacity_sats=9000),
GenChannel(1, 3, forward=GenChannel.Half(propfee=20000)), GenChannel(1, 3, forward=GenChannel.Half(propfee=20000)),
@ -160,8 +157,7 @@ def test_getroutes(node_factory):
GenChannel(2, 4, forward=GenChannel.Half(delay=2000))]) GenChannel(2, 4, forward=GenChannel.Half(delay=2000))])
# Set up l1 with this as the gossip_store # Set up l1 with this as the gossip_store
shutil.copy(gsfile.name, os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, 'gossip_store')) l1 = node_factory.get_node(gossip_store_file=gsfile.name)
l1.start()
# Start easy # Start easy
assert l1.rpc.getroutes(source=nodemap[0], assert l1.rpc.getroutes(source=nodemap[0],
@ -258,7 +254,6 @@ def test_getroutes(node_factory):
def test_getroutes_fee_fallback(node_factory): def test_getroutes_fee_fallback(node_factory):
"""Test getroutes call takes into account fees, if excessive""" """Test getroutes call takes into account fees, if excessive"""
l1 = node_factory.get_node(start=False)
# 0 -> 1 -> 3: high capacity, high fee (1%) # 0 -> 1 -> 3: high capacity, high fee (1%)
# 0 -> 2 -> 3: low capacity, low fee. # 0 -> 2 -> 3: low capacity, low fee.
gsfile, nodemap = generate_gossip_store([GenChannel(0, 1, gsfile, nodemap = generate_gossip_store([GenChannel(0, 1,
@ -272,8 +267,7 @@ def test_getroutes_fee_fallback(node_factory):
GenChannel(2, 3, GenChannel(2, 3,
capacity_sats=10000)]) capacity_sats=10000)])
# Set up l1 with this as the gossip_store # Set up l1 with this as the gossip_store
shutil.copy(gsfile.name, os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, 'gossip_store')) l1 = node_factory.get_node(gossip_store_file=gsfile.name)
l1.start()
# Don't hit maxfee? Go easy path. # Don't hit maxfee? Go easy path.
check_getroute_paths(l1, check_getroute_paths(l1,
@ -296,7 +290,6 @@ def test_getroutes_fee_fallback(node_factory):
def test_getroutes_auto_sourcefree(node_factory): def test_getroutes_auto_sourcefree(node_factory):
"""Test getroutes call with auto.sourcefree layer""" """Test getroutes call with auto.sourcefree layer"""
l1 = node_factory.get_node(start=False)
gsfile, nodemap = generate_gossip_store([GenChannel(0, 1, forward=GenChannel.Half(propfee=10000)), gsfile, nodemap = generate_gossip_store([GenChannel(0, 1, forward=GenChannel.Half(propfee=10000)),
GenChannel(0, 2, capacity_sats=9000), GenChannel(0, 2, capacity_sats=9000),
GenChannel(1, 3, forward=GenChannel.Half(propfee=20000)), GenChannel(1, 3, forward=GenChannel.Half(propfee=20000)),
@ -304,8 +297,7 @@ def test_getroutes_auto_sourcefree(node_factory):
GenChannel(2, 4, forward=GenChannel.Half(delay=2000))]) GenChannel(2, 4, forward=GenChannel.Half(delay=2000))])
# Set up l1 with this as the gossip_store # Set up l1 with this as the gossip_store
shutil.copy(gsfile.name, os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, 'gossip_store')) l1 = node_factory.get_node(gossip_store_file=gsfile.name)
l1.start()
# Start easy # Start easy
assert l1.rpc.getroutes(source=nodemap[0], assert l1.rpc.getroutes(source=nodemap[0],
@ -371,23 +363,20 @@ def test_getroutes_auto_sourcefree(node_factory):
def test_getroutes_auto_localchans(node_factory): def test_getroutes_auto_localchans(node_factory):
"""Test getroutes call with auto.localchans layer""" """Test getroutes call with auto.localchans layer"""
# We get bad signature warnings, since our gossip is made up! l1 = node_factory.get_node()
l1, l2 = node_factory.get_nodes(2, opts={'allow_warning': True})
gsfile, nodemap = generate_gossip_store([GenChannel(0, 1, forward=GenChannel.Half(propfee=10000)), gsfile, nodemap = generate_gossip_store([GenChannel(0, 1, forward=GenChannel.Half(propfee=10000)),
GenChannel(1, 2, forward=GenChannel.Half(propfee=10000))], GenChannel(1, 2, forward=GenChannel.Half(propfee=10000))],
nodemap={0: l2.info['id']}) nodemap={0: l1.info['id']})
# Set up l1 with this as the gossip_store # We get bad signature warnings, since our gossip is made up!
l1.stop() l2 = node_factory.get_node(allow_warning=True, gossip_store_file=gsfile.name)
shutil.copy(gsfile.name, os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, 'gossip_store'))
l1.start()
# Now l1 beleives l2 has an entire network behind it. # Now l2 believes l1 has an entire network behind it.
scid12, _ = l1.fundchannel(l2, 10**6, announce_channel=False) scid12, _ = l2.fundchannel(l1, 10**6, announce_channel=False)
# Cannot find a route unless we use local hints. # Cannot find a route unless we use local hints.
with pytest.raises(RpcError, match="Unknown source node {}".format(l1.info['id'])): with pytest.raises(RpcError, match="Unknown source node {}".format(l2.info['id'])):
l1.rpc.getroutes(source=l1.info['id'], l2.rpc.getroutes(source=l2.info['id'],
destination=nodemap[2], destination=nodemap[2],
amount_msat=100000, amount_msat=100000,
layers=[], layers=[],
@ -395,8 +384,8 @@ def test_getroutes_auto_localchans(node_factory):
final_cltv=99) final_cltv=99)
# This should work # This should work
check_getroute_paths(l1, check_getroute_paths(l2,
l1.info['id'], l2.info['id'],
nodemap[2], nodemap[2],
100000, 100000,
maxfee_msat=100000, maxfee_msat=100000,
@ -406,8 +395,8 @@ def test_getroutes_auto_localchans(node_factory):
{'short_channel_id': '1x2x1', 'amount_msat': 101000, 'delay': 99 + 6}]]) {'short_channel_id': '1x2x1', 'amount_msat': 101000, 'delay': 99 + 6}]])
# This should get self-discount correct # This should get self-discount correct
check_getroute_paths(l1, check_getroute_paths(l2,
l1.info['id'], l2.info['id'],
nodemap[2], nodemap[2],
100000, 100000,
maxfee_msat=100000, maxfee_msat=100000,
@ -418,8 +407,6 @@ def test_getroutes_auto_localchans(node_factory):
def test_fees_dont_exceed_constraints(node_factory): def test_fees_dont_exceed_constraints(node_factory):
l1 = node_factory.get_node(start=False)
msat = 100000000 msat = 100000000
max_msat = int(msat * 0.45) max_msat = int(msat * 0.45)
# 0 has to use two paths (1 and 2) to reach 3. But we tell it 0->1 has limited capacity. # 0 has to use two paths (1 and 2) to reach 3. But we tell it 0->1 has limited capacity.
@ -429,8 +416,7 @@ def test_fees_dont_exceed_constraints(node_factory):
GenChannel(2, 3, capacity_sats=msat // 1000, forward=GenChannel.Half(propfee=10000))]) GenChannel(2, 3, capacity_sats=msat // 1000, forward=GenChannel.Half(propfee=10000))])
# Set up l1 with this as the gossip_store # Set up l1 with this as the gossip_store
shutil.copy(gsfile.name, os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, 'gossip_store')) l1 = node_factory.get_node(gossip_store_file=gsfile.name)
l1.start()
chan = only_one([c for c in l1.rpc.listchannels(source=nodemap[0])['channels'] if c['destination'] == nodemap[1]]) chan = only_one([c for c in l1.rpc.listchannels(source=nodemap[0])['channels'] if c['destination'] == nodemap[1]])
l1.rpc.askrene_inform_channel(layer='test_layers', l1.rpc.askrene_inform_channel(layer='test_layers',
@ -514,8 +500,6 @@ def test_live_spendable(node_factory, bitcoind):
def test_limits_fake_gossmap(node_factory, bitcoind): def test_limits_fake_gossmap(node_factory, bitcoind):
"""Like test_live_spendable, but using a generated gossmap not real nodes""" """Like test_live_spendable, but using a generated gossmap not real nodes"""
l1 = node_factory.get_node(start=False)
gsfile, nodemap = generate_gossip_store([GenChannel(0, 1, capacity_sats=100_000), gsfile, nodemap = generate_gossip_store([GenChannel(0, 1, capacity_sats=100_000),
GenChannel(0, 1, capacity_sats=100_000), GenChannel(0, 1, capacity_sats=100_000),
GenChannel(0, 1, capacity_sats=200_000), GenChannel(0, 1, capacity_sats=200_000),
@ -526,9 +510,7 @@ def test_limits_fake_gossmap(node_factory, bitcoind):
GenChannel(1, 2, capacity_sats=200_000), GenChannel(1, 2, capacity_sats=200_000),
GenChannel(1, 2, capacity_sats=300_000), GenChannel(1, 2, capacity_sats=300_000),
GenChannel(1, 2, capacity_sats=400_000)]) GenChannel(1, 2, capacity_sats=400_000)])
l1 = node_factory.get_node(gossip_store_file=gsfile.name)
shutil.copy(gsfile.name, os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, 'gossip_store'))
l1.start()
# Create a layer like auto.localchans would from "spendable" # Create a layer like auto.localchans would from "spendable"
spendable = {'0x1x0/1': 87718000, spendable = {'0x1x0/1': 87718000,