Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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."""
  6. from test_framework.test_framework import BitcoinTestFramework
  7. from test_framework.util import (
  8. start_nodes,
  9. start_node,
  10. assert_equal,
  11. connect_nodes_bi,
  12. assert_start_raises_init_error
  13. )
  14. import os
  15. import shutil
  16. class WalletHDTest(BitcoinTestFramework):
  17. def __init__(self):
  18. super().__init__()
  19. self.setup_clean_chain = True
  20. self.num_nodes = 2
  21. self.node_args = [['-usehd=0'], ['-usehd=1', '-keypool=0']]
  22. def setup_network(self):
  23. self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.node_args)
  24. self.is_network_split = False
  25. connect_nodes_bi(self.nodes, 0, 1)
  26. def run_test (self):
  27. tmpdir = self.options.tmpdir
  28. # Make sure can't switch off usehd after wallet creation
  29. self.stop_node(1)
  30. assert_start_raises_init_error(1, self.options.tmpdir, ['-usehd=0'], 'already existing HD wallet')
  31. self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1])
  32. connect_nodes_bi(self.nodes, 0, 1)
  33. # Make sure we use hd, keep masterkeyid
  34. masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
  35. assert_equal(len(masterkeyid), 40)
  36. # create an internal key
  37. change_addr = self.nodes[1].getrawchangeaddress()
  38. change_addrV= self.nodes[1].validateaddress(change_addr)
  39. assert_equal(change_addrV["hdkeypath"], "m/0'/1'/0'") #first internal child key
  40. # Import a non-HD private key in the HD wallet
  41. non_hd_add = self.nodes[0].getnewaddress()
  42. self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add))
  43. # This should be enough to keep the master key and the non-HD key
  44. self.nodes[1].backupwallet(tmpdir + "/hd.bak")
  45. #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+1)+"'")
  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)
  60. # create an internal key (again)
  61. change_addr = self.nodes[1].getrawchangeaddress()
  62. change_addrV= self.nodes[1].validateaddress(change_addr)
  63. assert_equal(change_addrV["hdkeypath"], "m/0'/1'/1'") #second internal child key
  64. self.sync_all()
  65. assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)
  66. self.log.info("Restore backup ...")
  67. self.stop_node(1)
  68. os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat")
  69. shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/regtest/wallet.dat")
  70. self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1])
  71. #connect_nodes_bi(self.nodes, 0, 1)
  72. # Assert that derivation is deterministic
  73. hd_add_2 = None
  74. for _ in range(num_hd_adds):
  75. hd_add_2 = self.nodes[1].getnewaddress()
  76. hd_info_2 = self.nodes[1].validateaddress(hd_add_2)
  77. assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/"+str(_+1)+"'")
  78. assert_equal(hd_info_2["hdmasterkeyid"], masterkeyid)
  79. assert_equal(hd_add, hd_add_2)
  80. # Needs rescan
  81. self.stop_node(1)
  82. self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1] + ['-rescan'])
  83. #connect_nodes_bi(self.nodes, 0, 1)
  84. assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)
  85. # send a tx and make sure its using the internal chain for the changeoutput
  86. txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1)
  87. outs = self.nodes[1].decoderawtransaction(self.nodes[1].gettransaction(txid)['hex'])['vout']
  88. keypath = ""
  89. for out in outs:
  90. if out['value'] != 1:
  91. keypath = self.nodes[1].validateaddress(out['scriptPubKey']['addresses'][0])['hdkeypath']
  92. assert_equal(keypath[0:7], "m/0'/1'")
  93. if __name__ == '__main__':
  94. WalletHDTest().main ()