Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet_dump.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2016-2019 The Bitcoin Core developers | # Copyright (c) 2016-2019 The Bitcoin Core developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
"""Test the dumpwallet RPC.""" | """Test the dumpwallet RPC.""" | ||||
import os | import os | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import assert_equal, assert_raises_rpc_error | from test_framework.util import ( | ||||
assert_equal, | |||||
assert_raises_rpc_error, | |||||
) | |||||
def read_dump(file_name, addrs, script_addrs, hd_master_addr_old): | def read_dump(file_name, addrs, script_addrs, hd_master_addr_old): | ||||
""" | """ | ||||
Read the given dump, count the addrs that match, count change and reserve. | Read the given dump, count the addrs that match, count change and reserve. | ||||
Also check that the old hd_master is inactive | Also check that the old hd_master is inactive | ||||
""" | """ | ||||
with open(file_name, encoding='utf8') as inputfile: | with open(file_name, encoding='utf8') as inputfile: | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | class WalletDumpTest(BitcoinTestFramework): | ||||
def skip_test_if_missing_module(self): | def skip_test_if_missing_module(self): | ||||
self.skip_if_no_wallet() | self.skip_if_no_wallet() | ||||
def setup_network(self): | def setup_network(self): | ||||
self.add_nodes(self.num_nodes, extra_args=self.extra_args) | self.add_nodes(self.num_nodes, extra_args=self.extra_args) | ||||
self.start_nodes() | self.start_nodes() | ||||
def run_test(self): | def run_test(self): | ||||
tmpdir = self.options.tmpdir | wallet_unenc_dump = os.path.join( | ||||
self.nodes[0].datadir, "wallet.unencrypted.dump") | |||||
wallet_enc_dump = os.path.join( | |||||
self.nodes[0].datadir, "wallet.encrypted.dump") | |||||
# generate 20 addresses to compare against the dump | # generate 20 addresses to compare against the dump | ||||
test_addr_count = 20 | test_addr_count = 20 | ||||
addrs = [] | addrs = [] | ||||
for i in range(0, test_addr_count): | for i in range(0, test_addr_count): | ||||
addr = self.nodes[0].getnewaddress() | addr = self.nodes[0].getnewaddress() | ||||
vaddr = self.nodes[0].getaddressinfo( | vaddr = self.nodes[0].getaddressinfo( | ||||
addr) # required to get hd keypath | addr) # required to get hd keypath | ||||
addrs.append(vaddr) | addrs.append(vaddr) | ||||
# Should be a no-op: | # Should be a no-op: | ||||
self.nodes[0].keypoolrefill() | self.nodes[0].keypoolrefill() | ||||
# Test scripts dump by adding a 1-of-1 multisig address | # Test scripts dump by adding a 1-of-1 multisig address | ||||
multisig_addr = self.nodes[0].addmultisigaddress( | multisig_addr = self.nodes[0].addmultisigaddress( | ||||
1, [addrs[0]["address"]])["address"] | 1, [addrs[0]["address"]])["address"] | ||||
# dump unencrypted wallet | # dump unencrypted wallet | ||||
result = self.nodes[0].dumpwallet( | result = self.nodes[0].dumpwallet(wallet_unenc_dump) | ||||
tmpdir + "/node0/wallet.unencrypted.dump") | assert_equal(result['filename'], wallet_unenc_dump) | ||||
assert_equal(result['filename'], os.path.abspath( | |||||
tmpdir + "/node0/wallet.unencrypted.dump")) | |||||
found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \ | found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \ | ||||
read_dump(tmpdir + "/node0/wallet.unencrypted.dump", | read_dump(wallet_unenc_dump, addrs, [multisig_addr], None) | ||||
addrs, [multisig_addr], None) | |||||
# all keys must be in the dump | # all keys must be in the dump | ||||
assert_equal(found_addr, test_addr_count) | assert_equal(found_addr, test_addr_count) | ||||
# all scripts must be in the dump | # all scripts must be in the dump | ||||
assert_equal(found_script_addr, 1) | assert_equal(found_script_addr, 1) | ||||
# 0 blocks where mined | # 0 blocks where mined | ||||
assert_equal(found_addr_chg, 0) | assert_equal(found_addr_chg, 0) | ||||
# 90 keys plus 100% internal keys | # 90 keys plus 100% internal keys | ||||
assert_equal(found_addr_rsv, 90 * 2) | assert_equal(found_addr_rsv, 90 * 2) | ||||
# encrypt wallet, restart, unlock and dump | # encrypt wallet, restart, unlock and dump | ||||
self.nodes[0].encryptwallet('test') | self.nodes[0].encryptwallet('test') | ||||
self.nodes[0].walletpassphrase('test', 10) | self.nodes[0].walletpassphrase('test', 10) | ||||
# Should be a no-op: | # Should be a no-op: | ||||
self.nodes[0].keypoolrefill() | self.nodes[0].keypoolrefill() | ||||
self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.encrypted.dump") | self.nodes[0].dumpwallet(wallet_enc_dump) | ||||
found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \ | found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \ | ||||
read_dump(tmpdir + "/node0/wallet.encrypted.dump", | read_dump( | ||||
addrs, [multisig_addr], hd_master_addr_unenc) | wallet_enc_dump, | ||||
addrs, | |||||
[multisig_addr], | |||||
hd_master_addr_unenc) | |||||
assert_equal(found_addr, test_addr_count) | assert_equal(found_addr, test_addr_count) | ||||
assert_equal(found_script_addr, 1) | assert_equal(found_script_addr, 1) | ||||
# old reserve keys are marked as change now | # old reserve keys are marked as change now | ||||
assert_equal(found_addr_chg, 90 * 2) | assert_equal(found_addr_chg, 90 * 2) | ||||
assert_equal(found_addr_rsv, 90 * 2) | assert_equal(found_addr_rsv, 90 * 2) | ||||
# Overwriting should fail | # Overwriting should fail | ||||
assert_raises_rpc_error(-8, "already exists", | assert_raises_rpc_error(-8, | ||||
self.nodes[0].dumpwallet, tmpdir + "/node0/wallet.unencrypted.dump") | "already exists", | ||||
lambda: self.nodes[0].dumpwallet(wallet_enc_dump)) | |||||
# Restart node with new wallet, and test importwallet | # Restart node with new wallet, and test importwallet | ||||
self.stop_node(0) | self.stop_node(0) | ||||
self.start_node(0, ['-wallet=w2']) | self.start_node(0, ['-wallet=w2']) | ||||
# Make sure the address is not IsMine before import | # Make sure the address is not IsMine before import | ||||
result = self.nodes[0].getaddressinfo(multisig_addr) | result = self.nodes[0].getaddressinfo(multisig_addr) | ||||
assert result['ismine'] is False | assert result['ismine'] is False | ||||
self.nodes[0].importwallet(os.path.abspath( | self.nodes[0].importwallet(wallet_unenc_dump) | ||||
tmpdir + "/node0/wallet.unencrypted.dump")) | |||||
# Now check IsMine is true | # Now check IsMine is true | ||||
result = self.nodes[0].getaddressinfo(multisig_addr) | result = self.nodes[0].getaddressinfo(multisig_addr) | ||||
assert result['ismine'] is True | assert result['ismine'] is True | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
WalletDumpTest().main() | WalletDumpTest().main() |