Files
plugins/rebalance/test_rebalance.py
2023-02-08 15:32:42 +01:00

148 lines
5.0 KiB
Python

import os
from pyln.testing.fixtures import * # noqa: F401,F403
from pyln.client import Millisatoshi
plugin_path = os.path.join(os.path.dirname(__file__), "rebalance.py")
plugin_opt = {'plugin': plugin_path}
# waits for a bunch of nodes HTLCs to settle
def wait_for_all_htlcs(nodes):
for n in nodes:
n.wait_for_htlcs()
# waits for all nodes to have all scids gossip active
def wait_for_all_active(nodes, scids):
for n in nodes:
for scid in scids:
n.wait_channel_active(scid)
def test_rebalance_starts(node_factory):
l1 = node_factory.get_node()
# Test dynamically
l1.rpc.plugin_start(plugin_path)
l1.rpc.plugin_stop(plugin_path)
l1.rpc.plugin_start(plugin_path)
l1.stop()
# Then statically
l1.daemon.opts["plugin"] = plugin_path
l1.start()
def test_rebalance_manual(node_factory, bitcoind):
l1, l2, l3 = node_factory.line_graph(3, opts=plugin_opt)
nodes = [l1, l2, l3]
# form a circle so we can do rebalancing
l3.connect(l1)
l3.fundchannel(l1)
# get scids
scid12 = l1.get_channel_scid(l2)
scid23 = l2.get_channel_scid(l3)
scid31 = l3.get_channel_scid(l1)
scids = [scid12, scid23, scid31]
# wait for each others gossip
bitcoind.generate_block(6)
for n in nodes:
for scid in scids:
n.wait_channel_active(scid)
# check we can do an auto amount rebalance
result = l1.rpc.rebalance(scid12, scid31)
print(result)
assert result['status'] == 'complete'
assert result['outgoing_scid'] == scid12
assert result['incoming_scid'] == scid31
assert result['hops'] == 3
assert result['received'] == '500000000msat'
# wait until listpeers is up2date
wait_for_all_htlcs(nodes)
# check that channels are now balanced
c12 = l1.rpc.listpeerchannels(l2.info['id'])['channels'][0]
c13 = l1.rpc.listpeerchannels(l3.info['id'])['channels'][0]
assert abs(0.5 - (Millisatoshi(c12['to_us_msat']) / Millisatoshi(c12['total_msat']))) < 0.01
assert abs(0.5 - (Millisatoshi(c13['to_us_msat']) / Millisatoshi(c13['total_msat']))) < 0.01
# check we can do a manual amount rebalance in the other direction
result = l1.rpc.rebalance(scid31, scid12, '250000000msat')
assert result['status'] == 'complete'
assert result['outgoing_scid'] == scid31
assert result['incoming_scid'] == scid12
assert result['hops'] == 3
assert result['received'] == '250000000msat'
# briefly check rebalancereport works
report = l1.rpc.rebalancereport()
assert report.get('rebalanceall_is_running') is False
assert report.get('total_successful_rebalances') == 2
def test_rebalance_all(node_factory, bitcoind):
l1, l2, l3 = node_factory.line_graph(3, opts=plugin_opt)
nodes = [l1, l2, l3]
# check we get an error if theres just one channel
result = l1.rpc.rebalanceall()
assert result['message'] == 'Error: Not enough open channels to rebalance anything'
# now we add another 100% outgoing liquidity to l1 which does not help
l4 = node_factory.get_node()
l1.connect(l4)
l1.fundchannel(l4)
# test this is still not possible
result = l1.rpc.rebalanceall()
assert result['message'] == 'Error: Not enough liquidity to rebalance anything'
# remove l4 it does not distort further testing
l1.rpc.close(l1.get_channel_scid(l4))
# now we form a circle so we can do actually rebalanceall
l3.connect(l1)
l3.fundchannel(l1)
# get scids
scid12 = l1.get_channel_scid(l2)
scid23 = l2.get_channel_scid(l3)
scid31 = l3.get_channel_scid(l1)
scids = [scid12, scid23, scid31]
# wait for each others gossip
bitcoind.generate_block(6)
wait_for_all_active(nodes, scids)
# check that theres nothing to stop when theres nothing to stop
result = l1.rpc.rebalancestop()
assert result['message'] == "No rebalance is running, nothing to stop."
# check the rebalanceall starts
result = l1.rpc.rebalanceall(feeratio=5.0) # we need high fees to work
assert result['message'].startswith('Rebalance started')
l1.daemon.wait_for_logs([f"tries to rebalance: {scid12} -> {scid31}",
f"Automatic rebalance finished"])
# check additional calls to stop return 'nothing to stop' + last message
result = l1.rpc.rebalancestop()['message']
assert result.startswith("No rebalance is running, nothing to stop. "
"Last 'rebalanceall' gave: Automatic rebalance finished")
# wait until listpeers is up2date
wait_for_all_htlcs(nodes)
# check that channels are now balanced
c12 = l1.rpc.listpeerchannels(l2.info['id'])['channels'][0]
c13 = l1.rpc.listpeerchannels(l3.info['id'])['channels'][0]
assert abs(0.5 - (Millisatoshi(c12['to_us_msat']) / Millisatoshi(c12['total_msat']))) < 0.01
assert abs(0.5 - (Millisatoshi(c13['to_us_msat']) / Millisatoshi(c13['total_msat']))) < 0.01
# briefly check rebalancereport works
report = l1.rpc.rebalancereport()
assert report.get('rebalanceall_is_running') is False
assert report.get('total_successful_rebalances') == 2