mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-26 20:30:59 +01:00
pytest: Add a zeroreserve test
This commit is contained in:
parent
c3e9cb7a47
commit
c5b2aee5c6
2 changed files with 102 additions and 0 deletions
27
tests/plugins/zeroreserve.py
Executable file
27
tests/plugins/zeroreserve.py
Executable file
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Use the openchannel hook to selectively opt-into zeroconf
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pyln.client import Plugin
|
||||||
|
|
||||||
|
plugin = Plugin()
|
||||||
|
|
||||||
|
|
||||||
|
@plugin.hook('openchannel')
|
||||||
|
def on_openchannel(openchannel, plugin, **kwargs):
|
||||||
|
plugin.log(repr(openchannel))
|
||||||
|
reserve = plugin.options['reserve']['value']
|
||||||
|
|
||||||
|
if reserve is None:
|
||||||
|
return {'result': 'continue'}
|
||||||
|
else:
|
||||||
|
return {'result': 'continue', 'reserve': reserve}
|
||||||
|
|
||||||
|
|
||||||
|
plugin.add_option(
|
||||||
|
'reserve',
|
||||||
|
None,
|
||||||
|
'Absolute reserve to require from peers when accepting channels',
|
||||||
|
)
|
||||||
|
|
||||||
|
plugin.run()
|
|
@ -1730,3 +1730,78 @@ def test_zeroconf_multichan_forward(node_factory):
|
||||||
inv = l3.rpc.invoice(amount_msat=10000, label='lbl1', description='desc')['bolt11']
|
inv = l3.rpc.invoice(amount_msat=10000, label='lbl1', description='desc')['bolt11']
|
||||||
l1.rpc.pay(inv)
|
l1.rpc.pay(inv)
|
||||||
assert l2.daemon.is_in_log(r'Chose a better channel: .*')
|
assert l2.daemon.is_in_log(r'Chose a better channel: .*')
|
||||||
|
|
||||||
|
|
||||||
|
def test_zeroreserve(node_factory, bitcoind):
|
||||||
|
"""Ensure we can set the reserves.
|
||||||
|
|
||||||
|
3 nodes:
|
||||||
|
- l1 enforces zeroreserve
|
||||||
|
- l2 enforces default reserve
|
||||||
|
- l3 enforces sub-dust reserves
|
||||||
|
"""
|
||||||
|
ZEROCONF = True
|
||||||
|
plugin_path = Path(__file__).parent / "plugins" / "zeroreserve.py"
|
||||||
|
opts = [
|
||||||
|
{
|
||||||
|
'plugin': str(plugin_path),
|
||||||
|
'reserve': '0sat',
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
'plugin': str(plugin_path),
|
||||||
|
'reserve': '123sat'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
l1, l2, l3 = node_factory.get_nodes(3, opts=opts)
|
||||||
|
|
||||||
|
l1.fundwallet(10**7)
|
||||||
|
l2.fundwallet(10**7)
|
||||||
|
l3.fundwallet(10**7)
|
||||||
|
|
||||||
|
l1.connect(l2)
|
||||||
|
l2.connect(l3)
|
||||||
|
l3.connect(l1)
|
||||||
|
|
||||||
|
l1.rpc.fundchannel(l2.info['id'], 10**6, reserve='0sat')
|
||||||
|
l2.rpc.fundchannel(l3.info['id'], 10**6)
|
||||||
|
l3.rpc.fundchannel(l1.info['id'], 10**6, reserve='321sat')
|
||||||
|
bitcoind.generate_block(1, wait_for_mempool=3)
|
||||||
|
wait_for(lambda: l1.channel_state(l2) == 'CHANNELD_NORMAL')
|
||||||
|
wait_for(lambda: l2.channel_state(l3) == 'CHANNELD_NORMAL')
|
||||||
|
wait_for(lambda: l3.channel_state(l1) == 'CHANNELD_NORMAL')
|
||||||
|
|
||||||
|
# Now make sure we all agree on each others reserves
|
||||||
|
l1c1 = l1.rpc.listpeers(l2.info['id'])['peers'][0]['channels'][0]
|
||||||
|
l2c1 = l2.rpc.listpeers(l1.info['id'])['peers'][0]['channels'][0]
|
||||||
|
l2c2 = l2.rpc.listpeers(l3.info['id'])['peers'][0]['channels'][0]
|
||||||
|
l3c2 = l3.rpc.listpeers(l2.info['id'])['peers'][0]['channels'][0]
|
||||||
|
l3c3 = l3.rpc.listpeers(l1.info['id'])['peers'][0]['channels'][0]
|
||||||
|
l1c3 = l1.rpc.listpeers(l3.info['id'])['peers'][0]['channels'][0]
|
||||||
|
|
||||||
|
# l1 imposed a 0sat reserve on l2, while l2 imposed the default 1% reserve on l1
|
||||||
|
assert l1c1['their_channel_reserve_satoshis'] == l2c1['our_channel_reserve_satoshis'] == (0 if ZEROCONF else 546)
|
||||||
|
assert l1c1['our_channel_reserve_satoshis'] == l2c1['their_channel_reserve_satoshis'] == 10000
|
||||||
|
|
||||||
|
# l2 imposed the default 1% on l3, while l3 imposed a custom 123sat fee on l2
|
||||||
|
assert l2c2['their_channel_reserve_satoshis'] == l3c2['our_channel_reserve_satoshis'] == 10000
|
||||||
|
assert l2c2['our_channel_reserve_satoshis'] == l3c2['their_channel_reserve_satoshis'] == (123 if ZEROCONF else 546)
|
||||||
|
|
||||||
|
# l3 imposed a custom 321sat fee on l1, while l1 imposed a custom 0sat fee on l3
|
||||||
|
assert l3c3['their_channel_reserve_satoshis'] == l1c3['our_channel_reserve_satoshis'] == (321 if ZEROCONF else 546)
|
||||||
|
assert l3c3['our_channel_reserve_satoshis'] == l1c3['their_channel_reserve_satoshis'] == (0 if ZEROCONF else 546)
|
||||||
|
|
||||||
|
# Now do some drain tests on c1, as that should be drainable
|
||||||
|
# completely by l2 being the fundee
|
||||||
|
l1.rpc.keysend(l2.info['id'], 10 * 7) # Something above dust for sure
|
||||||
|
l2.drain(l1)
|
||||||
|
|
||||||
|
# Remember that this is the reserve l1 imposed on l2, so l2 can drain completely
|
||||||
|
l2c1 = l2.rpc.listpeers(l1.info['id'])['peers'][0]['channels'][0]
|
||||||
|
|
||||||
|
# And despite us briefly being above dust (with a to_us output),
|
||||||
|
# closing should result in the output being trimmed again since we
|
||||||
|
# dropped below dust again.
|
||||||
|
c = l2.rpc.close(l1.info['id'])
|
||||||
|
decoded = bitcoind.rpc.decoderawtransaction(c['tx'])
|
||||||
|
assert len(decoded['vout']) == 1
|
||||||
|
|
Loading…
Add table
Reference in a new issue