wallet_create_tx.py
1 #!/usr/bin/env python3 2 # Copyright (c) 2018-2022 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 6 from test_framework.test_framework import BitcoinTestFramework 7 from test_framework.util import ( 8 assert_equal, 9 assert_raises_rpc_error, 10 ) 11 from test_framework.blocktools import ( 12 TIME_GENESIS_BLOCK, 13 ) 14 15 16 class CreateTxWalletTest(BitcoinTestFramework): 17 def add_options(self, parser): 18 self.add_wallet_options(parser) 19 20 def set_test_params(self): 21 self.setup_clean_chain = True 22 self.num_nodes = 1 23 24 def skip_test_if_missing_module(self): 25 self.skip_if_no_wallet() 26 27 def run_test(self): 28 self.log.info('Create some old blocks') 29 self.nodes[0].setmocktime(TIME_GENESIS_BLOCK) 30 self.generate(self.nodes[0], 200) 31 self.nodes[0].setmocktime(0) 32 33 self.test_anti_fee_sniping() 34 self.test_tx_size_too_large() 35 self.test_create_too_long_mempool_chain() 36 37 def test_anti_fee_sniping(self): 38 self.log.info('Check that we have some (old) blocks and that anti-fee-sniping is disabled') 39 assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 200) 40 txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) 41 tx = self.nodes[0].gettransaction(txid=txid, verbose=True)['decoded'] 42 assert_equal(tx['locktime'], 0) 43 44 self.log.info('Check that anti-fee-sniping is enabled when we mine a recent block') 45 self.generate(self.nodes[0], 1) 46 txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) 47 tx = self.nodes[0].gettransaction(txid=txid, verbose=True)['decoded'] 48 assert 0 < tx['locktime'] <= 201 49 50 def test_tx_size_too_large(self): 51 # More than 10kB of outputs, so that we hit -maxtxfee with a high feerate 52 outputs = {self.nodes[0].getnewaddress(address_type='bech32'): 0.000025 for _ in range(400)} 53 raw_tx = self.nodes[0].createrawtransaction(inputs=[], outputs=outputs) 54 55 for fee_setting in ['-minrelaytxfee=0.01', '-mintxfee=0.01', '-paytxfee=0.01']: 56 self.log.info('Check maxtxfee in combination with {}'.format(fee_setting)) 57 self.restart_node(0, extra_args=[fee_setting]) 58 assert_raises_rpc_error( 59 -6, 60 "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", 61 lambda: self.nodes[0].sendmany(dummy="", amounts=outputs), 62 ) 63 assert_raises_rpc_error( 64 -4, 65 "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", 66 lambda: self.nodes[0].fundrawtransaction(hexstring=raw_tx), 67 ) 68 69 self.log.info('Check maxtxfee in combination with settxfee') 70 self.restart_node(0) 71 self.nodes[0].settxfee(0.01) 72 assert_raises_rpc_error( 73 -6, 74 "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", 75 lambda: self.nodes[0].sendmany(dummy="", amounts=outputs), 76 ) 77 assert_raises_rpc_error( 78 -4, 79 "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", 80 lambda: self.nodes[0].fundrawtransaction(hexstring=raw_tx), 81 ) 82 self.nodes[0].settxfee(0) 83 84 def test_create_too_long_mempool_chain(self): 85 self.log.info('Check too-long mempool chain error') 86 df_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name) 87 88 self.nodes[0].createwallet("too_long") 89 test_wallet = self.nodes[0].get_wallet_rpc("too_long") 90 91 tx_data = df_wallet.send(outputs=[{test_wallet.getnewaddress(): 25}], options={"change_position": 0}) 92 txid = tx_data['txid'] 93 vout = 1 94 95 self.nodes[0].syncwithvalidationinterfacequeue() 96 options = {"change_position": 0, "add_inputs": False} 97 for i in range(1, 25): 98 options['inputs'] = [{'txid': txid, 'vout': vout}] 99 tx_data = test_wallet.send(outputs=[{test_wallet.getnewaddress(): 25 - i}], options=options) 100 txid = tx_data['txid'] 101 102 # Sending one more chained transaction will fail 103 options = {"minconf": 0, "include_unsafe": True, 'add_inputs': True} 104 assert_raises_rpc_error(-4, "Unconfirmed UTXOs are available, but spending them creates a chain of transactions that will be rejected by the mempool", 105 test_wallet.send, outputs=[{test_wallet.getnewaddress(): 0.3}], options=options) 106 107 test_wallet.unloadwallet() 108 109 110 if __name__ == '__main__': 111 CreateTxWalletTest().main()