mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 12:32:48 +01:00
cc38451955
beee49b [tests] Allow stderr to be tested against specified string (John Newbery) e503671 [Tests] Use LIBC_FATAL_STDERR_=1 in tests (John Newbery) c22ce8a [Tests] Write stdout/stderr to datadir instead of temp file. (John Newbery) Pull request description: **Due to a merge conflict, this is now based on #10267. Please review that PR first!** Subset of #12379 now that parts of that PR have been merged. #12362 was only observed when running the functional tests locally because: - by defatul libc logs to `/dev/tty` instead of stderr - the functional tests only check for substring inclusion in stderr when we're expecting bitcoind to fail. This PR tightens our checking of stderr and will cause tests to fail if there is any unexpected message in stderr: - commit *Write stdout/stderr to datadir instead of temp file* writes stderr to a file in the datadir instead of a temporary file. This helps with debugging in the case of failure. - commit *Use LIBC_FATAL_STDERR=1 in tests* ensures that libc failures are logged to stderr instead of the terminal. commit *Assert that bitcoind stdout is empty on shutdown* asserts that stderr is empty on bitcoind shutdown. Tree-SHA512: 21111030e667b3b686f2a7625c2b625ebcfb6998e1cccb4f3932e8b5d21fb514b19a73ac971595d049343430e9a63155986a7f5648cad55b8f36f3c58b1c7048
185 lines
8.3 KiB
Python
Executable File
185 lines
8.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# Copyright (c) 2016 The Bitcoin Core developers
|
|
# Distributed under the MIT software license, see the accompanying
|
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
"""
|
|
wallet_upgradetohd.py
|
|
|
|
Test upgrade to a Hierarchical Deterministic wallet via upgradetohd rpc
|
|
"""
|
|
|
|
import shutil
|
|
import os
|
|
|
|
from test_framework.test_framework import BitcoinTestFramework
|
|
from test_framework.util import (
|
|
assert_equal,
|
|
assert_raises_rpc_error,
|
|
)
|
|
|
|
|
|
class WalletUpgradeToHDTest(BitcoinTestFramework):
|
|
def set_test_params(self):
|
|
self.num_nodes = 1
|
|
|
|
def setup_network(self):
|
|
self.add_nodes(self.num_nodes)
|
|
self.start_nodes()
|
|
|
|
def recover_non_hd(self):
|
|
self.log.info("Recover non-HD wallet to check different upgrade paths")
|
|
node = self.nodes[0]
|
|
self.stop_node(0)
|
|
shutil.copyfile(os.path.join(node.datadir, "non_hd.bak"), os.path.join(node.datadir, "regtest", "wallets", "wallet.dat"))
|
|
self.start_node(0)
|
|
assert('hdchainid' not in node.getwalletinfo())
|
|
|
|
def run_test(self):
|
|
node = self.nodes[0]
|
|
node.backupwallet(os.path.join(node.datadir, "non_hd.bak"))
|
|
|
|
self.log.info("No mnemonic, no mnemonic passphrase, no wallet passphrase")
|
|
assert('hdchainid' not in node.getwalletinfo())
|
|
balance_before = node.getbalance()
|
|
assert(node.upgradetohd())
|
|
mnemonic = node.dumphdinfo()['mnemonic']
|
|
chainid = node.getwalletinfo()['hdchainid']
|
|
assert_equal(len(chainid), 64)
|
|
assert_equal(balance_before, node.getbalance())
|
|
|
|
self.log.info("Should be spendable and should use correct paths")
|
|
for i in range(5):
|
|
txid = node.sendtoaddress(node.getnewaddress(), 1)
|
|
outs = node.decoderawtransaction(node.gettransaction(txid)['hex'])['vout']
|
|
for out in outs:
|
|
if out['value'] == 1:
|
|
keypath = node.getaddressinfo(out['scriptPubKey']['addresses'][0])['hdkeypath']
|
|
assert_equal(keypath, "m/44'/1'/0'/0/%d" % i)
|
|
else:
|
|
keypath = node.getaddressinfo(out['scriptPubKey']['addresses'][0])['hdkeypath']
|
|
assert_equal(keypath, "m/44'/1'/0'/1/%d" % i)
|
|
|
|
self.bump_mocktime(1)
|
|
node.generate(1)
|
|
|
|
self.log.info("Should no longer be able to start it with HD disabled")
|
|
self.stop_node(0)
|
|
node.assert_start_raises_init_error(['-usehd=0'], "Error: Error loading : You can't disable HD on an already existing HD wallet")
|
|
self.start_node(0)
|
|
balance_after = node.getbalance()
|
|
|
|
self.recover_non_hd()
|
|
|
|
# We spent some coins from non-HD keys to HD ones earlier
|
|
balance_non_HD = node.getbalance()
|
|
assert(balance_before != balance_non_HD)
|
|
|
|
self.log.info("No mnemonic, no mnemonic passphrase, no wallet passphrase, should result in completely different keys")
|
|
assert(node.upgradetohd())
|
|
assert(mnemonic != node.dumphdinfo()['mnemonic'])
|
|
assert(chainid != node.getwalletinfo()['hdchainid'])
|
|
assert_equal(balance_non_HD, node.getbalance())
|
|
node.keypoolrefill(5)
|
|
node.rescanblockchain()
|
|
# Completely different keys, no HD coins should be recovered
|
|
assert_equal(balance_non_HD, node.getbalance())
|
|
|
|
self.recover_non_hd()
|
|
|
|
self.log.info("Same mnemonic, another mnemonic passphrase, no wallet passphrase, should result in a different set of keys")
|
|
new_mnemonic_passphrase = "somewords"
|
|
assert(node.upgradetohd(mnemonic, new_mnemonic_passphrase))
|
|
assert_equal(mnemonic, node.dumphdinfo()['mnemonic'])
|
|
new_chainid = node.getwalletinfo()['hdchainid']
|
|
assert(chainid != new_chainid)
|
|
assert_equal(balance_non_HD, node.getbalance())
|
|
node.keypoolrefill(5)
|
|
node.rescanblockchain()
|
|
# A different set of keys, no HD coins should be recovered
|
|
new_addresses = (node.getnewaddress(), node.getrawchangeaddress())
|
|
assert_equal(balance_non_HD, node.getbalance())
|
|
|
|
self.recover_non_hd()
|
|
|
|
self.log.info("Same mnemonic, another mnemonic passphrase, no wallet passphrase, should result in a different set of keys (again)")
|
|
assert(node.upgradetohd(mnemonic, new_mnemonic_passphrase))
|
|
assert_equal(mnemonic, node.dumphdinfo()['mnemonic'])
|
|
assert_equal(new_chainid, node.getwalletinfo()['hdchainid'])
|
|
assert_equal(balance_non_HD, node.getbalance())
|
|
node.keypoolrefill(5)
|
|
node.rescanblockchain()
|
|
# A different set of keys, no HD coins should be recovered, keys should be the same as they were the previous time
|
|
assert_equal(new_addresses, (node.getnewaddress(), node.getrawchangeaddress()))
|
|
assert_equal(balance_non_HD, node.getbalance())
|
|
|
|
self.recover_non_hd()
|
|
|
|
self.log.info("Same mnemonic, no mnemonic passphrase, no wallet passphrase, should recover all coins after rescan")
|
|
assert(node.upgradetohd(mnemonic))
|
|
assert_equal(mnemonic, node.dumphdinfo()['mnemonic'])
|
|
assert_equal(chainid, node.getwalletinfo()['hdchainid'])
|
|
node.keypoolrefill(5)
|
|
node.rescanblockchain()
|
|
assert_equal(balance_after, node.getbalance())
|
|
|
|
self.recover_non_hd()
|
|
|
|
self.log.info("Same mnemonic, no mnemonic passphrase, no wallet passphrase, large enough keepool, should recover all coins with no extra rescan")
|
|
self.stop_node(0)
|
|
self.start_node(0, extra_args=['-keypool=10'])
|
|
assert(node.upgradetohd(mnemonic))
|
|
assert_equal(mnemonic, node.dumphdinfo()['mnemonic'])
|
|
assert_equal(chainid, node.getwalletinfo()['hdchainid'])
|
|
# All coins should be recovered
|
|
assert_equal(balance_after, node.getbalance())
|
|
|
|
self.recover_non_hd()
|
|
|
|
self.log.info("Same mnemonic, same mnemonic passphrase, encrypt wallet on upgrade, should recover all coins after rescan")
|
|
walletpass = "111pass222"
|
|
# Upgrading and encrypting at the saame time results in a warning
|
|
assert node.upgradetohd(mnemonic, "", walletpass)
|
|
node.stop()
|
|
node.wait_until_stopped()
|
|
self.start_node(0, extra_args=['-rescan'])
|
|
assert_raises_rpc_error(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.", node.dumphdinfo)
|
|
node.walletpassphrase(walletpass, 100)
|
|
assert_equal(mnemonic, node.dumphdinfo()['mnemonic'])
|
|
assert_equal(chainid, node.getwalletinfo()['hdchainid'])
|
|
# Note: wallet encryption results in additonal keypool topup,
|
|
# so we can't compare new balance to balance_non_HD here,
|
|
# assert_equal(balance_non_HD, node.getbalance()) # won't work
|
|
assert(balance_non_HD != node.getbalance())
|
|
node.keypoolrefill(4)
|
|
node.rescanblockchain()
|
|
# All coins should be recovered
|
|
assert_equal(balance_after, node.getbalance())
|
|
|
|
self.recover_non_hd()
|
|
|
|
self.log.info("Same mnemonic, same mnemonic passphrase, encrypt wallet first, should recover all coins on upgrade after rescan")
|
|
walletpass = "111pass222"
|
|
node.encryptwallet(walletpass)
|
|
node.stop()
|
|
node.wait_until_stopped()
|
|
self.start_node(0, extra_args=['-rescan'])
|
|
assert_raises_rpc_error(-14, "Cannot upgrade encrypted wallet to HD without the wallet passphrase", node.upgradetohd, mnemonic)
|
|
assert_raises_rpc_error(-14, "The wallet passphrase entered was incorrect", node.upgradetohd, mnemonic, "", "wrongpass")
|
|
assert(node.upgradetohd(mnemonic, "", walletpass))
|
|
assert_raises_rpc_error(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.", node.dumphdinfo)
|
|
node.walletpassphrase(walletpass, 100)
|
|
assert_equal(mnemonic, node.dumphdinfo()['mnemonic'])
|
|
assert_equal(chainid, node.getwalletinfo()['hdchainid'])
|
|
# Note: wallet encryption results in additonal keypool topup,
|
|
# so we can't compare new balance to balance_non_HD here,
|
|
# assert_equal(balance_non_HD, node.getbalance()) # won't work
|
|
assert(balance_non_HD != node.getbalance())
|
|
node.keypoolrefill(4)
|
|
node.rescanblockchain()
|
|
# All coins should be recovered
|
|
assert_equal(balance_after, node.getbalance())
|
|
|
|
|
|
if __name__ == '__main__':
|
|
WalletUpgradeToHDTest().main ()
|