1#!/usr/bin/env python3
2# Copyright (c) 2016-2018 The Bitcoin Core developers
3# Distributed under the MIT software license, see the accompanying
4# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5"""Test the bumpfee RPC.
6
7Verifies that the bumpfee RPC creates replacement transactions successfully when
8its preconditions are met, and returns appropriate errors in other cases.
9
10This module consists of around a dozen individual test cases implemented in the
11top-level functions named as test_<test_case_description>. The test functions
12can be disabled or reordered if needed for debugging. If new test cases are
13added in the future, they should try to follow the same convention and not
14make assumptions about execution order.
15"""
16from decimal import Decimal
17import io
18
19from test_framework.blocktools import add_witness_commitment, create_block, create_coinbase, send_to_witness
20from test_framework.messages import BIP125_SEQUENCE_NUMBER, CTransaction
21from test_framework.test_framework import BitcoinTestFramework, SkipTest
22from test_framework.util import assert_equal, assert_greater_than, assert_raises_rpc_error, bytes_to_hex_str, connect_nodes_bi, hex_str_to_bytes, sync_mempools
23
24WALLET_PASSPHRASE = "test"
25WALLET_PASSPHRASE_TIMEOUT = 3600
26
27class BumpFeeTest(BitcoinTestFramework):
28    def set_test_params(self):
29        self.num_nodes = 2
30        self.setup_clean_chain = True
31        self.extra_args = [[
32            "-walletrbf={}".format(i),
33            "-mintxfee=0.00002",
34            "-mempoolreplacement=1",
35        ] for i in range(self.num_nodes)]
36
37    def skip_test_if_missing_module(self):
38        self.skip_if_no_wallet()
39
40    def run_test(self):
41        if True:
42            raise SkipTest("Litecoin doesn't support RBF.")
43
44        # Encrypt wallet for test_locked_wallet_fails test
45        self.nodes[1].encryptwallet(WALLET_PASSPHRASE)
46        self.nodes[1].walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
47
48        connect_nodes_bi(self.nodes, 0, 1)
49        self.sync_all()
50
51        peer_node, rbf_node = self.nodes
52        rbf_node_address = rbf_node.getnewaddress()
53
54        # fund rbf node with 10 coins of 0.001 btc (100,000 satoshis)
55        self.log.info("Mining blocks...")
56        peer_node.generate(110)
57        self.sync_all()
58        for i in range(25):
59            peer_node.sendtoaddress(rbf_node_address, 0.001)
60        self.sync_all()
61        peer_node.generate(1)
62        self.sync_all()
63        assert_equal(rbf_node.getbalance(), Decimal("0.025"))
64
65        self.log.info("Running tests")
66        dest_address = peer_node.getnewaddress()
67        test_simple_bumpfee_succeeds(rbf_node, peer_node, dest_address)
68        test_segwit_bumpfee_succeeds(rbf_node, dest_address)
69        test_nonrbf_bumpfee_fails(peer_node, dest_address)
70        test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address)
71        test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address)
72        test_small_output_fails(rbf_node, dest_address)
73        test_dust_to_fee(rbf_node, dest_address)
74        test_settxfee(rbf_node, dest_address)
75        test_rebumping(rbf_node, dest_address)
76        test_rebumping_not_replaceable(rbf_node, dest_address)
77        test_unconfirmed_not_spendable(rbf_node, rbf_node_address)
78        test_bumpfee_metadata(rbf_node, dest_address)
79        test_locked_wallet_fails(rbf_node, dest_address)
80        test_maxtxfee_fails(self, rbf_node, dest_address)
81        self.log.info("Success")
82
83
84def test_simple_bumpfee_succeeds(rbf_node, peer_node, dest_address):
85    rbfid = spend_one_input(rbf_node, dest_address)
86    rbftx = rbf_node.gettransaction(rbfid)
87    sync_mempools((rbf_node, peer_node))
88    assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
89    bumped_tx = rbf_node.bumpfee(rbfid)
90    assert_equal(bumped_tx["errors"], [])
91    assert bumped_tx["fee"] - abs(rbftx["fee"]) > 0
92    # check that bumped_tx propagates, original tx was evicted and has a wallet conflict
93    sync_mempools((rbf_node, peer_node))
94    assert bumped_tx["txid"] in rbf_node.getrawmempool()
95    assert bumped_tx["txid"] in peer_node.getrawmempool()
96    assert rbfid not in rbf_node.getrawmempool()
97    assert rbfid not in peer_node.getrawmempool()
98    oldwtx = rbf_node.gettransaction(rbfid)
99    assert len(oldwtx["walletconflicts"]) > 0
100    # check wallet transaction replaces and replaced_by values
101    bumpedwtx = rbf_node.gettransaction(bumped_tx["txid"])
102    assert_equal(oldwtx["replaced_by_txid"], bumped_tx["txid"])
103    assert_equal(bumpedwtx["replaces_txid"], rbfid)
104
105
106def test_segwit_bumpfee_succeeds(rbf_node, dest_address):
107    # Create a transaction with segwit output, then create an RBF transaction
108    # which spends it, and make sure bumpfee can be called on it.
109
110    segwit_in = next(u for u in rbf_node.listunspent() if u["amount"] == Decimal("0.001"))
111    segwit_out = rbf_node.getaddressinfo(rbf_node.getnewaddress(address_type='p2sh-segwit'))
112    segwitid = send_to_witness(
113        use_p2wsh=False,
114        node=rbf_node,
115        utxo=segwit_in,
116        pubkey=segwit_out["pubkey"],
117        encode_p2sh=False,
118        amount=Decimal("0.0009"),
119        sign=True)
120
121    rbfraw = rbf_node.createrawtransaction([{
122        'txid': segwitid,
123        'vout': 0,
124        "sequence": BIP125_SEQUENCE_NUMBER
125    }], {dest_address: Decimal("0.0005"),
126         rbf_node.getrawchangeaddress(): Decimal("0.0003")})
127    rbfsigned = rbf_node.signrawtransactionwithwallet(rbfraw)
128    rbfid = rbf_node.sendrawtransaction(rbfsigned["hex"])
129    assert rbfid in rbf_node.getrawmempool()
130
131    bumped_tx = rbf_node.bumpfee(rbfid)
132    assert bumped_tx["txid"] in rbf_node.getrawmempool()
133    assert rbfid not in rbf_node.getrawmempool()
134
135
136def test_nonrbf_bumpfee_fails(peer_node, dest_address):
137    # cannot replace a non RBF transaction (from node which did not enable RBF)
138    not_rbfid = peer_node.sendtoaddress(dest_address, Decimal("0.00090000"))
139    assert_raises_rpc_error(-4, "not BIP 125 replaceable", peer_node.bumpfee, not_rbfid)
140
141
142def test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address):
143    # cannot bump fee unless the tx has only inputs that we own.
144    # here, the rbftx has a peer_node coin and then adds a rbf_node input
145    # Note that this test depends upon the RPC code checking input ownership prior to change outputs
146    # (since it can't use fundrawtransaction, it lacks a proper change output)
147    utxos = [node.listunspent()[-1] for node in (rbf_node, peer_node)]
148    inputs = [{
149        "txid": utxo["txid"],
150        "vout": utxo["vout"],
151        "address": utxo["address"],
152        "sequence": BIP125_SEQUENCE_NUMBER
153    } for utxo in utxos]
154    output_val = sum(utxo["amount"] for utxo in utxos) - Decimal("0.001")
155    rawtx = rbf_node.createrawtransaction(inputs, {dest_address: output_val})
156    signedtx = rbf_node.signrawtransactionwithwallet(rawtx)
157    signedtx = peer_node.signrawtransactionwithwallet(signedtx["hex"])
158    rbfid = rbf_node.sendrawtransaction(signedtx["hex"])
159    assert_raises_rpc_error(-4, "Transaction contains inputs that don't belong to this wallet",
160                            rbf_node.bumpfee, rbfid)
161
162
163def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address):
164    # cannot bump fee if the transaction has a descendant
165    # parent is send-to-self, so we don't have to check which output is change when creating the child tx
166    parent_id = spend_one_input(rbf_node, rbf_node_address)
167    tx = rbf_node.createrawtransaction([{"txid": parent_id, "vout": 0}], {dest_address: 0.00020000})
168    tx = rbf_node.signrawtransactionwithwallet(tx)
169    rbf_node.sendrawtransaction(tx["hex"])
170    assert_raises_rpc_error(-8, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id)
171
172
173def test_small_output_fails(rbf_node, dest_address):
174    # cannot bump fee with a too-small output
175    rbfid = spend_one_input(rbf_node, dest_address)
176    rbf_node.bumpfee(rbfid, {"totalFee": 50000})
177
178    rbfid = spend_one_input(rbf_node, dest_address)
179    assert_raises_rpc_error(-4, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 50001})
180
181
182def test_dust_to_fee(rbf_node, dest_address):
183    # check that if output is reduced to dust, it will be converted to fee
184    # the bumped tx sets fee=49,900, but it converts to 50,000
185    rbfid = spend_one_input(rbf_node, dest_address)
186    fulltx = rbf_node.getrawtransaction(rbfid, 1)
187    # (32-byte p2sh-pwpkh output size + 148 p2pkh spend estimate) * 10k(discard_rate) / 1000 = 1800
188    # P2SH outputs are slightly "over-discarding" due to the IsDust calculation assuming it will
189    # be spent as a P2PKH.
190    bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 50000 - 1800})
191    full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1)
192    assert_equal(bumped_tx["fee"], Decimal("0.00050000"))
193    assert_equal(len(fulltx["vout"]), 2)
194    assert_equal(len(full_bumped_tx["vout"]), 1)  # change output is eliminated
195
196
197def test_settxfee(rbf_node, dest_address):
198    assert_raises_rpc_error(-8, "txfee cannot be less than min relay tx fee", rbf_node.settxfee, Decimal('0.000005'))
199    assert_raises_rpc_error(-8, "txfee cannot be less than wallet min fee", rbf_node.settxfee, Decimal('0.000015'))
200    # check that bumpfee reacts correctly to the use of settxfee (paytxfee)
201    rbfid = spend_one_input(rbf_node, dest_address)
202    requested_feerate = Decimal("0.00025000")
203    rbf_node.settxfee(requested_feerate)
204    bumped_tx = rbf_node.bumpfee(rbfid)
205    actual_feerate = bumped_tx["fee"] * 1000 / rbf_node.getrawtransaction(bumped_tx["txid"], True)["vsize"]
206    # Assert that the difference between the requested feerate and the actual
207    # feerate of the bumped transaction is small.
208    assert_greater_than(Decimal("0.00001000"), abs(requested_feerate - actual_feerate))
209    rbf_node.settxfee(Decimal("0.00000000"))  # unset paytxfee
210
211
212def test_maxtxfee_fails(test, rbf_node, dest_address):
213    test.restart_node(1, ['-maxtxfee=0.00003'] + test.extra_args[1])
214    rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
215    rbfid = spend_one_input(rbf_node, dest_address)
216    assert_raises_rpc_error(-4, "Specified or calculated fee 0.0000332 is too high (cannot be higher than maxTxFee 0.00003)", rbf_node.bumpfee, rbfid)
217    test.restart_node(1, test.extra_args[1])
218    rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
219
220
221def test_rebumping(rbf_node, dest_address):
222    # check that re-bumping the original tx fails, but bumping the bumper succeeds
223    rbfid = spend_one_input(rbf_node, dest_address)
224    bumped = rbf_node.bumpfee(rbfid, {"totalFee": 2000})
225    assert_raises_rpc_error(-4, "already bumped", rbf_node.bumpfee, rbfid, {"totalFee": 3000})
226    rbf_node.bumpfee(bumped["txid"], {"totalFee": 3000})
227
228
229def test_rebumping_not_replaceable(rbf_node, dest_address):
230    # check that re-bumping a non-replaceable bump tx fails
231    rbfid = spend_one_input(rbf_node, dest_address)
232    bumped = rbf_node.bumpfee(rbfid, {"totalFee": 10000, "replaceable": False})
233    assert_raises_rpc_error(-4, "Transaction is not BIP 125 replaceable", rbf_node.bumpfee, bumped["txid"],
234                            {"totalFee": 20000})
235
236
237def test_unconfirmed_not_spendable(rbf_node, rbf_node_address):
238    # check that unconfirmed outputs from bumped transactions are not spendable
239    rbfid = spend_one_input(rbf_node, rbf_node_address)
240    rbftx = rbf_node.gettransaction(rbfid)["hex"]
241    assert rbfid in rbf_node.getrawmempool()
242    bumpid = rbf_node.bumpfee(rbfid)["txid"]
243    assert bumpid in rbf_node.getrawmempool()
244    assert rbfid not in rbf_node.getrawmempool()
245
246    # check that outputs from the bump transaction are not spendable
247    # due to the replaces_txid check in CWallet::AvailableCoins
248    assert_equal([t for t in rbf_node.listunspent(minconf=0, include_unsafe=False) if t["txid"] == bumpid], [])
249
250    # submit a block with the rbf tx to clear the bump tx out of the mempool,
251    # then invalidate the block so the rbf tx will be put back in the mempool.
252    # This makes it possible to check whether the rbf tx outputs are
253    # spendable before the rbf tx is confirmed.
254    block = submit_block_with_tx(rbf_node, rbftx)
255    # Can not abandon conflicted tx
256    assert_raises_rpc_error(-5, 'Transaction not eligible for abandonment', lambda: rbf_node.abandontransaction(txid=bumpid))
257    rbf_node.invalidateblock(block.hash)
258    # Call abandon to make sure the wallet doesn't attempt to resubmit
259    # the bump tx and hope the wallet does not rebroadcast before we call.
260    rbf_node.abandontransaction(bumpid)
261    assert bumpid not in rbf_node.getrawmempool()
262    assert rbfid in rbf_node.getrawmempool()
263
264    # check that outputs from the rbf tx are not spendable before the
265    # transaction is confirmed, due to the replaced_by_txid check in
266    # CWallet::AvailableCoins
267    assert_equal([t for t in rbf_node.listunspent(minconf=0, include_unsafe=False) if t["txid"] == rbfid], [])
268
269    # check that the main output from the rbf tx is spendable after confirmed
270    rbf_node.generate(1)
271    assert_equal(
272        sum(1 for t in rbf_node.listunspent(minconf=0, include_unsafe=False)
273            if t["txid"] == rbfid and t["address"] == rbf_node_address and t["spendable"]), 1)
274
275
276def test_bumpfee_metadata(rbf_node, dest_address):
277    rbfid = rbf_node.sendtoaddress(dest_address, Decimal("0.00100000"), "comment value", "to value")
278    bumped_tx = rbf_node.bumpfee(rbfid)
279    bumped_wtx = rbf_node.gettransaction(bumped_tx["txid"])
280    assert_equal(bumped_wtx["comment"], "comment value")
281    assert_equal(bumped_wtx["to"], "to value")
282
283
284def test_locked_wallet_fails(rbf_node, dest_address):
285    rbfid = spend_one_input(rbf_node, dest_address)
286    rbf_node.walletlock()
287    assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first.",
288                            rbf_node.bumpfee, rbfid)
289
290
291def spend_one_input(node, dest_address):
292    tx_input = dict(
293        sequence=BIP125_SEQUENCE_NUMBER, **next(u for u in node.listunspent() if u["amount"] == Decimal("0.00100000")))
294    rawtx = node.createrawtransaction(
295        [tx_input], {dest_address: Decimal("0.00050000"),
296                     node.getrawchangeaddress(): Decimal("0.00049000")})
297    signedtx = node.signrawtransactionwithwallet(rawtx)
298    txid = node.sendrawtransaction(signedtx["hex"])
299    return txid
300
301
302def submit_block_with_tx(node, tx):
303    ctx = CTransaction()
304    ctx.deserialize(io.BytesIO(hex_str_to_bytes(tx)))
305
306    tip = node.getbestblockhash()
307    height = node.getblockcount() + 1
308    block_time = node.getblockheader(tip)["mediantime"] + 1
309    block = create_block(int(tip, 16), create_coinbase(height), block_time, version=0x20000000)
310    block.vtx.append(ctx)
311    block.rehash()
312    block.hashMerkleRoot = block.calc_merkle_root()
313    add_witness_commitment(block)
314    block.solve()
315    node.submitblock(bytes_to_hex_str(block.serialize(True)))
316    return block
317
318
319if __name__ == "__main__":
320    BumpFeeTest().main()
321