Skip to content

Commit 2b761b0

Browse files
committed
pytest: Test that we don't forget zeroconf channels
Modified by Rusty: - Simplify (we only need to suppress l1's txs, since it opens) - Use synchronize_blockheight instead of log messages to ensure l2 has processed the block - Use listpeerchannels instead of log messages for balance (should be more robust against changes) - Open-code assertions for better debugging if they're wrong.
1 parent 66deb4d commit 2b761b0

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

tests/test_opening.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2685,3 +2685,74 @@ def test_multifunding_all_amount(node_factory, bitcoind):
26852685

26862686
inv2 = l3.rpc.invoice(100000, 'i2', 'i2')['bolt11']
26872687
l1.rpc.pay(inv2)
2688+
2689+
2690+
@pytest.mark.parametrize("dopay", [True, False]) # Whether to send a payment or not
2691+
def test_zeroconf_forget(node_factory, bitcoind, dopay: bool):
2692+
"""Reprotest for #8147: We should not forget a channel on which we received a zeroconf payment.
2693+
2694+
The channel forgetting code actually uses the fact that we ever
2695+
had a non-zero amount in this channel.
2696+
2697+
"""
2698+
blocks = 50
2699+
plugin_path = Path(__file__).parent / "plugins" / "zeroconf-selective.py"
2700+
l1, l2 = node_factory.get_nodes(
2701+
2,
2702+
opts=[
2703+
{},
2704+
{
2705+
"plugin": str(plugin_path),
2706+
"zeroconf-allow": "0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518",
2707+
"zeroconf-mindepth": "0",
2708+
"dev-max-funding-unconfirmed-blocks": blocks,
2709+
},
2710+
],
2711+
)
2712+
2713+
# Make it such that l1 cannot broadcast transactions
2714+
def censoring_sendrawtx(tx):
2715+
return {"id": tx["id"], "result": {}}
2716+
2717+
l1.daemon.rpcproxy.mock_rpc("sendrawtransaction", censoring_sendrawtx)
2718+
2719+
l1.connect(l2)
2720+
l1.fundwallet(10**7)
2721+
l1.rpc.fundchannel(l2.info["id"], 10**6, mindepth=0)
2722+
sync_blockheight(bitcoind, [l1, l2])
2723+
wait_for(lambda: l2.rpc.listincoming()["incoming"] != [])
2724+
2725+
# If we are told to pay while still not confirmed we perform one
2726+
# payment. This causes us to have a non-zero stake in the channel,
2727+
# thus we should not forget the channel. If we don't then our
2728+
# stake will remain 0msat, hence we can forget the channel without
2729+
# risking any of our funds.
2730+
if dopay:
2731+
inv = l2.rpc.invoice(1, "payme", "my stake in the unconfirmed channel")
2732+
l1.rpc.pay(inv["bolt11"])
2733+
wait_for(lambda: only_one(l2.rpc.listpeerchannels()['channels'])['to_us_msat'] == 1)
2734+
2735+
# Now stop, in order to cause catchup and re-evaluate whether to forget the channel
2736+
l2.stop()
2737+
2738+
# Now we generate enough blocks to cause l2 to forget the channel.
2739+
bitcoind.generate_block(blocks) # > blocks
2740+
l2.start()
2741+
2742+
sync_blockheight(bitcoind, [l1, l2])
2743+
2744+
# It will have completed processing of last block before being able to process this one:
2745+
# This ensures l2 will have forgotten channel if it was going to.
2746+
bitcoind.generate_block(1)
2747+
sync_blockheight(bitcoind, [l1, l2])
2748+
2749+
have_forgotten = l2.daemon.is_in_log(
2750+
r"Forgetting channel: It has been [0-9]+ blocks without the funding transaction"
2751+
)
2752+
2753+
if dopay:
2754+
assert not have_forgotten
2755+
assert len(l2.rpc.listpeerchannels()["channels"]) == 1
2756+
else:
2757+
assert have_forgotten
2758+
assert l2.rpc.listpeerchannels() == {"channels": []}

0 commit comments

Comments
 (0)