[test] Add getblockchaininfo functional test
[bitcoinplatinum.git] / test / functional / wallet-hd.py
blob5ef3bf5bffcba7bd569498b9732700aca9b73988
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 Hierarchical Deterministic wallet function."""
7 from test_framework.test_framework import BitcoinTestFramework
8 from test_framework.util import (
9 assert_equal,
10 connect_nodes_bi,
12 import shutil
14 class WalletHDTest(BitcoinTestFramework):
15 def set_test_params(self):
16 self.setup_clean_chain = True
17 self.num_nodes = 2
18 self.extra_args = [[], ['-keypool=0']]
20 def run_test (self):
21 tmpdir = self.options.tmpdir
23 # Make sure can't switch off usehd after wallet creation
24 self.stop_node(1)
25 self.assert_start_raises_init_error(1, ['-usehd=0'], 'already existing HD wallet')
26 self.start_node(1)
27 connect_nodes_bi(self.nodes, 0, 1)
29 # Make sure we use hd, keep masterkeyid
30 masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
31 assert_equal(len(masterkeyid), 40)
33 # create an internal key
34 change_addr = self.nodes[1].getrawchangeaddress()
35 change_addrV= self.nodes[1].validateaddress(change_addr)
36 assert_equal(change_addrV["hdkeypath"], "m/0'/1'/0'") #first internal child key
38 # Import a non-HD private key in the HD wallet
39 non_hd_add = self.nodes[0].getnewaddress()
40 self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add))
42 # This should be enough to keep the master key and the non-HD key
43 self.nodes[1].backupwallet(tmpdir + "/hd.bak")
44 #self.nodes[1].dumpwallet(tmpdir + "/hd.dump")
46 # Derive some HD addresses and remember the last
47 # Also send funds to each add
48 self.nodes[0].generate(101)
49 hd_add = None
50 num_hd_adds = 300
51 for i in range(num_hd_adds):
52 hd_add = self.nodes[1].getnewaddress()
53 hd_info = self.nodes[1].validateaddress(hd_add)
54 assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(i)+"'")
55 assert_equal(hd_info["hdmasterkeyid"], masterkeyid)
56 self.nodes[0].sendtoaddress(hd_add, 1)
57 self.nodes[0].generate(1)
58 self.nodes[0].sendtoaddress(non_hd_add, 1)
59 self.nodes[0].generate(1)
61 # create an internal key (again)
62 change_addr = self.nodes[1].getrawchangeaddress()
63 change_addrV= self.nodes[1].validateaddress(change_addr)
64 assert_equal(change_addrV["hdkeypath"], "m/0'/1'/1'") #second internal child key
66 self.sync_all()
67 assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)
69 self.log.info("Restore backup ...")
70 self.stop_node(1)
71 # we need to delete the complete regtest directory
72 # otherwise node1 would auto-recover all funds in flag the keypool keys as used
73 shutil.rmtree(tmpdir + "/node1/regtest/blocks")
74 shutil.rmtree(tmpdir + "/node1/regtest/chainstate")
75 shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/regtest/wallet.dat")
76 self.start_node(1)
78 # Assert that derivation is deterministic
79 hd_add_2 = None
80 for _ in range(num_hd_adds):
81 hd_add_2 = self.nodes[1].getnewaddress()
82 hd_info_2 = self.nodes[1].validateaddress(hd_add_2)
83 assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/"+str(_)+"'")
84 assert_equal(hd_info_2["hdmasterkeyid"], masterkeyid)
85 assert_equal(hd_add, hd_add_2)
86 connect_nodes_bi(self.nodes, 0, 1)
87 self.sync_all()
89 # Needs rescan
90 self.stop_node(1)
91 self.start_node(1, extra_args=self.extra_args[1] + ['-rescan'])
92 assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)
94 # send a tx and make sure its using the internal chain for the changeoutput
95 txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1)
96 outs = self.nodes[1].decoderawtransaction(self.nodes[1].gettransaction(txid)['hex'])['vout']
97 keypath = ""
98 for out in outs:
99 if out['value'] != 1:
100 keypath = self.nodes[1].validateaddress(out['scriptPubKey']['addresses'][0])['hdkeypath']
102 assert_equal(keypath[0:7], "m/0'/1'")
104 if __name__ == '__main__':
105 WalletHDTest().main ()