Close a channel before it's mined, and the most recent transaction hasn't made it to the mempool. Should publish all the commitment transactions that we have.
(node_factory, bitcoind, chainparams)
| 909 | @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') |
| 910 | @pytest.mark.openchannel('v2') |
| 911 | def test_rbf_broadcast_close_inflights(node_factory, bitcoind, chainparams): |
| 912 | """ |
| 913 | Close a channel before it's mined, and the most recent transaction |
| 914 | hasn't made it to the mempool. Should publish all the commitment |
| 915 | transactions that we have. |
| 916 | """ |
| 917 | l1, l2 = node_factory.get_nodes(2, |
| 918 | opts={'allow_warning': True}) |
| 919 | |
| 920 | l1.rpc.connect(l2.info['id'], 'localhost', l2.port) |
| 921 | amount = 2**24 |
| 922 | chan_amount = 100000 |
| 923 | bitcoind.rpc.sendtoaddress(l1.rpc.newaddr()['bech32'], amount / 10**8 + 0.01) |
| 924 | bitcoind.generate_block(1) |
| 925 | # Wait for it to arrive. |
| 926 | wait_for(lambda: len(l1.rpc.listfunds()['outputs']) > 0) |
| 927 | |
| 928 | res = l1.rpc.fundchannel(l2.info['id'], chan_amount, feerate='7500perkw') |
| 929 | chan_id = res['channel_id'] |
| 930 | vins = bitcoind.rpc.decoderawtransaction(res['tx'])['vin'] |
| 931 | assert(only_one(vins)) |
| 932 | prev_utxos = ["{}:{}".format(vins[0]['txid'], vins[0]['vout'])] |
| 933 | |
| 934 | # Check that we're waiting for lockin |
| 935 | l1.daemon.wait_for_log(' to DUALOPEND_AWAITING_LOCKIN') |
| 936 | inflights = only_one(only_one(l1.rpc.listpeers()['peers'])['channels'])['inflight'] |
| 937 | assert inflights[-1]['funding_txid'] in bitcoind.rpc.getrawmempool() |
| 938 | |
| 939 | # Make it such that l1 and l2 cannot broadcast transactions |
| 940 | # (mimics failing to reach the miner with replacement) |
| 941 | def censoring_sendrawtx(r): |
| 942 | return {'id': r['id'], 'result': {}} |
| 943 | |
| 944 | l1.daemon.rpcproxy.mock_rpc('sendrawtransaction', censoring_sendrawtx) |
| 945 | l2.daemon.rpcproxy.mock_rpc('sendrawtransaction', censoring_sendrawtx) |
| 946 | |
| 947 | def run_retry(): |
| 948 | startweight = 42 + 173 |
| 949 | next_feerate = find_next_feerate(l1, l2) |
| 950 | initpsbt = l1.rpc.utxopsbt(chan_amount, next_feerate, startweight, |
| 951 | prev_utxos, reservedok=True, |
| 952 | min_witness_weight=110, |
| 953 | excess_as_change=True) |
| 954 | |
| 955 | l1.rpc.connect(l2.info['id'], 'localhost', l2.port) |
| 956 | bump = l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt']) |
| 957 | update = l1.rpc.openchannel_update(chan_id, bump['psbt']) |
| 958 | assert update['commitments_secured'] |
| 959 | |
| 960 | return l1.rpc.signpsbt(update['psbt'])['signed_psbt'] |
| 961 | |
| 962 | signed_psbt = run_retry() |
| 963 | l1.rpc.openchannel_signed(chan_id, signed_psbt) |
| 964 | inflights = only_one(only_one(l1.rpc.listpeers()['peers'])['channels'])['inflight'] |
| 965 | assert inflights[-1]['funding_txid'] not in bitcoind.rpc.getrawmempool() |
| 966 | |
| 967 | cmtmt_txid = only_one(only_one(l1.rpc.listpeers()['peers'])['channels'])['scratch_txid'] |
| 968 | assert cmtmt_txid == inflights[-1]['scratch_txid'] |
nothing calls this directly
no test coverage detected