From 30ec8cbf8e5f49625b2edfb0c3b41711b2fcd073 Mon Sep 17 00:00:00 2001 From: niftynei Date: Tue, 31 Oct 2023 16:36:35 -0500 Subject: [PATCH] dualfund, test: add test for dropping to chain during RBF Here we make sure we can drop the initial tx to chain, and that an inflight txid that's missing its commitment sigs is properly ignored. --- tests/test_opening.py | 64 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tests/test_opening.py b/tests/test_opening.py index 753087157..3d92e0631 100644 --- a/tests/test_opening.py +++ b/tests/test_opening.py @@ -1031,6 +1031,70 @@ def test_rbf_reconnect_tx_sigs(node_factory, bitcoind, chainparams): assert l1_funding_txid == l2_funding_txid +@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') +@pytest.mark.openchannel('v2') +def test_rbf_to_chain_before_commit(node_factory, bitcoind, chainparams): + disconnects = ['=WIRE_TX_ADD_INPUT', # Initial funding succeeds + '=WIRE_COMMITMENT_SIGNED', + '-WIRE_COMMITMENT_SIGNED'] + l1, l2 = node_factory.get_nodes(2, + opts=[{'disconnect': disconnects, + 'may_reconnect': True, + 'dev-no-reconnect': None}, + {'may_reconnect': True, + 'dev-no-reconnect': None, + 'allow_broken_log': True}]) + + l1.rpc.connect(l2.info['id'], 'localhost', l2.port) + amount = 2**24 + chan_amount = 100000 + bitcoind.rpc.sendtoaddress(l1.rpc.newaddr()['bech32'], amount / 10**8 + 0.01) + bitcoind.generate_block(1) + # Wait for it to arrive. + wait_for(lambda: len(l1.rpc.listfunds()['outputs']) > 0) + + res = l1.rpc.fundchannel(l2.info['id'], chan_amount) + chan_id = res['channel_id'] + vins = bitcoind.rpc.decoderawtransaction(res['tx'])['vin'] + assert(only_one(vins)) + prev_utxos = ["{}:{}".format(vins[0]['txid'], vins[0]['vout'])] + + # Check that we're waiting for lockin + l1.daemon.wait_for_log(' to DUALOPEND_AWAITING_LOCKIN') + + # rbf the lease with a higher amount + rate = int(find_next_feerate(l1, l2)[:-5]) + # We 4x the feerate to beat the min-relay fee + next_feerate = '{}perkw'.format(rate * 4) + + # Initiate an RBF + startweight = 42 + 172 # base weight, funding output + initpsbt = l1.rpc.utxopsbt(chan_amount, next_feerate, startweight, + prev_utxos, reservedok=True, + min_witness_weight=110, + excess_as_change=True) + + # Peers try RBF, break on initial COMMITMENT_SIGNED + bump = l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt']) + with pytest.raises(RpcError): + l1.rpc.openchannel_update(chan_id, bump['psbt']) + wait_for(lambda: l1.rpc.getpeer(l2.info['id'])['connected'] is False) + + # We don't have the commtiments yet, there's no scratch_txid + inflights = only_one(l1.rpc.listpeerchannels()['channels'])['inflight'] + assert len(inflights) == 2 + assert 'scratch_txid' not in inflights[1] + + # Close the channel! + l1.rpc.close(chan_id, 1) + l1.daemon.wait_for_logs(['Broadcasting txid {}'.format(inflights[0]['scratch_txid']), + 'sendrawtx exit 0']) + + wait_for(lambda: inflights[0]['scratch_txid'] in bitcoind.rpc.getrawmempool()) + assert inflights[0]['funding_txid'] in bitcoind.rpc.getrawmempool() + assert inflights[1]['funding_txid'] not in bitcoind.rpc.getrawmempool() + + @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_rbf_no_overlap(node_factory, bitcoind, chainparams):