mirror of
https://github.com/bitromortac/lndmanage.git
synced 2026-08-13 12:33:37 +02:00
adds the main listpeers command with subcommands * listpeers in: sorted by total incoming funds * listpeers out: sorted by total outgoing funds
208 lines
6.7 KiB
Python
208 lines
6.7 KiB
Python
"""
|
|
Integration tests for rebalancing of channels.
|
|
"""
|
|
import time
|
|
|
|
from lndmanage import settings
|
|
from lndmanage.lib.listings import ListChannels
|
|
from lndmanage.lib.rebalance import Rebalancer
|
|
from lndmanage.lib.ln_utilities import channel_unbalancedness_and_commit_fee
|
|
from lndmanage.lib.exceptions import RebalanceCandidatesExhausted
|
|
from test.testnetwork import TestNetwork
|
|
|
|
from test.testing_common import (
|
|
lndmanage_home,
|
|
test_graphs_paths,
|
|
SLEEP_SEC_AFTER_REBALANCING)
|
|
|
|
import logging.config
|
|
settings.set_lndmanage_home_dir(lndmanage_home)
|
|
logging.config.dictConfig(settings.logger_config)
|
|
logger = logging.getLogger()
|
|
logger.setLevel(logging.DEBUG)
|
|
logger.handlers[0].setLevel(logging.DEBUG)
|
|
|
|
|
|
class RebalanceTest(TestNetwork):
|
|
"""
|
|
Implements an abstract testing class for channel rebalancing.
|
|
"""
|
|
def rebalance_and_check(self, test_channel_number, target,
|
|
allow_unbalancing, places=5):
|
|
"""
|
|
Test function for rebalancing to a specific target unbalancedness and
|
|
asserts afterwards that the target was reached.
|
|
|
|
:param test_channel_number: channel id
|
|
:type test_channel_number: int
|
|
:param target: unbalancedness target
|
|
:type target: float
|
|
:param allow_unbalancing: if unbalancing should be allowed
|
|
:type allow_unbalancing: bool
|
|
:param places: accuracy of the comparison between expected and tested
|
|
values
|
|
:type places: int
|
|
"""
|
|
rebalancer = Rebalancer(
|
|
self.lndnode,
|
|
max_effective_fee_rate=50,
|
|
budget_sat=20
|
|
)
|
|
|
|
channel_id = self.testnet.channel_mapping[
|
|
test_channel_number]['channel_id']
|
|
|
|
try:
|
|
fees_msat = rebalancer.rebalance(
|
|
channel_id,
|
|
dry=False,
|
|
chunksize=1.0,
|
|
target=target,
|
|
allow_unbalancing=allow_unbalancing
|
|
)
|
|
except Exception as e:
|
|
raise e
|
|
|
|
# sleep a bit to let LNDs update their balances
|
|
time.sleep(SLEEP_SEC_AFTER_REBALANCING)
|
|
|
|
# check if graph has the desired channel balances
|
|
graph = self.testnet.assemble_graph()
|
|
channel_data = graph['A'][test_channel_number]
|
|
listchannels = ListChannels(self.lndnode)
|
|
listchannels.print_all_channels('rev_alias')
|
|
|
|
channel_unbalancedness, _ = channel_unbalancedness_and_commit_fee(
|
|
channel_data['local_balance'],
|
|
channel_data['capacity'],
|
|
channel_data['commit_fee'],
|
|
channel_data['initiator']
|
|
)
|
|
|
|
self.assertAlmostEqual(
|
|
target, channel_unbalancedness, places=places)
|
|
|
|
return fees_msat
|
|
|
|
def graph_test(self):
|
|
"""
|
|
graph_test should be implemented by each subclass test and check,
|
|
whether the test graph has the correct shape.
|
|
"""
|
|
raise NotImplementedError
|
|
|
|
|
|
class TestLiquidRebalance(RebalanceTest):
|
|
network_definition = test_graphs_paths['star_ring_3_liquid']
|
|
|
|
# channels:
|
|
# A -> B (channel #1)
|
|
# A -> C (channel #2)
|
|
# A -> D (channel #6)
|
|
# B -> C (channel #3)
|
|
# B -> D (channel #4)
|
|
# C -> D (channel #5)
|
|
|
|
def graph_test(self):
|
|
self.assertEqual(6, len(self.master_node_graph_view))
|
|
|
|
def test_rebalance_channel_6(self):
|
|
test_channel_number = 6
|
|
self.rebalance_and_check(test_channel_number, 0.0, False)
|
|
|
|
def test_small_positive_target_channel_6(self):
|
|
test_channel_number = 6
|
|
self.rebalance_and_check(test_channel_number, 0.2, False)
|
|
|
|
def test_large_positive_channel_6(self):
|
|
test_channel_number = 6
|
|
self.rebalance_and_check(test_channel_number, 0.8, False)
|
|
|
|
def test_small_negative_target_channel_6_fail(self):
|
|
# this test should fail when unbalancing is not allowed, as it would
|
|
# unbalance another channel if the full target would be accounted for
|
|
test_channel_number = 6
|
|
self.assertRaises(
|
|
RebalanceCandidatesExhausted,
|
|
self.rebalance_and_check, test_channel_number, -0.2, False)
|
|
|
|
def test_small_negative_target_channel_6_succeed(self):
|
|
# this test should fail when unbalancing is not allowed, as it would
|
|
# unbalance another channel if the full target would be accounted for
|
|
test_channel_number = 6
|
|
self.rebalance_and_check(test_channel_number, -0.2, True)
|
|
|
|
def test_rebalance_channel_1(self):
|
|
test_channel_number = 1
|
|
self.rebalance_and_check(test_channel_number, 0.0, False, places=2)
|
|
|
|
def test_rebalance_channel_2(self):
|
|
test_channel_number = 2
|
|
self.rebalance_and_check(test_channel_number, 0.0, False, places=1)
|
|
|
|
def test_shuffle_arround(self):
|
|
"""
|
|
Shuffles sat around in channel 6.
|
|
"""
|
|
first_target_amount = -0.1
|
|
second_target_amount = 0.1
|
|
test_channel_number = 6
|
|
|
|
self.rebalance_and_check(
|
|
test_channel_number, first_target_amount, True)
|
|
self.rebalance_and_check(
|
|
test_channel_number, second_target_amount, True)
|
|
|
|
|
|
class TestUnbalancedRebalance(RebalanceTest):
|
|
network_definition = test_graphs_paths['star_ring_4_unbalanced']
|
|
|
|
# channels:
|
|
# A -> B (channel #1)
|
|
# A -> C (channel #2)
|
|
# A -> D (channel #3)
|
|
# A -> E (channel #4)
|
|
|
|
def graph_test(self):
|
|
self.assertEqual(10, len(self.master_node_graph_view))
|
|
|
|
def test_rebalance_channel_1(self):
|
|
"""tests multiple rebalance of one channel"""
|
|
test_channel_number = 1
|
|
# TODO: find out why not exact rebalancing target is reached
|
|
print(self.rebalance_and_check(
|
|
test_channel_number, -0.05, False, places=1))
|
|
|
|
|
|
class TestIlliquidRebalance(RebalanceTest):
|
|
network_definition = test_graphs_paths['star_ring_4_illiquid']
|
|
|
|
# channels:
|
|
# A -> B (channel #1)
|
|
# A -> C (channel #2)
|
|
# A -> D (channel #3)
|
|
# A -> E (channel #4)
|
|
|
|
def graph_test(self):
|
|
self.assertEqual(10, len(self.master_node_graph_view))
|
|
|
|
def test_rebalance_channel_1(self):
|
|
"""
|
|
Tests multiple payment attempt rebalancing.
|
|
"""
|
|
test_channel_number = 1
|
|
# TODO: find out why not exact rebalancing target is reached
|
|
fees_msat = self.rebalance_and_check(
|
|
test_channel_number, -0.05, False, places=1)
|
|
self.assertEqual(2623, fees_msat)
|
|
|
|
def test_rebalance_channel_1_fail(self):
|
|
"""
|
|
Tests if there are no rebalance candidates, because the target
|
|
requested doesn't match with the other channels.
|
|
"""
|
|
test_channel_number = 1
|
|
self.assertRaises(
|
|
RebalanceCandidatesExhausted, self.rebalance_and_check,
|
|
test_channel_number, 0.3, False, places=1
|
|
)
|