mirror of
https://github.com/aljazceru/plugins.git
synced 2025-12-25 08:54:20 +01:00
148 lines
5.0 KiB
Python
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
|