You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bumpfee.py 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #!/usr/bin/env python3
  2. # Copyright (c) 2016 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. from segwit import send_to_witness
  7. from test_framework.test_framework import BitcoinTestFramework
  8. from test_framework import blocktools
  9. from test_framework.mininode import CTransaction
  10. from test_framework.util import *
  11. import io
  12. # Sequence number that is BIP 125 opt-in and BIP 68-compliant
  13. BIP125_SEQUENCE_NUMBER = 0xfffffffd
  14. WALLET_PASSPHRASE = "test"
  15. WALLET_PASSPHRASE_TIMEOUT = 3600
  16. class BumpFeeTest(BitcoinTestFramework):
  17. def __init__(self):
  18. super().__init__()
  19. self.num_nodes = 2
  20. self.setup_clean_chain = True
  21. def setup_network(self, split=False):
  22. extra_args = [["-prematurewitness", "-walletprematurewitness", "-walletrbf={}".format(i)]
  23. for i in range(self.num_nodes)]
  24. self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args)
  25. # Encrypt wallet for test_locked_wallet_fails test
  26. self.nodes[1].encryptwallet(WALLET_PASSPHRASE)
  27. bitcoind_processes[1].wait()
  28. self.nodes[1] = start_node(1, self.options.tmpdir, extra_args[1])
  29. self.nodes[1].walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
  30. connect_nodes_bi(self.nodes, 0, 1)
  31. self.is_network_split = False
  32. self.sync_all()
  33. def run_test(self):
  34. peer_node, rbf_node = self.nodes
  35. rbf_node_address = rbf_node.getnewaddress()
  36. # fund rbf node with 10 coins of 0.001 btc (100,000 satoshis)
  37. self.log.info("Mining blocks...")
  38. peer_node.generate(110)
  39. self.sync_all()
  40. for i in range(25):
  41. peer_node.sendtoaddress(rbf_node_address, 0.001)
  42. self.sync_all()
  43. peer_node.generate(1)
  44. self.sync_all()
  45. assert_equal(rbf_node.getbalance(), Decimal("0.025"))
  46. self.log.info("Running tests")
  47. dest_address = peer_node.getnewaddress()
  48. test_small_output_fails(rbf_node, dest_address)
  49. test_dust_to_fee(rbf_node, dest_address)
  50. test_simple_bumpfee_succeeds(rbf_node, peer_node, dest_address)
  51. test_segwit_bumpfee_succeeds(rbf_node, dest_address)
  52. test_nonrbf_bumpfee_fails(peer_node, dest_address)
  53. test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address)
  54. test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address)
  55. test_settxfee(rbf_node, dest_address)
  56. test_rebumping(rbf_node, dest_address)
  57. test_rebumping_not_replaceable(rbf_node, dest_address)
  58. test_unconfirmed_not_spendable(rbf_node, rbf_node_address)
  59. test_bumpfee_metadata(rbf_node, dest_address)
  60. test_locked_wallet_fails(rbf_node, dest_address)
  61. self.log.info("Success")
  62. def test_simple_bumpfee_succeeds(rbf_node, peer_node, dest_address):
  63. rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
  64. rbftx = rbf_node.gettransaction(rbfid)
  65. sync_mempools((rbf_node, peer_node))
  66. assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
  67. bumped_tx = rbf_node.bumpfee(rbfid)
  68. assert bumped_tx["fee"] - abs(rbftx["fee"]) > 0
  69. # check that bumped_tx propogates, original tx was evicted and has a wallet conflict
  70. sync_mempools((rbf_node, peer_node))
  71. assert bumped_tx["txid"] in rbf_node.getrawmempool()
  72. assert bumped_tx["txid"] in peer_node.getrawmempool()
  73. assert rbfid not in rbf_node.getrawmempool()
  74. assert rbfid not in peer_node.getrawmempool()
  75. oldwtx = rbf_node.gettransaction(rbfid)
  76. assert len(oldwtx["walletconflicts"]) > 0
  77. # check wallet transaction replaces and replaced_by values
  78. bumpedwtx = rbf_node.gettransaction(bumped_tx["txid"])
  79. assert_equal(oldwtx["replaced_by_txid"], bumped_tx["txid"])
  80. assert_equal(bumpedwtx["replaces_txid"], rbfid)
  81. def test_segwit_bumpfee_succeeds(rbf_node, dest_address):
  82. # Create a transaction with segwit output, then create an RBF transaction
  83. # which spends it, and make sure bumpfee can be called on it.
  84. segwit_in = next(u for u in rbf_node.listunspent() if u["amount"] == Decimal("0.001"))
  85. segwit_out = rbf_node.validateaddress(rbf_node.getnewaddress())
  86. rbf_node.addwitnessaddress(segwit_out["address"])
  87. segwitid = send_to_witness(
  88. use_p2wsh=False,
  89. node=rbf_node,
  90. utxo=segwit_in,
  91. pubkey=segwit_out["pubkey"],
  92. encode_p2sh=False,
  93. amount=Decimal("0.0009"),
  94. sign=True)
  95. rbfraw = rbf_node.createrawtransaction([{
  96. 'txid': segwitid,
  97. 'vout': 0,
  98. "sequence": BIP125_SEQUENCE_NUMBER
  99. }], {dest_address: Decimal("0.0005"),
  100. get_change_address(rbf_node): Decimal("0.0003")})
  101. rbfsigned = rbf_node.signrawtransaction(rbfraw)
  102. rbfid = rbf_node.sendrawtransaction(rbfsigned["hex"])
  103. assert rbfid in rbf_node.getrawmempool()
  104. bumped_tx = rbf_node.bumpfee(rbfid)
  105. assert bumped_tx["txid"] in rbf_node.getrawmempool()
  106. assert rbfid not in rbf_node.getrawmempool()
  107. def test_nonrbf_bumpfee_fails(peer_node, dest_address):
  108. # cannot replace a non RBF transaction (from node which did not enable RBF)
  109. not_rbfid = create_fund_sign_send(peer_node, {dest_address: 0.00090000})
  110. assert_raises_jsonrpc(-4, "not BIP 125 replaceable", peer_node.bumpfee, not_rbfid)
  111. def test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address):
  112. # cannot bump fee unless the tx has only inputs that we own.
  113. # here, the rbftx has a peer_node coin and then adds a rbf_node input
  114. # Note that this test depends upon the RPC code checking input ownership prior to change outputs
  115. # (since it can't use fundrawtransaction, it lacks a proper change output)
  116. utxos = [node.listunspent()[-1] for node in (rbf_node, peer_node)]
  117. inputs = [{
  118. "txid": utxo["txid"],
  119. "vout": utxo["vout"],
  120. "address": utxo["address"],
  121. "sequence": BIP125_SEQUENCE_NUMBER
  122. } for utxo in utxos]
  123. output_val = sum(utxo["amount"] for utxo in utxos) - Decimal("0.001")
  124. rawtx = rbf_node.createrawtransaction(inputs, {dest_address: output_val})
  125. signedtx = rbf_node.signrawtransaction(rawtx)
  126. signedtx = peer_node.signrawtransaction(signedtx["hex"])
  127. rbfid = rbf_node.sendrawtransaction(signedtx["hex"])
  128. assert_raises_jsonrpc(-4, "Transaction contains inputs that don't belong to this wallet",
  129. rbf_node.bumpfee, rbfid)
  130. def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address):
  131. # cannot bump fee if the transaction has a descendant
  132. # parent is send-to-self, so we don't have to check which output is change when creating the child tx
  133. parent_id = create_fund_sign_send(rbf_node, {rbf_node_address: 0.00050000})
  134. tx = rbf_node.createrawtransaction([{"txid": parent_id, "vout": 0}], {dest_address: 0.00020000})
  135. tx = rbf_node.signrawtransaction(tx)
  136. txid = rbf_node.sendrawtransaction(tx["hex"])
  137. assert_raises_jsonrpc(-8, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id)
  138. def test_small_output_fails(rbf_node, dest_address):
  139. # cannot bump fee with a too-small output
  140. rbfid = spend_one_input(rbf_node,
  141. Decimal("0.00100000"),
  142. {dest_address: 0.00080000,
  143. get_change_address(rbf_node): Decimal("0.00010000")})
  144. rbf_node.bumpfee(rbfid, {"totalFee": 20000})
  145. rbfid = spend_one_input(rbf_node,
  146. Decimal("0.00100000"),
  147. {dest_address: 0.00080000,
  148. get_change_address(rbf_node): Decimal("0.00010000")})
  149. assert_raises_jsonrpc(-4, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 20001})
  150. def test_dust_to_fee(rbf_node, dest_address):
  151. # check that if output is reduced to dust, it will be converted to fee
  152. # the bumped tx sets fee=9900, but it converts to 10,000
  153. rbfid = spend_one_input(rbf_node,
  154. Decimal("0.00100000"),
  155. {dest_address: 0.00080000,
  156. get_change_address(rbf_node): Decimal("0.00010000")})
  157. fulltx = rbf_node.getrawtransaction(rbfid, 1)
  158. bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 19900})
  159. full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1)
  160. assert_equal(bumped_tx["fee"], Decimal("0.00020000"))
  161. assert_equal(len(fulltx["vout"]), 2)
  162. assert_equal(len(full_bumped_tx["vout"]), 1) #change output is eliminated
  163. def test_settxfee(rbf_node, dest_address):
  164. # check that bumpfee reacts correctly to the use of settxfee (paytxfee)
  165. # increase feerate by 2.5x, test that fee increased at least 2x
  166. rbf_node.settxfee(Decimal("0.00001000"))
  167. rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
  168. rbftx = rbf_node.gettransaction(rbfid)
  169. rbf_node.settxfee(Decimal("0.00002500"))
  170. bumped_tx = rbf_node.bumpfee(rbfid)
  171. assert bumped_tx["fee"] > 2 * abs(rbftx["fee"])
  172. rbf_node.settxfee(Decimal("0.00000000")) # unset paytxfee
  173. def test_rebumping(rbf_node, dest_address):
  174. # check that re-bumping the original tx fails, but bumping the bumper succeeds
  175. rbf_node.settxfee(Decimal("0.00001000"))
  176. rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
  177. bumped = rbf_node.bumpfee(rbfid, {"totalFee": 1000})
  178. assert_raises_jsonrpc(-4, "already bumped", rbf_node.bumpfee, rbfid, {"totalFee": 2000})
  179. rbf_node.bumpfee(bumped["txid"], {"totalFee": 2000})
  180. def test_rebumping_not_replaceable(rbf_node, dest_address):
  181. # check that re-bumping a non-replaceable bump tx fails
  182. rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
  183. bumped = rbf_node.bumpfee(rbfid, {"totalFee": 10000, "replaceable": False})
  184. assert_raises_jsonrpc(-4, "Transaction is not BIP 125 replaceable", rbf_node.bumpfee, bumped["txid"],
  185. {"totalFee": 20000})
  186. def test_unconfirmed_not_spendable(rbf_node, rbf_node_address):
  187. # check that unconfirmed outputs from bumped transactions are not spendable
  188. rbfid = create_fund_sign_send(rbf_node, {rbf_node_address: 0.00090000})
  189. rbftx = rbf_node.gettransaction(rbfid)["hex"]
  190. assert rbfid in rbf_node.getrawmempool()
  191. bumpid = rbf_node.bumpfee(rbfid)["txid"]
  192. assert bumpid in rbf_node.getrawmempool()
  193. assert rbfid not in rbf_node.getrawmempool()
  194. # check that outputs from the bump transaction are not spendable
  195. # due to the replaces_txid check in CWallet::AvailableCoins
  196. assert_equal([t for t in rbf_node.listunspent(minconf=0, include_unsafe=False) if t["txid"] == bumpid], [])
  197. # submit a block with the rbf tx to clear the bump tx out of the mempool,
  198. # then call abandon to make sure the wallet doesn't attempt to resubmit the
  199. # bump tx, then invalidate the block so the rbf tx will be put back in the
  200. # mempool. this makes it possible to check whether the rbf tx outputs are
  201. # spendable before the rbf tx is confirmed.
  202. block = submit_block_with_tx(rbf_node, rbftx)
  203. rbf_node.abandontransaction(bumpid)
  204. rbf_node.invalidateblock(block.hash)
  205. assert bumpid not in rbf_node.getrawmempool()
  206. assert rbfid in rbf_node.getrawmempool()
  207. # check that outputs from the rbf tx are not spendable before the
  208. # transaction is confirmed, due to the replaced_by_txid check in
  209. # CWallet::AvailableCoins
  210. assert_equal([t for t in rbf_node.listunspent(minconf=0, include_unsafe=False) if t["txid"] == rbfid], [])
  211. # check that the main output from the rbf tx is spendable after confirmed
  212. rbf_node.generate(1)
  213. assert_equal(
  214. sum(1 for t in rbf_node.listunspent(minconf=0, include_unsafe=False)
  215. if t["txid"] == rbfid and t["address"] == rbf_node_address and t["spendable"]), 1)
  216. def test_bumpfee_metadata(rbf_node, dest_address):
  217. rbfid = rbf_node.sendtoaddress(dest_address, 0.00090000, "comment value", "to value")
  218. bumped_tx = rbf_node.bumpfee(rbfid)
  219. bumped_wtx = rbf_node.gettransaction(bumped_tx["txid"])
  220. assert_equal(bumped_wtx["comment"], "comment value")
  221. assert_equal(bumped_wtx["to"], "to value")
  222. def test_locked_wallet_fails(rbf_node, dest_address):
  223. rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
  224. rbf_node.walletlock()
  225. assert_raises_jsonrpc(-13, "Please enter the wallet passphrase with walletpassphrase first.",
  226. rbf_node.bumpfee, rbfid)
  227. def create_fund_sign_send(node, outputs):
  228. rawtx = node.createrawtransaction([], outputs)
  229. fundtx = node.fundrawtransaction(rawtx)
  230. signedtx = node.signrawtransaction(fundtx["hex"])
  231. txid = node.sendrawtransaction(signedtx["hex"])
  232. return txid
  233. def spend_one_input(node, input_amount, outputs):
  234. input = dict(sequence=BIP125_SEQUENCE_NUMBER, **next(u for u in node.listunspent() if u["amount"] == input_amount))
  235. rawtx = node.createrawtransaction([input], outputs)
  236. signedtx = node.signrawtransaction(rawtx)
  237. txid = node.sendrawtransaction(signedtx["hex"])
  238. return txid
  239. def get_change_address(node):
  240. """Get a wallet change address.
  241. There is no wallet RPC to access unused change addresses, so this creates a
  242. dummy transaction, calls fundrawtransaction to give add an input and change
  243. output, then returns the change address."""
  244. dest_address = node.getnewaddress()
  245. dest_amount = Decimal("0.00012345")
  246. rawtx = node.createrawtransaction([], {dest_address: dest_amount})
  247. fundtx = node.fundrawtransaction(rawtx)
  248. info = node.decoderawtransaction(fundtx["hex"])
  249. return next(address for out in info["vout"]
  250. if out["value"] != dest_amount for address in out["scriptPubKey"]["addresses"])
  251. def submit_block_with_tx(node, tx):
  252. ctx = CTransaction()
  253. ctx.deserialize(io.BytesIO(hex_str_to_bytes(tx)))
  254. tip = node.getbestblockhash()
  255. height = node.getblockcount() + 1
  256. block_time = node.getblockheader(tip)["mediantime"] + 1
  257. block = blocktools.create_block(int(tip, 16), blocktools.create_coinbase(height), block_time)
  258. block.vtx.append(ctx)
  259. block.rehash()
  260. block.hashMerkleRoot = block.calc_merkle_root()
  261. block.solve()
  262. node.submitblock(bytes_to_hex_str(block.serialize(True)))
  263. return block
  264. if __name__ == "__main__":
  265. BumpFeeTest().main()