Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet_hd.py
Show All 27 Lines | def run_test(self): | ||||
connect_nodes_bi(self.nodes[0], self.nodes[1]) | connect_nodes_bi(self.nodes[0], self.nodes[1]) | ||||
# Make sure we use hd, keep masterkeyid | # Make sure we use hd, keep masterkeyid | ||||
masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid'] | masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid'] | ||||
assert_equal(len(masterkeyid), 40) | assert_equal(len(masterkeyid), 40) | ||||
# create an internal key | # create an internal key | ||||
change_addr = self.nodes[1].getrawchangeaddress() | change_addr = self.nodes[1].getrawchangeaddress() | ||||
change_addrV = self.nodes[1].validateaddress(change_addr) | change_addrV = self.nodes[1].getaddressinfo(change_addr) | ||||
# first internal child key | # first internal child key | ||||
assert_equal(change_addrV["hdkeypath"], "m/0'/1'/0'") | assert_equal(change_addrV["hdkeypath"], "m/0'/1'/0'") | ||||
# Import a non-HD private key in the HD wallet | # Import a non-HD private key in the HD wallet | ||||
non_hd_add = self.nodes[0].getnewaddress() | non_hd_add = self.nodes[0].getnewaddress() | ||||
self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add)) | self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add)) | ||||
# This should be enough to keep the master key and the non-HD key | # This should be enough to keep the master key and the non-HD key | ||||
self.nodes[1].backupwallet( | self.nodes[1].backupwallet( | ||||
os.path.join(self.nodes[1].datadir, "hd.bak")) | os.path.join(self.nodes[1].datadir, "hd.bak")) | ||||
#self.nodes[1].dumpwallet(os.path.join(self.nodes[1].datadir, "hd.dump")) | #self.nodes[1].dumpwallet(os.path.join(self.nodes[1].datadir, "hd.dump")) | ||||
# Derive some HD addresses and remember the last | # Derive some HD addresses and remember the last | ||||
# Also send funds to each add | # Also send funds to each add | ||||
self.nodes[0].generate(101) | self.nodes[0].generate(101) | ||||
hd_add = None | hd_add = None | ||||
num_hd_adds = 300 | num_hd_adds = 300 | ||||
for i in range(num_hd_adds): | for i in range(num_hd_adds): | ||||
hd_add = self.nodes[1].getnewaddress() | hd_add = self.nodes[1].getnewaddress() | ||||
hd_info = self.nodes[1].validateaddress(hd_add) | hd_info = self.nodes[1].getaddressinfo(hd_add) | ||||
assert_equal(hd_info["hdkeypath"], "m/0'/0'/" + str(i) + "'") | assert_equal(hd_info["hdkeypath"], "m/0'/0'/" + str(i) + "'") | ||||
assert_equal(hd_info["hdmasterkeyid"], masterkeyid) | assert_equal(hd_info["hdmasterkeyid"], masterkeyid) | ||||
self.nodes[0].sendtoaddress(hd_add, 1) | self.nodes[0].sendtoaddress(hd_add, 1) | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
self.nodes[0].sendtoaddress(non_hd_add, 1) | self.nodes[0].sendtoaddress(non_hd_add, 1) | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
# create an internal key (again) | # create an internal key (again) | ||||
change_addr = self.nodes[1].getrawchangeaddress() | change_addr = self.nodes[1].getrawchangeaddress() | ||||
change_addrV = self.nodes[1].validateaddress(change_addr) | change_addrV = self.nodes[1].getaddressinfo(change_addr) | ||||
# second internal child key | # second internal child key | ||||
assert_equal(change_addrV["hdkeypath"], "m/0'/1'/1'") | assert_equal(change_addrV["hdkeypath"], "m/0'/1'/1'") | ||||
self.sync_all() | self.sync_all() | ||||
assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1) | assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1) | ||||
self.log.info("Restore backup ...") | self.log.info("Restore backup ...") | ||||
self.stop_node(1) | self.stop_node(1) | ||||
# we need to delete the complete regtest directory | # we need to delete the complete regtest directory | ||||
# otherwise node1 would auto-recover all funds in flag the keypool keys as used | # otherwise node1 would auto-recover all funds in flag the keypool keys as used | ||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "blocks")) | shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "blocks")) | ||||
shutil.rmtree(os.path.join( | shutil.rmtree(os.path.join( | ||||
self.nodes[1].datadir, "regtest", "chainstate")) | self.nodes[1].datadir, "regtest", "chainstate")) | ||||
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join( | shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join( | ||||
self.nodes[1].datadir, "regtest", "wallets", "wallet.dat")) | self.nodes[1].datadir, "regtest", "wallets", "wallet.dat")) | ||||
self.start_node(1) | self.start_node(1) | ||||
# Assert that derivation is deterministic | # Assert that derivation is deterministic | ||||
hd_add_2 = None | hd_add_2 = None | ||||
for _ in range(num_hd_adds): | for _ in range(num_hd_adds): | ||||
hd_add_2 = self.nodes[1].getnewaddress() | hd_add_2 = self.nodes[1].getnewaddress() | ||||
hd_info_2 = self.nodes[1].validateaddress(hd_add_2) | hd_info_2 = self.nodes[1].getaddressinfo(hd_add_2) | ||||
assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/" + str(_) + "'") | assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/" + str(_) + "'") | ||||
assert_equal(hd_info_2["hdmasterkeyid"], masterkeyid) | assert_equal(hd_info_2["hdmasterkeyid"], masterkeyid) | ||||
assert_equal(hd_add, hd_add_2) | assert_equal(hd_add, hd_add_2) | ||||
connect_nodes_bi(self.nodes[0], self.nodes[1]) | connect_nodes_bi(self.nodes[0], self.nodes[1]) | ||||
self.sync_all() | self.sync_all() | ||||
# Needs rescan | # Needs rescan | ||||
self.stop_node(1) | self.stop_node(1) | ||||
Show All 26 Lines | def run_test(self): | ||||
# send a tx and make sure its using the internal chain for the changeoutput | # send a tx and make sure its using the internal chain for the changeoutput | ||||
txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1) | txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1) | ||||
outs = self.nodes[1].decoderawtransaction( | outs = self.nodes[1].decoderawtransaction( | ||||
self.nodes[1].gettransaction(txid)['hex'])['vout'] | self.nodes[1].gettransaction(txid)['hex'])['vout'] | ||||
keypath = "" | keypath = "" | ||||
for out in outs: | for out in outs: | ||||
if out['value'] != 1: | if out['value'] != 1: | ||||
keypath = self.nodes[1].validateaddress( | keypath = self.nodes[1].getaddressinfo( | ||||
out['scriptPubKey']['addresses'][0])['hdkeypath'] | out['scriptPubKey']['addresses'][0])['hdkeypath'] | ||||
assert_equal(keypath[0:7], "m/0'/1'") | assert_equal(keypath[0:7], "m/0'/1'") | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
WalletHDTest().main() | WalletHDTest().main() |