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 datetime | |||||
import os | import os | ||||
import time | |||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import ( | from test_framework.util import ( | ||||
assert_equal, | assert_equal, | ||||
assert_raises_rpc_error, | 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: | ||||
found_addr = 0 | found_addr = 0 | ||||
found_comments = [] | |||||
found_script_addr = 0 | found_script_addr = 0 | ||||
found_addr_chg = 0 | found_addr_chg = 0 | ||||
found_addr_rsv = 0 | found_addr_rsv = 0 | ||||
hd_master_addr_ret = None | hd_master_addr_ret = None | ||||
for line in inputfile: | for line in inputfile: | ||||
# only read non comment lines | line = line.strip() | ||||
if line[0] != "#" and len(line) > 10: | if not line: | ||||
continue | |||||
if line[0] == '#': | |||||
found_comments.append(line) | |||||
else: | |||||
# split out some data | # split out some data | ||||
key_date_label, comment = line.split("#") | key_date_label, comment = line.split("#") | ||||
key_date_label = key_date_label.split(" ") | key_date_label = key_date_label.split(" ") | ||||
# key = key_date_label[0] | # key = key_date_label[0] | ||||
date = key_date_label[1] | date = key_date_label[1] | ||||
keytype = key_date_label[2] | keytype = key_date_label[2] | ||||
imported_key = date == '1970-01-01T00:00:01Z' | imported_key = date == '1970-01-01T00:00:01Z' | ||||
Show All 31 Lines | with open(file_name, encoding='utf8') as inputfile: | ||||
break | break | ||||
# count scripts | # count scripts | ||||
for script_addr in script_addrs: | for script_addr in script_addrs: | ||||
if script_addr == addr.rstrip() and keytype == "script=1": | if script_addr == addr.rstrip() and keytype == "script=1": | ||||
found_script_addr += 1 | found_script_addr += 1 | ||||
break | break | ||||
return found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret | return found_comments, found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret | ||||
class WalletDumpTest(BitcoinTestFramework): | class WalletDumpTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
self.extra_args = [["-keypool=90"]] | self.extra_args = [["-keypool=90"]] | ||||
self.rpc_timeout = 120 | self.rpc_timeout = 120 | ||||
Show All 20 Lines | def run_test(self): | ||||
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 | self.log.info('Mine a block one second before the wallet is dumped') | ||||
dump_time = int(time.time()) | |||||
self.nodes[0].setmocktime(dump_time - 1) | |||||
self.nodes[0].generate(1) | |||||
self.nodes[0].setmocktime(dump_time) | |||||
dump_time_str = '# * Created on {}Z'.format( | |||||
datetime.datetime.fromtimestamp( | |||||
dump_time, | |||||
tz=datetime.timezone.utc, | |||||
).replace(tzinfo=None).isoformat()) | |||||
dump_best_block_1 = '# * Best block at time of backup was {} ({}),'.format( | |||||
self.nodes[0].getblockcount(), | |||||
self.nodes[0].getbestblockhash(), | |||||
) | |||||
dump_best_block_2 = '# mined on {}Z'.format( | |||||
datetime.datetime.fromtimestamp( | |||||
dump_time - 1, | |||||
tz=datetime.timezone.utc, | |||||
).replace(tzinfo=None).isoformat()) | |||||
self.log.info('Dump unencrypted wallet') | |||||
result = self.nodes[0].dumpwallet(wallet_unenc_dump) | result = self.nodes[0].dumpwallet(wallet_unenc_dump) | ||||
assert_equal(result['filename'], wallet_unenc_dump) | assert_equal(result['filename'], wallet_unenc_dump) | ||||
found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \ | found_comments, found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \ | ||||
read_dump(wallet_unenc_dump, addrs, [multisig_addr], None) | read_dump(wallet_unenc_dump, addrs, [multisig_addr], None) | ||||
# Check that file is not corrupt | |||||
assert '# End of dump' in found_comments | |||||
assert_equal( | |||||
dump_time_str, next( | |||||
c for c in found_comments if c.startswith('# * Created on'))) | |||||
assert_equal( | |||||
dump_best_block_1, next( | |||||
c for c in found_comments if c.startswith('# * Best block'))) | |||||
assert_equal( | |||||
dump_best_block_2, next( | |||||
c for c in found_comments if c.startswith('# mined on'))) | |||||
# 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(wallet_enc_dump) | self.nodes[0].dumpwallet(wallet_enc_dump) | ||||
found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \ | found_comments, found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \ | ||||
read_dump( | read_dump( | ||||
wallet_enc_dump, | wallet_enc_dump, | ||||
addrs, | addrs, | ||||
[multisig_addr], | [multisig_addr], | ||||
hd_master_addr_unenc) | hd_master_addr_unenc) | ||||
# Check that file is not corrupt | |||||
assert '# End of dump' in found_comments | |||||
assert_equal(found_addr, test_addr_count) | assert_equal(found_addr, test_addr_count) | ||||
assert_equal( | |||||
dump_time_str, next( | |||||
c for c in found_comments if c.startswith('# * Created on'))) | |||||
assert_equal( | |||||
dump_best_block_1, next( | |||||
c for c in found_comments if c.startswith('# * Best block'))) | |||||
assert_equal( | |||||
dump_best_block_2, next( | |||||
c for c in found_comments if c.startswith('# mined on'))) | |||||
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, | assert_raises_rpc_error(-8, | ||||
"already exists", | "already exists", | ||||
Show All 23 Lines |