wallet_createwallet.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 """Test createwallet arguments. 6 """ 7 8 from test_framework.descriptors import descsum_create 9 from test_framework.test_framework import BitcoinTestFramework 10 from test_framework.util import ( 11 assert_equal, 12 assert_raises_rpc_error, 13 wallet_importprivkey, 14 ) 15 from test_framework.wallet_util import generate_keypair, WalletUnlock 16 17 18 EMPTY_PASSPHRASE_MSG = "Empty string given as passphrase, wallet will not be encrypted." 19 20 21 class CreateWalletTest(BitcoinTestFramework): 22 def set_test_params(self): 23 self.num_nodes = 1 24 25 def skip_test_if_missing_module(self): 26 self.skip_if_no_wallet() 27 28 def run_test(self): 29 node = self.nodes[0] 30 31 self.log.info("Run createwallet with invalid parameters.") 32 # Run createwallet with invalid parameters. This must not prevent a new wallet with the same name from being created with the correct parameters. 33 assert_raises_rpc_error(-4, "Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.", 34 self.nodes[0].createwallet, wallet_name='w0', disable_private_keys=True, passphrase="passphrase") 35 36 self.nodes[0].createwallet(wallet_name='w0') 37 w0 = node.get_wallet_rpc('w0') 38 address1 = w0.getnewaddress() 39 40 self.log.info("Test disableprivatekeys creation.") 41 self.nodes[0].createwallet(wallet_name='w1', disable_private_keys=True) 42 w1 = node.get_wallet_rpc('w1') 43 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w1.getnewaddress) 44 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w1.getrawchangeaddress) 45 import_res = w1.importdescriptors([{"desc": w0.getaddressinfo(address1)['desc'], "timestamp": "now"}]) 46 assert_equal(import_res[0]["success"], True) 47 assert_equal(sorted(w1.getwalletinfo()["flags"]), sorted(["last_hardened_xpub_cached", "descriptor_wallet", "disable_private_keys"])) 48 49 self.log.info('Test that private keys cannot be imported') 50 privkey, pubkey = generate_keypair(wif=True) 51 result = w1.importdescriptors([{'desc': descsum_create('wpkh(' + privkey + ')'), 'timestamp': 'now'}]) 52 assert not result[0]['success'] 53 assert 'warnings' not in result[0] 54 assert_equal(result[0]['error']['code'], -4) 55 assert_equal(result[0]['error']['message'], 'Cannot import private keys to a wallet with private keys disabled') 56 57 self.log.info("Test blank creation with private keys disabled.") 58 self.nodes[0].createwallet(wallet_name='w2', disable_private_keys=True, blank=True) 59 w2 = node.get_wallet_rpc('w2') 60 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w2.getnewaddress) 61 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w2.getrawchangeaddress) 62 import_res = w2.importdescriptors([{"desc": w0.getaddressinfo(address1)['desc'], "timestamp": "now"}]) 63 assert_equal(import_res[0]["success"], True) 64 65 self.log.info("Test blank creation with private keys enabled.") 66 self.nodes[0].createwallet(wallet_name='w3', disable_private_keys=False, blank=True) 67 w3 = node.get_wallet_rpc('w3') 68 assert_equal(w3.getwalletinfo()['keypoolsize'], 0) 69 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getnewaddress) 70 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getrawchangeaddress) 71 # Import private key 72 wallet_importprivkey(w3, generate_keypair(wif=True)[0], "now") 73 # Imported private keys are currently ignored by the keypool 74 assert_equal(w3.getwalletinfo()['keypoolsize'], 0) 75 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getnewaddress) 76 # Set the seed 77 w3.importdescriptors([{ 78 'desc': descsum_create('wpkh(tprv8ZgxMBicQKsPcwuZGKp8TeWppSuLMiLe2d9PupB14QpPeQsqoj3LneJLhGHH13xESfvASyd4EFLJvLrG8b7DrLxEuV7hpF9uUc6XruKA1Wq/0h/*)'), 79 'timestamp': 'now', 80 'active': True 81 }, 82 { 83 'desc': descsum_create('wpkh(tprv8ZgxMBicQKsPcwuZGKp8TeWppSuLMiLe2d9PupB14QpPeQsqoj3LneJLhGHH13xESfvASyd4EFLJvLrG8b7DrLxEuV7hpF9uUc6XruKA1Wq/1h/*)'), 84 'timestamp': 'now', 85 'active': True, 86 'internal': True 87 }]) 88 assert_equal(w3.getwalletinfo()['keypoolsize'], 1) 89 w3.getnewaddress() 90 w3.getrawchangeaddress() 91 92 self.log.info("Test blank creation with privkeys enabled and then encryption") 93 self.nodes[0].createwallet(wallet_name='w4', disable_private_keys=False, blank=True) 94 w4 = node.get_wallet_rpc('w4') 95 assert_equal(w4.getwalletinfo()['keypoolsize'], 0) 96 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w4.getnewaddress) 97 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w4.getrawchangeaddress) 98 # Encrypt the wallet. Nothing should change about the keypool 99 w4.encryptwallet('pass') 100 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w4.getnewaddress) 101 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w4.getrawchangeaddress) 102 with WalletUnlock(w4, "pass"): 103 # Now set a seed and it should work. Wallet should also be encrypted 104 w4.importdescriptors([{ 105 'desc': descsum_create('wpkh(tprv8ZgxMBicQKsPcwuZGKp8TeWppSuLMiLe2d9PupB14QpPeQsqoj3LneJLhGHH13xESfvASyd4EFLJvLrG8b7DrLxEuV7hpF9uUc6XruKA1Wq/0h/*)'), 106 'timestamp': 'now', 107 'active': True 108 }, 109 { 110 'desc': descsum_create('wpkh(tprv8ZgxMBicQKsPcwuZGKp8TeWppSuLMiLe2d9PupB14QpPeQsqoj3LneJLhGHH13xESfvASyd4EFLJvLrG8b7DrLxEuV7hpF9uUc6XruKA1Wq/1h/*)'), 111 'timestamp': 'now', 112 'active': True, 113 'internal': True 114 }]) 115 w4.getnewaddress() 116 w4.getrawchangeaddress() 117 118 self.log.info("Test blank creation with privkeys disabled and then encryption") 119 self.nodes[0].createwallet(wallet_name='w5', disable_private_keys=True, blank=True) 120 w5 = node.get_wallet_rpc('w5') 121 assert_equal(w5.getwalletinfo()['keypoolsize'], 0) 122 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getnewaddress) 123 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getrawchangeaddress) 124 # Encrypt the wallet 125 assert_raises_rpc_error(-16, "Error: wallet does not contain private keys, nothing to encrypt.", w5.encryptwallet, 'pass') 126 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getnewaddress) 127 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getrawchangeaddress) 128 129 self.log.info('New blank and encrypted wallets can be created') 130 self.nodes[0].createwallet(wallet_name='wblank', disable_private_keys=False, blank=True, passphrase='thisisapassphrase') 131 wblank = node.get_wallet_rpc('wblank') 132 assert_raises_rpc_error(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.", wblank.signmessage, "needanargument", "test") 133 with WalletUnlock(wblank, "thisisapassphrase"): 134 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", wblank.getnewaddress) 135 assert_raises_rpc_error(-4, "Error: This wallet has no available keys", wblank.getrawchangeaddress) 136 137 self.log.info('Test creating a new encrypted wallet.') 138 # Born encrypted wallet is created (has keys) 139 self.nodes[0].createwallet(wallet_name='w6', disable_private_keys=False, blank=False, passphrase='thisisapassphrase') 140 w6 = node.get_wallet_rpc('w6') 141 assert_raises_rpc_error(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.", w6.signmessage, "needanargument", "test") 142 with WalletUnlock(w6, "thisisapassphrase"): 143 w6.signmessage(w6.getnewaddress('', 'legacy'), "test") 144 w6.keypoolrefill(1) 145 # There should only be 1 key for legacy, 3 for descriptors 146 walletinfo = w6.getwalletinfo() 147 keys = 4 148 assert_equal(walletinfo['keypoolsize'], keys) 149 assert_equal(walletinfo['keypoolsize_hd_internal'], keys) 150 # Allow empty passphrase, but there should be a warning 151 resp = self.nodes[0].createwallet(wallet_name='w7', disable_private_keys=False, blank=False, passphrase='') 152 assert_equal(resp["warnings"], [EMPTY_PASSPHRASE_MSG]) 153 154 w7 = node.get_wallet_rpc('w7') 155 assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 60) 156 157 self.log.info('Test making a wallet with avoid reuse flag') 158 self.nodes[0].createwallet('w8', False, False, '', True) # Use positional arguments to check for bug where avoid_reuse could not be set for wallets without needing them to be encrypted 159 w8 = node.get_wallet_rpc('w8') 160 assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 60) 161 assert_equal(w8.getwalletinfo()["avoid_reuse"], True) 162 163 self.log.info('Using a passphrase with private keys disabled returns error') 164 assert_raises_rpc_error(-4, 'Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.', self.nodes[0].createwallet, wallet_name='w9', disable_private_keys=True, passphrase='thisisapassphrase') 165 166 self.log.info("Test that legacy wallets cannot be created") 167 assert_raises_rpc_error(-4, 'descriptors argument must be set to "true"; it is no longer possible to create a legacy wallet.', self.nodes[0].createwallet, wallet_name="legacy", descriptors=False) 168 169 self.log.info("Check that the version number is being logged correctly") 170 with node.assert_debug_log(expected_msgs=[], unexpected_msgs=["Last client version = "]): 171 node.createwallet("version_check") 172 wallet = node.get_wallet_rpc("version_check") 173 client_version = node.getnetworkinfo()["version"] 174 wallet.unloadwallet() 175 with node.assert_debug_log( 176 expected_msgs=[f"Last client version = {client_version}"] 177 ): 178 node.loadwallet("version_check") 179 180 181 if __name__ == '__main__': 182 CreateWalletTest(__file__).main()