mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-03 20:35:17 +02:00
Merge #11466: Specify custom wallet directory with -walletdir param
c1e5d40Make debugging test crash easier (MeshCollider)8263f6aCreate walletdir if datadir doesn't exist and fix tests (MeshCollider)9587a9cDefault walletdir is wallets/ if it exists (MeshCollider)d987889Add release notes for -walletdir and wallets/ dir (MeshCollider)80c5cbcAdd test for -walletdir (MeshCollider)0530ba0Add -walletdir parameter to specify custom wallet dir (MeshCollider) Pull request description: Closes #11348 Adds a `-walletdir` parameter which specifies a directory to use for wallets, allowing them to be stored separately from the 'main' data directory. Creates a new `wallets/` directory in datadir if this is the first time running, and defaults to using it if it exists. Includes tests and release notes. Things which might need to be considered more: - there is no 'lock' on the wallets directory, which might be needed? - because this uses a new wallets/ directory by default, downgrading to an earlier version won't see the wallets in that directory (not a big deal though, users can just copy them up to the main dir) - jnewbery suggested putting each wallet in its own directory, which is a good idea, but out of scope for this PR IMO. EDIT: this is being done in https://github.com/bitcoin/bitcoin/pull/11687 - doc/files.md needs updating (will do soon) I also considered including a cleanup by removing caching of data directory paths and instead just initialise them once on startup (c.f. #3073), but decided it wasn't super relevant here will just complicate review. Tree-SHA512: c8ac04bfe9a810c32055f2c8b8fa0d535e56125ceb8d96f12447dd3538bf3e5ee992b60b1cd2173bf5f3fa023a9feab12c9963593bf27ed419df929bb413398d
This commit is contained in:
@@ -33,7 +33,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
|
||||
|
||||
self.stop_node(1)
|
||||
|
||||
shutil.copyfile(self.tmpdir + "/node1/regtest/wallet.dat", self.tmpdir + "/wallet.bak")
|
||||
shutil.copyfile(self.tmpdir + "/node1/regtest/wallets/wallet.dat", self.tmpdir + "/wallet.bak")
|
||||
self.start_node(1, self.extra_args[1])
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
|
||||
@@ -56,7 +56,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
|
||||
|
||||
self.stop_node(1)
|
||||
|
||||
shutil.copyfile(self.tmpdir + "/wallet.bak", self.tmpdir + "/node1/regtest/wallet.dat")
|
||||
shutil.copyfile(self.tmpdir + "/wallet.bak", self.tmpdir + "/node1/regtest/wallets/wallet.dat")
|
||||
|
||||
self.log.info("Verify keypool is restored and balance is correct")
|
||||
|
||||
|
||||
@@ -27,18 +27,40 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
self.assert_start_raises_init_error(0, ['-wallet=w1', '-wallet=w1'], 'Error loading wallet w1. Duplicate -wallet filename specified.')
|
||||
|
||||
# should not initialize if wallet file is a directory
|
||||
os.mkdir(os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w11'))
|
||||
wallet_dir = os.path.join(self.options.tmpdir, 'node0', 'regtest', 'wallets')
|
||||
os.mkdir(os.path.join(wallet_dir, 'w11'))
|
||||
self.assert_start_raises_init_error(0, ['-wallet=w11'], 'Error loading wallet w11. -wallet filename must be a regular file.')
|
||||
|
||||
# should not initialize if one wallet is a copy of another
|
||||
shutil.copyfile(os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w2'),
|
||||
os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w22'))
|
||||
shutil.copyfile(os.path.join(wallet_dir, 'w2'), os.path.join(wallet_dir, 'w22'))
|
||||
self.assert_start_raises_init_error(0, ['-wallet=w2', '-wallet=w22'], 'duplicates fileid')
|
||||
|
||||
# should not initialize if wallet file is a symlink
|
||||
os.symlink(os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w1'), os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w12'))
|
||||
os.symlink(os.path.join(wallet_dir, 'w1'), os.path.join(wallet_dir, 'w12'))
|
||||
self.assert_start_raises_init_error(0, ['-wallet=w12'], 'Error loading wallet w12. -wallet filename must be a regular file.')
|
||||
|
||||
# should not initialize if the specified walletdir does not exist
|
||||
self.assert_start_raises_init_error(0, ['-walletdir=bad'], 'Error: Specified wallet directory "bad" does not exist.')
|
||||
|
||||
# if wallets/ doesn't exist, datadir should be the default wallet dir
|
||||
wallet_dir2 = os.path.join(self.options.tmpdir, 'node0', 'regtest', 'walletdir')
|
||||
os.rename(wallet_dir, wallet_dir2)
|
||||
self.start_node(0, ['-wallet=w4', '-wallet=w5'])
|
||||
assert_equal(set(self.nodes[0].listwallets()), {"w4", "w5"})
|
||||
w5 = self.nodes[0].get_wallet_rpc("w5")
|
||||
w5.generate(1)
|
||||
self.stop_node(0)
|
||||
|
||||
# now if wallets/ exists again, but the rootdir is specified as the walletdir, w4 and w5 should still be loaded
|
||||
os.rename(wallet_dir2, wallet_dir)
|
||||
self.start_node(0, ['-wallet=w4', '-wallet=w5', '-walletdir=' + os.path.join(self.options.tmpdir, 'node0', 'regtest')])
|
||||
assert_equal(set(self.nodes[0].listwallets()), {"w4", "w5"})
|
||||
w5 = self.nodes[0].get_wallet_rpc("w5")
|
||||
w5_info = w5.getwalletinfo()
|
||||
assert_equal(w5_info['immature_balance'], 50)
|
||||
|
||||
self.stop_node(0)
|
||||
|
||||
self.start_node(0, self.extra_args[0])
|
||||
|
||||
w1 = self.nodes[0].get_wallet_rpc("w1")
|
||||
|
||||
@@ -432,7 +432,7 @@ class BitcoinTestFramework():
|
||||
self.disable_mocktime()
|
||||
for i in range(MAX_NODES):
|
||||
os.remove(log_filename(self.options.cachedir, i, "debug.log"))
|
||||
os.remove(log_filename(self.options.cachedir, i, "db.log"))
|
||||
os.remove(log_filename(self.options.cachedir, i, "wallets/db.log"))
|
||||
os.remove(log_filename(self.options.cachedir, i, "peers.dat"))
|
||||
os.remove(log_filename(self.options.cachedir, i, "fee_estimates.dat"))
|
||||
|
||||
|
||||
@@ -300,7 +300,11 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove
|
||||
|
||||
if len(test_list) > 1 and jobs > 1:
|
||||
# Populate cache
|
||||
subprocess.check_output([tests_dir + 'create_cache.py'] + flags + ["--tmpdir=%s/cache" % tmpdir])
|
||||
try:
|
||||
subprocess.check_output([tests_dir + 'create_cache.py'] + flags + ["--tmpdir=%s/cache" % tmpdir])
|
||||
except Exception as e:
|
||||
print(e.output)
|
||||
raise e
|
||||
|
||||
#Run Tests
|
||||
job_queue = TestHandler(jobs, tests_dir, tmpdir, test_list, flags)
|
||||
|
||||
@@ -73,7 +73,7 @@ class WalletHDTest(BitcoinTestFramework):
|
||||
# otherwise node1 would auto-recover all funds in flag the keypool keys as used
|
||||
shutil.rmtree(os.path.join(tmpdir, "node1/regtest/blocks"))
|
||||
shutil.rmtree(os.path.join(tmpdir, "node1/regtest/chainstate"))
|
||||
shutil.copyfile(os.path.join(tmpdir, "hd.bak"), os.path.join(tmpdir, "node1/regtest/wallet.dat"))
|
||||
shutil.copyfile(os.path.join(tmpdir, "hd.bak"), os.path.join(tmpdir, "node1/regtest/wallets/wallet.dat"))
|
||||
self.start_node(1)
|
||||
|
||||
# Assert that derivation is deterministic
|
||||
|
||||
@@ -90,9 +90,9 @@ class WalletBackupTest(BitcoinTestFramework):
|
||||
self.stop_node(2)
|
||||
|
||||
def erase_three(self):
|
||||
os.remove(self.options.tmpdir + "/node0/regtest/wallet.dat")
|
||||
os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat")
|
||||
os.remove(self.options.tmpdir + "/node2/regtest/wallet.dat")
|
||||
os.remove(self.options.tmpdir + "/node0/regtest/wallets/wallet.dat")
|
||||
os.remove(self.options.tmpdir + "/node1/regtest/wallets/wallet.dat")
|
||||
os.remove(self.options.tmpdir + "/node2/regtest/wallets/wallet.dat")
|
||||
|
||||
def run_test(self):
|
||||
self.log.info("Generating initial blockchain")
|
||||
@@ -154,9 +154,9 @@ class WalletBackupTest(BitcoinTestFramework):
|
||||
shutil.rmtree(self.options.tmpdir + "/node2/regtest/chainstate")
|
||||
|
||||
# Restore wallets from backup
|
||||
shutil.copyfile(tmpdir + "/node0/wallet.bak", tmpdir + "/node0/regtest/wallet.dat")
|
||||
shutil.copyfile(tmpdir + "/node1/wallet.bak", tmpdir + "/node1/regtest/wallet.dat")
|
||||
shutil.copyfile(tmpdir + "/node2/wallet.bak", tmpdir + "/node2/regtest/wallet.dat")
|
||||
shutil.copyfile(tmpdir + "/node0/wallet.bak", tmpdir + "/node0/regtest/wallets/wallet.dat")
|
||||
shutil.copyfile(tmpdir + "/node1/wallet.bak", tmpdir + "/node1/regtest/wallets/wallet.dat")
|
||||
shutil.copyfile(tmpdir + "/node2/wallet.bak", tmpdir + "/node2/regtest/wallets/wallet.dat")
|
||||
|
||||
self.log.info("Re-starting nodes")
|
||||
self.start_three()
|
||||
@@ -192,10 +192,10 @@ class WalletBackupTest(BitcoinTestFramework):
|
||||
|
||||
# Backup to source wallet file must fail
|
||||
sourcePaths = [
|
||||
tmpdir + "/node0/regtest/wallet.dat",
|
||||
tmpdir + "/node0/./regtest/wallet.dat",
|
||||
tmpdir + "/node0/regtest/",
|
||||
tmpdir + "/node0/regtest"]
|
||||
tmpdir + "/node0/regtest/wallets/wallet.dat",
|
||||
tmpdir + "/node0/./regtest/wallets/wallet.dat",
|
||||
tmpdir + "/node0/regtest/wallets/",
|
||||
tmpdir + "/node0/regtest/wallets"]
|
||||
|
||||
for sourcePath in sourcePaths:
|
||||
assert_raises_rpc_error(-4, "backup failed", self.nodes[0].backupwallet, sourcePath)
|
||||
|
||||
Reference in New Issue
Block a user