bkpr: failing test for bookkeeper crash

Reproduce crash for #5557!

If we record the channel open because bookkeeper was added after the
channel open request started but the channel confirms later, we end up
with re-recording any associated push or leased fees (paid or rcvd).

In the case where you've paid for these fees, your channel balance goes
negative and the node crashes the next time you call `listbalances`.

Reported-by: @chrisguida
This commit is contained in:
niftynei 2022-09-12 18:49:26 -05:00 committed by Rusty Russell
parent e0d6f3ceb1
commit 8452d903b4

View File

@ -1513,6 +1513,61 @@ def test_buy_liquidity_ad_no_v2(node_factory, bitcoind):
compact_lease='029a002d000000004b2003e8') compact_lease='029a002d000000004b2003e8')
@pytest.mark.xfail
@pytest.mark.openchannel('v2')
def test_buy_liquidity_ad_check_bookkeeping(node_factory, bitcoind):
""" Test that your bookkeeping for a liquidity ad is good."""
opts = [{'funder-policy': 'match', 'funder-policy-mod': 100,
'lease-fee-base-sat': '100sat', 'lease-fee-basis': 100,
'rescan': 10, 'disable-plugin': 'bookkeeper',
'funding-confirms': 6, 'may_reconnect': True},
{'funder-policy': 'match', 'funder-policy-mod': 100,
'lease-fee-base-sat': '100sat', 'lease-fee-basis': 100}]
l1, l2, = node_factory.get_nodes(2, opts=opts)
amount = 500000
feerate = 2000
l1.fundwallet(amount * 100)
l2.fundwallet(amount * 100)
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
rates = l1.rpc.dev_queryrates(l2.info['id'], amount, amount)
wait_for(lambda: len(l1.rpc.listpeers(l2.info['id'])['peers']) == 0)
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
# l1 leases a channel from l2
l1.rpc.fundchannel(l2.info['id'], amount, request_amt=amount,
feerate='{}perkw'.format(feerate),
compact_lease=rates['compact_lease'])
# add the funding transaction
bitcoind.generate_block(4, wait_for_mempool=1)
l1.stop()
del l1.daemon.opts['disable-plugin']
l1.start()
chan_id = first_channel_id(l1, l2)
ev_tags = [e['tag'] for e in l1.rpc.bkpr_listaccountevents(chan_id)['events']]
assert 'lease_fee' in ev_tags
bitcoind.generate_block(2)
l1.daemon.wait_for_log('to CHANNELD_NORMAL')
# This should work ok
l1.rpc.bkpr_listbalances()
l1.rpc.close(l2.info['id'], 1)
bitcoind.generate_block(6, wait_for_mempool=1)
l1.daemon.wait_for_log(' to ONCHAIN')
l2.daemon.wait_for_log(' to ONCHAIN')
# This should crash
l1.rpc.bkpr_listbalances()
def test_scid_alias_private(node_factory, bitcoind): def test_scid_alias_private(node_factory, bitcoind):
"""Test that we don't allow use of real scid for scid_alias-type channels""" """Test that we don't allow use of real scid for scid_alias-type channels"""
l1, l2, l3 = node_factory.line_graph(3, fundchannel=False, opts=[{}, {}, l1, l2, l3 = node_factory.line_graph(3, fundchannel=False, opts=[{}, {},