Skip to content

Commit 8caffde

Browse files
committed
pytest: test for watching utxos over restart reorg.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent 534e3ae commit 8caffde

File tree

1 file changed

+47
-2
lines changed

1 file changed

+47
-2
lines changed

tests/test_wallet.py

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
from fixtures import TEST_NETWORK
55
from pyln.client import RpcError, Millisatoshi
66
from utils import (
7-
only_one, wait_for, sync_blockheight,
7+
only_one, wait_for, sync_blockheight, mine_funding_to_announce,
88
VALGRIND, check_coin_moves, TailableProc, scriptpubkey_addr,
9-
check_utxos_channel, check_feerate, did_short_sig
9+
check_utxos_channel, check_feerate, did_short_sig, first_scid,
1010
)
1111

1212
import os
@@ -2536,3 +2536,48 @@ def test_hsm_wrong_passphrase_crash(node_factory):
25362536

25372537
os.close(master_fd2)
25382538
os.close(slave_fd2)
2539+
2540+
2541+
@pytest.mark.xfail(strict=True)
2542+
def test_unspend_during_reorg(node_factory, bitcoind):
2543+
l1, l2 = node_factory.line_graph(2)
2544+
scid = first_scid(l1, l2)
2545+
blockheight, txindex, _ = scid.split('x')
2546+
2547+
# Use mainnet settings for rescan.
2548+
l3 = node_factory.get_node(options={'rescan': 15})
2549+
l3.connect(l2)
2550+
2551+
mine_funding_to_announce(bitcoind, [l1, l2, l3])
2552+
bitcoind.generate_block(20)
2553+
sync_blockheight(bitcoind, [l3])
2554+
wait_for(lambda: len(l3.rpc.listchannels()['channels']) == 2)
2555+
2556+
# db shows it unspent.
2557+
assert only_one(l1.db_query(f"SELECT spendheight as spendheight FROM utxoset WHERE blockheight={blockheight} AND txindex={txindex}"))['spendheight'] is None
2558+
2559+
# Now, l3 sees the close, marks channel dying.
2560+
l1.rpc.close(l2.info['id'])
2561+
spentheight = bitcoind.rpc.getblockcount() + 1
2562+
bitcoind.generate_block(14, wait_for_mempool=1)
2563+
wait_for(lambda: len(l3.rpc.listchannels()['channels']) == 2)
2564+
2565+
# In one fell swoop it goes through dying, to dead (12 blocks)
2566+
l3.daemon.wait_for_log(f"Adding block {spentheight}")
2567+
l3.daemon.wait_for_log(f"gossipd: channel {scid} closing soon due to the funding outpoint being spent")
2568+
l3.daemon.wait_for_log(f"gossipd: Deleting channel {scid} due to the funding outpoint being spent")
2569+
2570+
# db shows it spent
2571+
assert only_one(l3.db_query(f"SELECT spendheight as spendheight FROM utxoset WHERE blockheight={blockheight} AND txindex={txindex}"))['spendheight'] == spentheight
2572+
2573+
# Restart, see replay.
2574+
l3.stop()
2575+
# This is enough to take channel from dying to dead.
2576+
bitcoind.generate_block(10)
2577+
2578+
l3.start()
2579+
# Channel should still be dead.
2580+
l3.daemon.wait_for_log(f"Adding block {spentheight}")
2581+
2582+
sync_blockheight(bitcoind, [l3])
2583+
assert only_one(l3.db_query(f"SELECT spendheight as spendheight FROM utxoset WHERE blockheight={blockheight} AND txindex={txindex}"))['spendheight'] == spentheight

0 commit comments

Comments
 (0)