From 602085128f1d0c49cdaad1845ba3ed05cb608588 Mon Sep 17 00:00:00 2001 From: Aditya Sharma Date: Wed, 20 Nov 2024 06:49:34 +1030 Subject: [PATCH] tests/test_misc.py: Add test for emergencyrecover Check if we can successfully create a penalty transaction when we recover a channel using emergencyrecover and the peer publishes an old state. Changelog-Added: Now the emergency.recover file would keep track of all the revocation secrets when any channel advances it's state. --- tests/test_misc.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tests/test_misc.py b/tests/test_misc.py index 0e16f337fa39..794e2676837b 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -2883,6 +2883,60 @@ def test_getemergencyrecoverdata(node_factory): assert lines == filedata +def test_emergencyrecoverpenaltytxn(node_factory, bitcoind): + l1, l2 = node_factory.get_nodes(2, [{'broken_log': r"onchaind-chan#[0-9]*: Could not find resolution for output .*: did \*we\* cheat\?", + 'may_reconnect': True, + 'allow_bad_gossip': True, + 'rescan': 10}, + {'broken_log': r"onchaind-chan#[0-9]*: Could not find resolution for output .*: did \*we\* cheat\?", + 'may_reconnect': True}]) + + l1.rpc.connect(l2.info['id'], 'localhost', l2.port) + c12, _ = l2.fundchannel(l1, 10**5) + stubs = l1.rpc.emergencyrecover()["stubs"] + assert l1.daemon.is_in_log('channel {} already exists!'.format(_['channel_id'])) + + l2.rpc.pay(l1.rpc.invoice(25000000, 'lbl1', 'desc1')['bolt11']) + + tx = l2.rpc.dev_sign_last_tx(l1.info['id'])['tx'] + + l2.rpc.pay(l1.rpc.invoice(25000000, 'lbl2', 'desc2')['bolt11']) + + l1.stop() + + # Now l2 cheats + bitcoind.rpc.sendrawtransaction(tx) + time.sleep(1) + bitcoind.generate_block(1) + + # Deleting the database for the L1 node + os.unlink(os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, "lightningd.sqlite3")) + + # Running emergencyrecover on L1 to stub the channel inside the database. + l1.start() + assert l1.daemon.is_in_log('Server started with public key') + stubs = l1.rpc.emergencyrecover()["stubs"] + assert len(stubs) == 1 + assert stubs[0] == _["channel_id"] + l1.daemon.wait_for_log('peer_out WIRE_ERROR') + + # Restarting so that L1 + l1.restart() + + # Wait till L1 detects that L2 has cheated and it needs to create a penalty transaction. + _, txid, blocks = l1.wait_for_onchaind_tx('OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM') + assert blocks == 0 + bitcoind.generate_block(10, wait_for_mempool=[txid]) + sync_blockheight(bitcoind, [l1, l2]) + + # And l1 should consider it resolved now. + l1.daemon.wait_for_log('Resolved THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM by our proposal OUR_PENALTY_TX') + + assert(l1.rpc.listfunds()["channels"][0]["state"] == "ONCHAIN") + assert(l1.rpc.listfunds()["outputs"][0]["txid"] == txid) + + @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "deletes database, which is assumed sqlite3") def test_emergencyrecover(node_factory, bitcoind): """