lnworker: split LNWallet and LNWorker: LNWallet "has an" LNWorker
- LNWallet no longer "is-an" LNWorker, instead LNWallet "has-an" LNWorker - the motivation is to make the unit tests nicer, and allow writing unit tests for more things - I hope this makes it possible to e.g. test lnsweep in the unit tests - some stuff we would previously have to write a regtest for, maybe we can write a unit test for, now - in unit tests, MockLNWallet now - inherits LNWallet - the Wallet is no longer being mocked
This commit is contained in:
@@ -10,6 +10,7 @@ from collections import defaultdict
|
||||
import logging
|
||||
import concurrent
|
||||
from concurrent import futures
|
||||
from functools import lru_cache
|
||||
from unittest import mock
|
||||
from typing import Iterable, NamedTuple, Tuple, List, Dict, Sequence
|
||||
from types import MappingProxyType
|
||||
@@ -24,6 +25,7 @@ import electrum.trampoline
|
||||
from electrum import bitcoin
|
||||
from electrum import util
|
||||
from electrum import constants
|
||||
from electrum import bip32
|
||||
from electrum.network import Network
|
||||
from electrum import simple_config, lnutil
|
||||
from electrum.lnaddr import lnencode, LnAddr, lndecode
|
||||
@@ -37,7 +39,7 @@ from electrum.lnutil import Keypair, PaymentFailure, LnFeatures, HTLCOwner, Paym
|
||||
from electrum.lnchannel import ChannelState, PeerState, Channel
|
||||
from electrum.lnrouter import LNPathFinder, PathEdge, LNPathInconsistent
|
||||
from electrum.channel_db import ChannelDB
|
||||
from electrum.lnworker import LNWallet, NoPathFound, SentHtlcInfo, PaySession
|
||||
from electrum.lnworker import LNWallet, NoPathFound, SentHtlcInfo, PaySession, LNPeerManager
|
||||
from electrum.lnmsg import encode_msg, decode_msg
|
||||
from electrum import lnmsg
|
||||
from electrum.logging import console_stderr_handler, Logger
|
||||
@@ -49,10 +51,11 @@ from electrum.interface import GracefulDisconnect
|
||||
from electrum.simple_config import SimpleConfig
|
||||
from electrum.fee_policy import FeeTimeEstimates, FEE_ETA_TARGETS
|
||||
from electrum.mpp_split import split_amount_normal
|
||||
from electrum.wallet import Abstract_Wallet
|
||||
|
||||
from .test_lnchannel import create_test_channels
|
||||
from .test_bitcoin import needs_test_with_all_chacha20_implementations
|
||||
from . import ElectrumTestCase
|
||||
from . import ElectrumTestCase, restore_wallet_from_text__for_unittest
|
||||
|
||||
|
||||
def keypair():
|
||||
@@ -62,9 +65,6 @@ def keypair():
|
||||
privkey=priv)
|
||||
return k1
|
||||
|
||||
@contextmanager
|
||||
def noop_lock():
|
||||
yield
|
||||
|
||||
class MockNetwork:
|
||||
def __init__(self, tx_queue, *, config: SimpleConfig):
|
||||
@@ -120,144 +120,100 @@ class MockADB:
|
||||
def get_local_height(self):
|
||||
return self._blockchain.height()
|
||||
|
||||
class MockWallet:
|
||||
receive_requests = {}
|
||||
adb = MockADB()
|
||||
|
||||
def get_invoice(self, key):
|
||||
pass
|
||||
|
||||
def get_request(self, key):
|
||||
pass
|
||||
|
||||
def get_key_for_receive_request(self, x):
|
||||
pass
|
||||
|
||||
def set_label(self, x, y):
|
||||
pass
|
||||
|
||||
def save_db(self):
|
||||
pass
|
||||
|
||||
def is_lightning_backup(self):
|
||||
return False
|
||||
|
||||
def is_mine(self, addr):
|
||||
return True
|
||||
|
||||
def get_fingerprint(self):
|
||||
return ''
|
||||
|
||||
def get_new_sweep_address_for_channel(self):
|
||||
# note: sweep is not tested here, only in regtest
|
||||
return "tb1qqu5newtapamjchgxf0nty6geuykhvwas45q4q4"
|
||||
|
||||
def is_up_to_date(self):
|
||||
return True
|
||||
|
||||
|
||||
class MockLNGossip:
|
||||
def get_sync_progress_estimate(self):
|
||||
return None, None, None
|
||||
|
||||
|
||||
class MockLNWallet(Logger, EventListener, NetworkRetryManager[LNPeerAddr]):
|
||||
class MockLNPeerManager(LNPeerManager):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
node_keypair,
|
||||
config: SimpleConfig,
|
||||
features: LnFeatures,
|
||||
lnwallet: LNWallet,
|
||||
network: 'MockNetwork',
|
||||
):
|
||||
LNPeerManager.__init__(
|
||||
self,
|
||||
node_keypair=node_keypair,
|
||||
lnwallet_or_lngossip=lnwallet,
|
||||
features=features,
|
||||
config=config,
|
||||
)
|
||||
self.network = network
|
||||
|
||||
|
||||
@lru_cache()
|
||||
def _bip32_from_name(name: str) -> bip32.BIP32Node:
|
||||
# note: unlike a serialized xprv, the bip32 node can be cached easily,
|
||||
# as it does not depend on constant.net (testnet/mainnet) network bytes
|
||||
sequence = [ord(c) for c in name]
|
||||
bip32_node = bip32.BIP32Node.from_rootseed(b"9dk", xtype='standard').subkey_at_private_derivation(sequence)
|
||||
return bip32_node
|
||||
|
||||
|
||||
class MockLNWallet(LNWallet):
|
||||
MPP_EXPIRY = 2 # HTLC timestamps are cast to int, so this cannot be 1
|
||||
PAYMENT_TIMEOUT = 120
|
||||
TIMEOUT_SHUTDOWN_FAIL_PENDING_HTLCS = 0
|
||||
MPP_SPLIT_PART_FRACTION = 1 # this disables the forced splitting
|
||||
MPP_SPLIT_PART_MINAMT_MSAT = 5_000_000
|
||||
|
||||
def __init__(self, *, local_keypair: Keypair, chans: Iterable['Channel'], tx_queue, name, has_anchors):
|
||||
def __init__(self, *, tx_queue, name, has_anchors, ln_xprv: str = None):
|
||||
self.name = name
|
||||
Logger.__init__(self)
|
||||
NetworkRetryManager.__init__(self, max_retry_delay_normal=1, init_retry_delay_normal=1)
|
||||
self.node_keypair = local_keypair
|
||||
self.payment_secret_key = os.urandom(32) # does not need to be deterministic in tests
|
||||
|
||||
self._user_dir = tempfile.mkdtemp(prefix="electrum-lnpeer-test-")
|
||||
self.config = SimpleConfig({}, read_user_dir_function=lambda: self._user_dir)
|
||||
self.network = MockNetwork(tx_queue, config=self.config)
|
||||
self.taskgroup = OldTaskGroup()
|
||||
self.config.ENABLE_ANCHOR_CHANNELS = has_anchors
|
||||
self.config.INITIAL_TRAMPOLINE_FEE_LEVEL = 0
|
||||
|
||||
network = MockNetwork(tx_queue, config=self.config)
|
||||
|
||||
wallet = restore_wallet_from_text__for_unittest(
|
||||
"9dk", path=None, passphrase=name, config=self.config)['wallet'] # type: Abstract_Wallet
|
||||
wallet.is_up_to_date = lambda: True
|
||||
wallet.adb.network = wallet.network = network
|
||||
|
||||
features = LnFeatures(0)
|
||||
features |= LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT
|
||||
features |= LnFeatures.OPTION_UPFRONT_SHUTDOWN_SCRIPT_OPT
|
||||
features |= LnFeatures.VAR_ONION_OPT
|
||||
features |= LnFeatures.PAYMENT_SECRET_OPT
|
||||
features |= LnFeatures.OPTION_TRAMPOLINE_ROUTING_OPT_ELECTRUM
|
||||
features |= LnFeatures.OPTION_CHANNEL_TYPE_OPT
|
||||
features |= LnFeatures.OPTION_SCID_ALIAS_OPT
|
||||
features |= LnFeatures.OPTION_STATIC_REMOTEKEY_OPT
|
||||
|
||||
if ln_xprv is None:
|
||||
ln_xprv = _bip32_from_name(name).to_xprv()
|
||||
LNWallet.__init__(self, wallet=wallet, xprv=ln_xprv, features=features)
|
||||
|
||||
self.lnpeermgr = MockLNPeerManager(
|
||||
node_keypair=self.node_keypair,
|
||||
config=self.config,
|
||||
features=features,
|
||||
lnwallet=self,
|
||||
network=network,
|
||||
)
|
||||
self.lnwatcher = None
|
||||
self.swap_manager = None
|
||||
self.onion_message_manager = None
|
||||
self.listen_server = None
|
||||
self._channels = {chan.channel_id: chan for chan in chans}
|
||||
self.payment_info = {}
|
||||
self.logs = defaultdict(list)
|
||||
self.wallet = MockWallet()
|
||||
self.features = LnFeatures(0)
|
||||
self.features |= LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT
|
||||
self.features |= LnFeatures.OPTION_UPFRONT_SHUTDOWN_SCRIPT_OPT
|
||||
self.features |= LnFeatures.VAR_ONION_OPT
|
||||
self.features |= LnFeatures.PAYMENT_SECRET_OPT
|
||||
self.features |= LnFeatures.OPTION_TRAMPOLINE_ROUTING_OPT_ELECTRUM
|
||||
self.features |= LnFeatures.OPTION_CHANNEL_TYPE_OPT
|
||||
self.features |= LnFeatures.OPTION_SCID_ALIAS_OPT
|
||||
self.features |= LnFeatures.OPTION_STATIC_REMOTEKEY_OPT
|
||||
self.config.ENABLE_ANCHOR_CHANNELS = has_anchors
|
||||
for chan in chans:
|
||||
chan.lnworker = self
|
||||
self._peers = {} # bytes -> Peer
|
||||
# used in tests
|
||||
self.enable_htlc_settle = True
|
||||
self.enable_htlc_forwarding = True
|
||||
self.received_mpp_htlcs = dict()
|
||||
self._paysessions = dict()
|
||||
self.sent_htlcs_info = dict()
|
||||
self.sent_buckets = defaultdict(set)
|
||||
self.active_forwardings = {}
|
||||
self.forwarding_failures = {}
|
||||
self.inflight_payments = set()
|
||||
self._preimages = {}
|
||||
self.stopping_soon = False
|
||||
self.downstream_to_upstream_htlc = {}
|
||||
self.dont_expire_htlcs = {}
|
||||
self.dont_settle_htlcs = {}
|
||||
self.hold_invoice_callbacks = {}
|
||||
self._payment_bundles_pkey_to_canon = {} # type: Dict[bytes, bytes]
|
||||
self._payment_bundles_canon_to_pkeylist = {} # type: Dict[bytes, Sequence[bytes]]
|
||||
self.config.INITIAL_TRAMPOLINE_FEE_LEVEL = 0
|
||||
self._channel_sending_capacity_lock = asyncio.Lock()
|
||||
|
||||
self.logger.info(f"created LNWallet[{name}] with nodeID={local_keypair.pubkey.hex()}")
|
||||
self.logger.info(f"created LNWallet[{name}] with nodeID={self.node_keypair.pubkey.hex()}")
|
||||
|
||||
def clear_invoices_cache(self):
|
||||
pass
|
||||
def _add_channel(self, chan: Channel):
|
||||
self._channels[chan.channel_id] = chan
|
||||
chan.lnworker = self
|
||||
|
||||
def get_invoice_status(self, key):
|
||||
pass
|
||||
|
||||
@property
|
||||
def lock(self):
|
||||
return noop_lock()
|
||||
|
||||
@property
|
||||
def channel_db(self):
|
||||
return self.network.channel_db if self.network else None
|
||||
|
||||
def uses_trampoline(self):
|
||||
return not bool(self.channel_db)
|
||||
|
||||
@property
|
||||
def channels(self):
|
||||
return self._channels
|
||||
|
||||
@property
|
||||
def peers(self):
|
||||
return self._peers
|
||||
|
||||
def get_channel_by_short_id(self, short_channel_id):
|
||||
with self.lock:
|
||||
for chan in self._channels.values():
|
||||
if chan.short_channel_id == short_channel_id:
|
||||
return chan
|
||||
|
||||
def channel_state_changed(self, chan):
|
||||
pass
|
||||
@LNWallet.features.setter
|
||||
def features(self, value):
|
||||
self.lnpeermgr.features = value
|
||||
|
||||
def save_channel(self, chan):
|
||||
print("Ignoring channel save")
|
||||
pass
|
||||
#print("Ignoring channel save")
|
||||
|
||||
def diagnostic_name(self):
|
||||
return self.name
|
||||
@@ -290,69 +246,6 @@ class MockLNWallet(Logger, EventListener, NetworkRetryManager[LNPeerAddr]):
|
||||
budget=PaymentFeeBudget.from_invoice_amount(invoice_amount_msat=amount_msat, config=self.config),
|
||||
)]
|
||||
|
||||
get_payments = LNWallet.get_payments
|
||||
get_payment_secret = LNWallet.get_payment_secret
|
||||
get_payment_info = LNWallet.get_payment_info
|
||||
save_payment_info = LNWallet.save_payment_info
|
||||
set_invoice_status = LNWallet.set_invoice_status
|
||||
set_request_status = LNWallet.set_request_status
|
||||
set_payment_status = LNWallet.set_payment_status
|
||||
get_payment_status = LNWallet.get_payment_status
|
||||
htlc_fulfilled = LNWallet.htlc_fulfilled
|
||||
htlc_failed = LNWallet.htlc_failed
|
||||
save_preimage = LNWallet.save_preimage
|
||||
get_preimage = LNWallet.get_preimage
|
||||
create_route_for_single_htlc = LNWallet.create_route_for_single_htlc
|
||||
create_routes_for_payment = LNWallet.create_routes_for_payment
|
||||
_check_bolt11_invoice = LNWallet._check_bolt11_invoice
|
||||
pay_to_route = LNWallet.pay_to_route
|
||||
pay_to_node = LNWallet.pay_to_node
|
||||
pay_invoice = LNWallet.pay_invoice
|
||||
force_close_channel = LNWallet.force_close_channel
|
||||
schedule_force_closing = LNWallet.schedule_force_closing
|
||||
on_peer_successfully_established = LNWallet.on_peer_successfully_established
|
||||
get_channel_by_id = LNWallet.get_channel_by_id
|
||||
channels_for_peer = LNWallet.channels_for_peer
|
||||
calc_routing_hints_for_invoice = LNWallet.calc_routing_hints_for_invoice
|
||||
get_channels_for_receiving = LNWallet.get_channels_for_receiving
|
||||
handle_error_code_from_failed_htlc = LNWallet.handle_error_code_from_failed_htlc
|
||||
is_trampoline_peer = LNWallet.is_trampoline_peer
|
||||
wait_for_received_pending_htlcs_to_get_removed = LNWallet.wait_for_received_pending_htlcs_to_get_removed
|
||||
#on_event_proxy_set = LNWallet.on_event_proxy_set
|
||||
_decode_channel_update_msg = LNWallet._decode_channel_update_msg
|
||||
_handle_chanupd_from_failed_htlc = LNWallet._handle_chanupd_from_failed_htlc
|
||||
is_forwarded_htlc = LNWallet.is_forwarded_htlc
|
||||
notify_upstream_peer = LNWallet.notify_upstream_peer
|
||||
_force_close_channel = LNWallet._force_close_channel
|
||||
suggest_payment_splits = LNWallet.suggest_payment_splits
|
||||
register_hold_invoice = LNWallet.register_hold_invoice
|
||||
unregister_hold_invoice = LNWallet.unregister_hold_invoice
|
||||
add_payment_info_for_hold_invoice = LNWallet.add_payment_info_for_hold_invoice
|
||||
|
||||
update_or_create_mpp_with_received_htlc = LNWallet.update_or_create_mpp_with_received_htlc
|
||||
set_mpp_resolution = LNWallet.set_mpp_resolution
|
||||
get_mpp_amounts = LNWallet.get_mpp_amounts
|
||||
bundle_payments = LNWallet.bundle_payments
|
||||
get_payment_bundle = LNWallet.get_payment_bundle
|
||||
_get_payment_key = LNWallet._get_payment_key
|
||||
save_forwarding_failure = LNWallet.save_forwarding_failure
|
||||
get_forwarding_failure = LNWallet.get_forwarding_failure
|
||||
maybe_cleanup_forwarding = LNWallet.maybe_cleanup_forwarding
|
||||
current_target_feerate_per_kw = LNWallet.current_target_feerate_per_kw
|
||||
current_low_feerate_per_kw_srk_channel = LNWallet.current_low_feerate_per_kw_srk_channel
|
||||
create_onion_for_route = LNWallet.create_onion_for_route
|
||||
maybe_forward_htlc_set = LNWallet.maybe_forward_htlc_set
|
||||
_maybe_forward_htlc = LNWallet._maybe_forward_htlc
|
||||
_maybe_forward_trampoline = LNWallet._maybe_forward_trampoline
|
||||
_maybe_refuse_to_forward_htlc_that_corresponds_to_payreq_we_created = LNWallet._maybe_refuse_to_forward_htlc_that_corresponds_to_payreq_we_created
|
||||
set_htlc_set_error = LNWallet.set_htlc_set_error
|
||||
is_payment_bundle_complete = LNWallet.is_payment_bundle_complete
|
||||
delete_payment_bundle = LNWallet.delete_payment_bundle
|
||||
_process_htlc_log = LNWallet._process_htlc_log
|
||||
_get_invoice_features = LNWallet._get_invoice_features
|
||||
receive_requires_jit_channel = LNWallet.receive_requires_jit_channel
|
||||
can_get_zeroconf_channel = LNWallet.can_get_zeroconf_channel
|
||||
|
||||
|
||||
class MockTransport:
|
||||
def __init__(self, name):
|
||||
@@ -667,25 +560,24 @@ class TestPeerDirect(TestPeer):
|
||||
|
||||
def prepare_peers(
|
||||
self, alice_channel: Channel, bob_channel: Channel,
|
||||
*, k1: Keypair = None, k2: Keypair = None,
|
||||
):
|
||||
if k1 is None:
|
||||
k1 = keypair()
|
||||
if k2 is None:
|
||||
k2 = keypair()
|
||||
q1, q2 = asyncio.Queue(), asyncio.Queue()
|
||||
w1 = MockLNWallet(tx_queue=q1, name=bob_channel.name, has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
w2 = MockLNWallet(tx_queue=q2, name=alice_channel.name, has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
k1 = w1.node_keypair
|
||||
k2 = w2.node_keypair
|
||||
alice_channel.node_id = k2.pubkey
|
||||
bob_channel.node_id = k1.pubkey
|
||||
alice_channel.storage['node_id'] = alice_channel.node_id
|
||||
bob_channel.storage['node_id'] = bob_channel.node_id
|
||||
t1, t2 = transport_pair(k1, k2, alice_channel.name, bob_channel.name)
|
||||
q1, q2 = asyncio.Queue(), asyncio.Queue()
|
||||
w1 = MockLNWallet(local_keypair=k1, chans=[alice_channel], tx_queue=q1, name=bob_channel.name, has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
w2 = MockLNWallet(local_keypair=k2, chans=[bob_channel], tx_queue=q2, name=alice_channel.name, has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
w1._add_channel(alice_channel)
|
||||
w2._add_channel(bob_channel)
|
||||
self._lnworkers_created.extend([w1, w2])
|
||||
p1 = PeerInTests(w1, k2.pubkey, t1)
|
||||
p2 = PeerInTests(w2, k1.pubkey, t2)
|
||||
w1._peers[p1.pubkey] = p1
|
||||
w2._peers[p2.pubkey] = p2
|
||||
w1.lnpeermgr._peers[p1.pubkey] = p1
|
||||
w2.lnpeermgr._peers[p2.pubkey] = p2
|
||||
# mark_open won't work if state is already OPEN.
|
||||
# so set it to FUNDED
|
||||
alice_channel._state = ChannelState.FUNDED
|
||||
@@ -790,10 +682,9 @@ class TestPeerDirect(TestPeer):
|
||||
----sig-->
|
||||
"""
|
||||
chan_AB, chan_BA = create_test_channels()
|
||||
k1, k2 = keypair(), keypair()
|
||||
# note: we don't start peer.htlc_switch() so that the fake htlcs are left alone.
|
||||
async def f():
|
||||
p1, p2, w1, w2, _q1, _q2 = self.prepare_peers(chan_AB, chan_BA, k1=k1, k2=k2)
|
||||
p1, p2, w1, w2, _q1, _q2 = self.prepare_peers(chan_AB, chan_BA)
|
||||
async with OldTaskGroup() as group:
|
||||
await group.spawn(p1._message_loop())
|
||||
await group.spawn(p2._message_loop())
|
||||
@@ -807,7 +698,7 @@ class TestPeerDirect(TestPeer):
|
||||
await group.cancel_remaining()
|
||||
# simulating disconnection. recreate transports.
|
||||
self.logger.info("simulating disconnection. recreating transports.")
|
||||
p1, p2, w1, w2, _q1, _q2 = self.prepare_peers(chan_AB, chan_BA, k1=k1, k2=k2)
|
||||
p1, p2, w1, w2, _q1, _q2 = self.prepare_peers(chan_AB, chan_BA)
|
||||
for chan in (chan_AB, chan_BA):
|
||||
chan.peer_state = PeerState.DISCONNECTED
|
||||
async with OldTaskGroup() as group:
|
||||
@@ -846,10 +737,9 @@ class TestPeerDirect(TestPeer):
|
||||
----rev-->
|
||||
"""
|
||||
chan_AB, chan_BA = create_test_channels()
|
||||
k1, k2 = keypair(), keypair()
|
||||
# note: we don't start peer.htlc_switch() so that the fake htlcs are left alone.
|
||||
async def f():
|
||||
p1, p2, w1, w2, _q1, _q2 = self.prepare_peers(chan_AB, chan_BA, k1=k1, k2=k2)
|
||||
p1, p2, w1, w2, _q1, _q2 = self.prepare_peers(chan_AB, chan_BA)
|
||||
async with OldTaskGroup() as group:
|
||||
await group.spawn(p1._message_loop())
|
||||
await group.spawn(p2._message_loop())
|
||||
@@ -864,7 +754,7 @@ class TestPeerDirect(TestPeer):
|
||||
await group.cancel_remaining()
|
||||
# simulating disconnection. recreate transports.
|
||||
self.logger.info("simulating disconnection. recreating transports.")
|
||||
p1, p2, w1, w2, _q1, _q2 = self.prepare_peers(chan_AB, chan_BA, k1=k1, k2=k2)
|
||||
p1, p2, w1, w2, _q1, _q2 = self.prepare_peers(chan_AB, chan_BA)
|
||||
for chan in (chan_AB, chan_BA):
|
||||
chan.peer_state = PeerState.DISCONNECTED
|
||||
async with OldTaskGroup() as group:
|
||||
@@ -1788,7 +1678,7 @@ class TestPeerDirect(TestPeer):
|
||||
with self.assertRaises(NoPathFound) as e:
|
||||
await w1.create_routes_from_invoice(lnaddr.get_amount_msat(), decoded_invoice=lnaddr)
|
||||
|
||||
peer = w1.peers[route[0].node_id]
|
||||
peer = w1.lnpeermgr._peers[route[0].node_id]
|
||||
# AssertionError is ok since we shouldn't use old routes, and the
|
||||
# route finding should fail when channel is closed
|
||||
async def f():
|
||||
@@ -2126,12 +2016,19 @@ class TestPeerDirect(TestPeer):
|
||||
class TestPeerForwarding(TestPeer):
|
||||
|
||||
def prepare_chans_and_peers_in_graph(self, graph_definition) -> Graph:
|
||||
keys = {k: keypair() for k in graph_definition}
|
||||
workers = {} # type: Dict[str, MockLNWallet]
|
||||
txs_queues = {k: asyncio.Queue() for k in graph_definition}
|
||||
|
||||
# create workers
|
||||
for a, definition in graph_definition.items():
|
||||
workers[a] = MockLNWallet(tx_queue=txs_queues[a], name=a, has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
self._lnworkers_created.extend(list(workers.values()))
|
||||
keys = {name: w.node_keypair for name, w in workers.items()}
|
||||
|
||||
channels = {} # type: Dict[Tuple[str, str], Channel]
|
||||
transports = {}
|
||||
workers = {} # type: Dict[str, MockLNWallet]
|
||||
peers = {}
|
||||
|
||||
# create channels
|
||||
for a, definition in graph_definition.items():
|
||||
for b, channel_def in definition.get('channels', {}).items():
|
||||
@@ -2145,6 +2042,8 @@ class TestPeerForwarding(TestPeer):
|
||||
anchor_outputs=self.TEST_ANCHOR_CHANNELS
|
||||
)
|
||||
channels[(a, b)], channels[(b, a)] = channel_ab, channel_ba
|
||||
workers[a]._add_channel(channel_ab)
|
||||
workers[b]._add_channel(channel_ba)
|
||||
transport_ab, transport_ba = transport_pair(keys[a], keys[b], channel_ab.name, channel_ba.name)
|
||||
transports[(a, b)], transports[(b, a)] = transport_ab, transport_ba
|
||||
# set fees
|
||||
@@ -2153,12 +2052,6 @@ class TestPeerForwarding(TestPeer):
|
||||
channel_ba.forwarding_fee_proportional_millionths = channel_def['remote_fee_rate_millionths']
|
||||
channel_ba.forwarding_fee_base_msat = channel_def['remote_base_fee_msat']
|
||||
|
||||
# create workers and peers
|
||||
for a, definition in graph_definition.items():
|
||||
channels_of_node = [c for k, c in channels.items() if k[0] == a]
|
||||
workers[a] = MockLNWallet(local_keypair=keys[a], chans=channels_of_node, tx_queue=txs_queues[a], name=a, has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
self._lnworkers_created.extend(list(workers.values()))
|
||||
|
||||
# create peers
|
||||
for ab in channels.keys():
|
||||
peers[ab] = Peer(workers[ab[0]], keys[ab[1]].pubkey, transports[ab])
|
||||
@@ -2167,7 +2060,7 @@ class TestPeerForwarding(TestPeer):
|
||||
for a, w in workers.items():
|
||||
for ab, peer_ab in peers.items():
|
||||
if ab[0] == a:
|
||||
w._peers[peer_ab.pubkey] = peer_ab
|
||||
w.lnpeermgr._peers[peer_ab.pubkey] = peer_ab
|
||||
|
||||
# set forwarding properties
|
||||
for a, definition in graph_definition.items():
|
||||
|
||||
Reference in New Issue
Block a user