Merge pull request #5069 from PastaPastaPasta/revert/bitcoin-20186

revert: multiple breaking changes in wallet code
This commit is contained in:
PastaPastaPasta 2022-11-09 17:55:31 -06:00 committed by GitHub
commit 0db359a2ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 107 additions and 228 deletions

View File

@ -1,6 +0,0 @@
Wallet
------
Dash Core will no longer create an unnamed `""` wallet by default when no wallet is specified on the command line or in the configuration files.
For backwards compatibility, if an unnamed `""` wallet already exists and would have been loaded previously, then it will still be loaded.
Users without an unnamed `""` wallet and without any other wallets to be loaded on startup will be prompted to either choose a wallet to load, or to create a new wallet.

View File

@ -1,16 +0,0 @@
Wallet
------
### Automatic wallet creation removed
Dash Core will no longer automatically create new wallets on startup. It will
load existing wallets specified by `-wallet` options on the command line or in
`dash.conf` or `settings.json` files. And by default it will also load a
top-level unnamed ("") wallet. However, if specified wallets don't exist,
Dash Core will now just log warnings instead of creating new wallets with
new keys and addresses like previous releases did.
New wallets can be created through the GUI (which has a more prominent create
wallet option), through the `dash-cli createwallet` or `dash-wallet
create` commands, or the `createwallet` RPC.

View File

@ -581,7 +581,8 @@ public:
class WalletClientImpl : public WalletClient class WalletClientImpl : public WalletClient
{ {
public: public:
WalletClientImpl(Chain& chain, ArgsManager& args) WalletClientImpl(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames)
: m_wallet_filenames(std::move(wallet_filenames))
{ {
m_context.chain = &chain; m_context.chain = &chain;
m_context.args = &args; m_context.args = &args;
@ -598,8 +599,8 @@ public:
m_rpc_handlers.emplace_back(m_context.chain->handleRpc(m_rpc_commands.back())); m_rpc_handlers.emplace_back(m_context.chain->handleRpc(m_rpc_commands.back()));
} }
} }
bool verify() override { return VerifyWallets(*m_context.chain); } bool verify() override { return VerifyWallets(*m_context.chain, m_wallet_filenames); }
bool load() override { return LoadWallets(*m_context.chain); } bool load() override { return LoadWallets(*m_context.chain, m_wallet_filenames); }
void start(CScheduler& scheduler) override { return StartWallets(scheduler, *Assert(m_context.args)); } void start(CScheduler& scheduler) override { return StartWallets(scheduler, *Assert(m_context.args)); }
void flush() override { return FlushWallets(); } void flush() override { return FlushWallets(); }
void stop() override { return StopWallets(); } void stop() override { return StopWallets(); }
@ -658,9 +659,9 @@ public:
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return wallet ? std::make_unique<WalletImpl>(wallet) : nullptr; } std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return wallet ? std::make_unique<WalletImpl>(wallet) : nullptr; }
std::unique_ptr<WalletClient> MakeWalletClient(Chain& chain, ArgsManager& args) std::unique_ptr<WalletClient> MakeWalletClient(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames)
{ {
return std::make_unique<WalletClientImpl>(chain, args); return std::make_unique<WalletClientImpl>(chain, args, std::move(wallet_filenames));
} }
} // namespace interfaces } // namespace interfaces

View File

@ -449,7 +449,7 @@ std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet);
//! Return implementation of ChainClient interface for a wallet client. This //! Return implementation of ChainClient interface for a wallet client. This
//! function will be undefined in builds where ENABLE_WALLET is false. //! function will be undefined in builds where ENABLE_WALLET is false.
std::unique_ptr<WalletClient> MakeWalletClient(Chain& chain, ArgsManager& args); std::unique_ptr<WalletClient> MakeWalletClient(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames);
} // namespace interfaces } // namespace interfaces

View File

@ -870,11 +870,6 @@ void BitcoinGUI::setWalletController(WalletController* wallet_controller)
} }
} }
WalletController* BitcoinGUI::getWalletController()
{
return m_wallet_controller;
}
void BitcoinGUI::addWallet(WalletModel* walletModel) void BitcoinGUI::addWallet(WalletModel* walletModel)
{ {
if (!walletFrame) return; if (!walletFrame) return;

View File

@ -80,7 +80,6 @@ public:
void setClientModel(ClientModel *clientModel = nullptr, interfaces::BlockAndHeaderTipInfo* tip_info = nullptr); void setClientModel(ClientModel *clientModel = nullptr, interfaces::BlockAndHeaderTipInfo* tip_info = nullptr);
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
void setWalletController(WalletController* wallet_controller); void setWalletController(WalletController* wallet_controller);
WalletController* getWalletController();
#endif #endif
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET

View File

@ -1455,7 +1455,7 @@ void updateFonts()
std::vector<QString> vecIgnoreClasses{ std::vector<QString> vecIgnoreClasses{
"QWidget", "QDialog", "QFrame", "QStackedWidget", "QDesktopWidget", "QDesktopScreenWidget", "QWidget", "QDialog", "QFrame", "QStackedWidget", "QDesktopWidget", "QDesktopScreenWidget",
"QTipLabel", "QMessageBox", "QMenu", "QComboBoxPrivateScroller", "QComboBoxPrivateContainer", "QTipLabel", "QMessageBox", "QMenu", "QComboBoxPrivateScroller", "QComboBoxPrivateContainer",
"QScrollBar", "QListView", "BitcoinGUI", "WalletView", "WalletFrame", "QVBoxLayout", "QGroupBox" "QScrollBar", "QListView", "BitcoinGUI", "WalletView", "WalletFrame"
}; };
std::vector<QString> vecIgnoreObjects{ std::vector<QString> vecIgnoreObjects{
"messagesWidget" "messagesWidget"

View File

@ -2,8 +2,6 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <qt/createwalletdialog.h>
#include <qt/walletcontroller.h>
#include <qt/walletframe.h> #include <qt/walletframe.h>
#include <qt/walletmodel.h> #include <qt/walletmodel.h>
@ -14,11 +12,8 @@
#include <cassert> #include <cassert>
#include <QGroupBox>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
WalletFrame::WalletFrame(BitcoinGUI* _gui) : WalletFrame::WalletFrame(BitcoinGUI* _gui) :
QFrame(_gui), QFrame(_gui),
@ -31,25 +26,9 @@ WalletFrame::WalletFrame(BitcoinGUI* _gui) :
walletFrameLayout->setContentsMargins(0,0,0,0); walletFrameLayout->setContentsMargins(0,0,0,0);
walletFrameLayout->addWidget(walletStack); walletFrameLayout->addWidget(walletStack);
// hbox for no wallet QLabel *noWallet = new QLabel(tr("No wallet has been loaded."));
QGroupBox* no_wallet_group = new QGroupBox(walletStack);
QVBoxLayout* no_wallet_layout = new QVBoxLayout(no_wallet_group);
QLabel *noWallet = new QLabel(tr("No wallet has been loaded.\nGo to File > Open Wallet to load a wallet.\n- OR -"));
noWallet->setAlignment(Qt::AlignCenter); noWallet->setAlignment(Qt::AlignCenter);
no_wallet_layout->addWidget(noWallet, 0, Qt::AlignHCenter | Qt::AlignBottom); walletStack->addWidget(noWallet);
// A button for create wallet dialog
QPushButton* create_wallet_button = new QPushButton(tr("Create a new wallet"), walletStack);
connect(create_wallet_button, &QPushButton::clicked, [this] {
auto activity = new CreateWalletActivity(gui->getWalletController(), this);
connect(activity, &CreateWalletActivity::finished, activity, &QObject::deleteLater);
activity->create();
});
no_wallet_layout->addWidget(create_wallet_button, 0, Qt::AlignHCenter | Qt::AlignTop);
no_wallet_group->setLayout(no_wallet_layout);
walletStack->addWidget(no_wallet_group);
masternodeListPage = new MasternodeList(); masternodeListPage = new MasternodeList();
walletStack->addWidget(masternodeListPage); walletStack->addWidget(masternodeListPage);

View File

@ -58,7 +58,7 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const
" (1 = start from wallet creation time, 2 = start from genesis block)", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); " (1 = start from wallet creation time, 2 = start from genesis block)", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-spendzeroconfchange", strprintf("Spend unconfirmed change when sending transactions (default: %u)", DEFAULT_SPEND_ZEROCONF_CHANGE), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); argsman.AddArg("-spendzeroconfchange", strprintf("Spend unconfirmed change when sending transactions (default: %u)", DEFAULT_SPEND_ZEROCONF_CHANGE), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-upgradewallet", "Upgrade wallet to latest format on startup", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); argsman.AddArg("-upgradewallet", "Upgrade wallet to latest format on startup", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-wallet=<path>", "Specify wallet path to load at startup. Can be used multiple times to load multiple wallets. Path is to a directory containing wallet data and log files. If the path is not absolute, it is interpreted relative to <walletdir>. This only loads existing wallets and does not create new ones. For backwards compatibility this also accepts names of existing top-level data files in <walletdir>.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET); argsman.AddArg("-wallet=<path>", "Specify wallet database path. Can be specified multiple times to load multiple wallets. Path is interpreted relative to <walletdir> if it is not absolute, and will be created if it does not exist (as a directory containing a wallet.dat file and log files). For backwards compatibility this will also accept names of existing data files in <walletdir>.)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
argsman.AddArg("-walletbackupsdir=<dir>", "Specify full path to directory for automatic wallet backups (must exist)", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); argsman.AddArg("-walletbackupsdir=<dir>", "Specify full path to directory for automatic wallet backups (must exist)", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-walletbroadcast", strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); argsman.AddArg("-walletbroadcast", strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET); argsman.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
@ -166,7 +166,16 @@ void WalletInit::Construct(NodeContext& node) const
LogPrintf("Wallet disabled!\n"); LogPrintf("Wallet disabled!\n");
return; return;
} }
auto wallet_client = interfaces::MakeWalletClient(*node.chain, args); // If there's no -wallet setting with a list of wallets to load, set it to
// load the default "" wallet.
if (!args.IsArgSet("wallet")) {
args.LockSettings([&](util::Settings& settings) {
util::SettingsValue wallets(util::SettingsValue::VARR);
wallets.push_back(""); // Default wallet name is ""
settings.rw_settings["wallet"] = wallets;
});
}
auto wallet_client = interfaces::MakeWalletClient(*node.chain, args, args.GetArgs("-wallet"));
node.wallet_client = wallet_client.get(); node.wallet_client = wallet_client.get();
node.chain_clients.emplace_back(std::move(wallet_client)); node.chain_clients.emplace_back(std::move(wallet_client));
} }

View File

@ -19,7 +19,7 @@
#include <univalue.h> #include <univalue.h>
bool VerifyWallets(interfaces::Chain& chain) bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
{ {
if (gArgs.IsArgSet("-walletdir")) { if (gArgs.IsArgSet("-walletdir")) {
fs::path wallet_dir = gArgs.GetArg("-walletdir", ""); fs::path wallet_dir = gArgs.GetArg("-walletdir", "");
@ -44,27 +44,10 @@ bool VerifyWallets(interfaces::Chain& chain)
chain.initMessage(_("Verifying wallet(s)...").translated); chain.initMessage(_("Verifying wallet(s)...").translated);
// For backwards compatibility if an unnamed top level wallet exists in the
// wallets directory, include it in the default list of wallets to load.
if (!gArgs.IsArgSet("wallet")) {
DatabaseOptions options;
DatabaseStatus status;
bilingual_str error_string;
options.require_existing = true;
options.verify = false;
if (MakeWalletDatabase("", options, status, error_string)) {
gArgs.LockSettings([&](util::Settings& settings) {
util::SettingsValue wallets(util::SettingsValue::VARR);
wallets.push_back(""); // Default wallet name is ""
settings.rw_settings["wallet"] = wallets;
});
}
}
// Keep track of each wallet absolute path to detect duplicates. // Keep track of each wallet absolute path to detect duplicates.
std::set<fs::path> wallet_paths; std::set<fs::path> wallet_paths;
for (const auto& wallet_file : gArgs.GetArgs("-wallet")) { for (const auto& wallet_file : wallet_files) {
const fs::path path = fs::absolute(wallet_file, GetWalletDir()); const fs::path path = fs::absolute(wallet_file, GetWalletDir());
if (!wallet_paths.insert(path).second) { if (!wallet_paths.insert(path).second) {
@ -74,36 +57,27 @@ bool VerifyWallets(interfaces::Chain& chain)
DatabaseOptions options; DatabaseOptions options;
DatabaseStatus status; DatabaseStatus status;
options.require_existing = true;
options.verify = true; options.verify = true;
bilingual_str error_string; bilingual_str error_string;
if (!MakeWalletDatabase(wallet_file, options, status, error_string)) { if (!MakeWalletDatabase(wallet_file, options, status, error_string)) {
if (status == DatabaseStatus::FAILED_NOT_FOUND) { chain.initError(error_string);
chain.initWarning(Untranslated(strprintf("Skipping -wallet path that doesn't exist. %s\n", error_string.original))); return false;
} else {
chain.initError(error_string);
return false;
}
} }
} }
return true; return true;
} }
bool LoadWallets(interfaces::Chain& chain) bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
{ {
try { try {
for (const std::string& name : gArgs.GetArgs("-wallet")) { for (const std::string& name : wallet_files) {
DatabaseOptions options; DatabaseOptions options;
DatabaseStatus status; DatabaseStatus status;
options.require_existing = true;
options.verify = false; // No need to verify, assuming verified earlier in VerifyWallets() options.verify = false; // No need to verify, assuming verified earlier in VerifyWallets()
bilingual_str error_string; bilingual_str error_string;
std::vector<bilingual_str> warnings; std::vector<bilingual_str> warnings;
std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error_string); std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error_string);
if (!database && status == DatabaseStatus::FAILED_NOT_FOUND) {
continue;
}
std::shared_ptr<CWallet> pwallet = database ? CWallet::Create(chain, name, std::move(database), options.create_flags, error_string, warnings) : nullptr; std::shared_ptr<CWallet> pwallet = database ? CWallet::Create(chain, name, std::move(database), options.create_flags, error_string, warnings) : nullptr;
if (!warnings.empty()) chain.initWarning(Join(warnings, Untranslated("\n"))); if (!warnings.empty()) chain.initWarning(Join(warnings, Untranslated("\n")));
if (!pwallet) { if (!pwallet) {

View File

@ -18,10 +18,10 @@ class Chain;
} // namespace interfaces } // namespace interfaces
//! Responsible for reading and validating the -wallet arguments and verifying the wallet database. //! Responsible for reading and validating the -wallet arguments and verifying the wallet database.
bool VerifyWallets(interfaces::Chain& chain); bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
//! Load wallet databases. //! Load wallet databases.
bool LoadWallets(interfaces::Chain& chain); bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
//! Complete startup of wallets. //! Complete startup of wallets.
void StartWallets(CScheduler& scheduler, const ArgsManager& args); void StartWallets(CScheduler& scheduler, const ArgsManager& args);

View File

@ -10,7 +10,7 @@
InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainName) : BasicTestingSetup(chainName) InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
{ {
m_wallet_client = MakeWalletClient(*m_chain, *Assert(m_node.args)); m_wallet_client = MakeWalletClient(*m_chain, *Assert(m_node.args), {});
std::string sep; std::string sep;
sep += fs::path::preferred_separator; sep += fs::path::preferred_separator;

View File

@ -21,7 +21,7 @@ struct WalletTestingSetup : public TestingSetup {
explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN); explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node); std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
std::unique_ptr<interfaces::WalletClient> m_wallet_client = interfaces::MakeWalletClient(*m_chain, *Assert(m_node.args)); std::unique_ptr<interfaces::WalletClient> m_wallet_client = interfaces::MakeWalletClient(*m_chain, *Assert(m_node.args), {});
CWallet m_wallet; CWallet m_wallet;
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler; std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
}; };

View File

@ -37,7 +37,6 @@
#include <wallet/coincontrol.h> #include <wallet/coincontrol.h>
#include <wallet/coinselection.h> #include <wallet/coinselection.h>
#include <wallet/fees.h> #include <wallet/fees.h>
#include <walletinitinterface.h>
#include <warnings.h> #include <warnings.h>
#include <coinjoin/client.h> #include <coinjoin/client.h>
@ -113,7 +112,6 @@ bool AddWallet(const std::shared_ptr<CWallet>& wallet)
if (i != vpwallets.end()) return false; if (i != vpwallets.end()) return false;
coinJoinClientManagers.emplace(std::make_pair(wallet->GetName(), std::make_shared<CCoinJoinClientManager>(*wallet))); coinJoinClientManagers.emplace(std::make_pair(wallet->GetName(), std::make_shared<CCoinJoinClientManager>(*wallet)));
vpwallets.push_back(wallet); vpwallets.push_back(wallet);
g_wallet_init_interface.InitCoinJoinSettings();
return true; return true;
} }
@ -132,7 +130,6 @@ bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, std::optional<bool> lo
vpwallets.erase(i); vpwallets.erase(i);
auto it = coinJoinClientManagers.find(wallet->GetName()); auto it = coinJoinClientManagers.find(wallet->GetName());
coinJoinClientManagers.erase(it); coinJoinClientManagers.erase(it);
g_wallet_init_interface.InitCoinJoinSettings();
// Write the wallet setting // Write the wallet setting
UpdateWalletSetting(chain, name, load_on_start, warnings); UpdateWalletSetting(chain, name, load_on_start, warnings);

View File

@ -14,7 +14,6 @@ class ConfArgsTest(BitcoinTestFramework):
self.setup_clean_chain = True self.setup_clean_chain = True
self.num_nodes = 1 self.num_nodes = 1
self.supports_cli = False self.supports_cli = False
self.wallet_names = []
def test_config_file_parser(self): def test_config_file_parser(self):
# Assume node is stopped # Assume node is stopped
@ -148,15 +147,19 @@ class ConfArgsTest(BitcoinTestFramework):
# Create the directory and ensure the config file now works # Create the directory and ensure the config file now works
os.mkdir(new_data_dir) os.mkdir(new_data_dir)
# Temporarily disabled, because this test would access the user's home dir (~/.bitcoin) # Temporarily disabled, because this test would access the user's home dir (~/.bitcoin)
self.start_node(0, ['-conf='+conf_file]) self.start_node(0, ['-conf='+conf_file, '-wallet=w1'])
self.stop_node(0) self.stop_node(0)
assert os.path.exists(os.path.join(new_data_dir, self.chain, 'blocks')) assert os.path.exists(os.path.join(new_data_dir, self.chain, 'blocks'))
if self.is_wallet_compiled():
assert os.path.exists(os.path.join(new_data_dir, self.chain, 'wallets', 'w1'))
# Ensure command line argument overrides datadir in conf # Ensure command line argument overrides datadir in conf
os.mkdir(new_data_dir_2) os.mkdir(new_data_dir_2)
self.nodes[0].datadir = new_data_dir_2 self.nodes[0].datadir = new_data_dir_2
self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file]) self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file, '-wallet=w2'])
assert os.path.exists(os.path.join(new_data_dir_2, self.chain, 'blocks')) assert os.path.exists(os.path.join(new_data_dir_2, self.chain, 'blocks'))
if self.is_wallet_compiled():
assert os.path.exists(os.path.join(new_data_dir_2, self.chain, 'wallets', 'w2'))
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -15,7 +15,7 @@ class FilelockTest(BitcoinTestFramework):
def setup_network(self): def setup_network(self):
self.add_nodes(self.num_nodes, extra_args=None) self.add_nodes(self.num_nodes, extra_args=None)
self.nodes[0].start() self.nodes[0].start([])
self.nodes[0].wait_for_rpc_connection() self.nodes[0].wait_for_rpc_connection()
def run_test(self): def run_test(self):
@ -27,11 +27,10 @@ class FilelockTest(BitcoinTestFramework):
self.nodes[1].assert_start_raises_init_error(extra_args=['-datadir={}'.format(self.nodes[0].datadir), '-noserver'], expected_msg=expected_msg) self.nodes[1].assert_start_raises_init_error(extra_args=['-datadir={}'.format(self.nodes[0].datadir), '-noserver'], expected_msg=expected_msg)
if self.is_wallet_compiled(): if self.is_wallet_compiled():
self.nodes[0].createwallet(self.default_wallet_name)
wallet_dir = os.path.join(datadir, 'wallets') wallet_dir = os.path.join(datadir, 'wallets')
self.log.info("Check that we can't start a second dashd instance using the same wallet") self.log.info("Check that we can't start a second dashd instance using the same wallet")
expected_msg = "Error: Error initializing wallet database environment" expected_msg = "Error: Error initializing wallet database environment"
self.nodes[1].assert_start_raises_init_error(extra_args=['-walletdir={}'.format(wallet_dir), '-wallet=' + self.default_wallet_name, '-noserver'], expected_msg=expected_msg, match=ErrorMatch.PARTIAL_REGEX) self.nodes[1].assert_start_raises_init_error(extra_args=['-walletdir={}'.format(wallet_dir), '-noserver'], expected_msg=expected_msg, match=ErrorMatch.PARTIAL_REGEX)
if __name__ == '__main__': if __name__ == '__main__':
FilelockTest().main() FilelockTest().main()

View File

@ -43,8 +43,8 @@ class NotificationsTest(BitcoinTestFramework):
"-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s'))], "-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s'))],
["-blockversion=211", ["-blockversion=211",
"-rescan", "-rescan",
"-wallet={}".format(self.wallet),
"-walletnotify=echo > {}".format(os.path.join(self.walletnotify_dir, notify_outputname('%w', '%s')))]] "-walletnotify=echo > {}".format(os.path.join(self.walletnotify_dir, notify_outputname('%w', '%s')))]]
self.wallet_names = [self.default_wallet_name, self.wallet]
super().setup_network() super().setup_network()
def run_test(self): def run_test(self):

View File

@ -106,7 +106,8 @@ class PruneTest(BitcoinTestFramework):
def setup_nodes(self): def setup_nodes(self):
self.add_nodes(self.num_nodes, self.extra_args) self.add_nodes(self.num_nodes, self.extra_args)
self.start_nodes() self.start_nodes()
self.import_deterministic_coinbase_privkeys() for n in self.nodes:
n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase', rescan=False)
def create_big_chain(self): def create_big_chain(self):
# Start by creating some coinbases we can spend later # Start by creating some coinbases we can spend later

View File

@ -17,7 +17,6 @@ class SettingsTest(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.setup_clean_chain = True self.setup_clean_chain = True
self.num_nodes = 1 self.num_nodes = 1
self.wallet_names = []
def run_test(self): def run_test(self):
node, = self.nodes node, = self.nodes

View File

@ -18,10 +18,6 @@ class HTTPBasicsTest(BitcoinTestFramework):
self.num_nodes = 1 self.num_nodes = 1
self.supports_cli = False self.supports_cli = False
def setup_nodes(self):
self.add_nodes(self.num_nodes)
self.start_nodes()
def setup_chain(self): def setup_chain(self):
super().setup_chain() super().setup_chain()
# Append rpcauth to dash.conf before initialization # Append rpcauth to dash.conf before initialization
@ -40,6 +36,7 @@ class HTTPBasicsTest(BitcoinTestFramework):
f.write(rpcauthoperator+"\n") f.write(rpcauthoperator+"\n")
def run_test(self): def run_test(self):
url = urllib.parse.urlparse(self.nodes[0].url) url = urllib.parse.urlparse(self.nodes[0].url)
def test_command(method, params, auth, expexted_status, should_not_match=False): def test_command(method, params, auth, expexted_status, should_not_match=False):

View File

@ -55,8 +55,7 @@ class ScantxoutsetTest(BitcoinTestFramework):
self.log.info("Stop node, remove wallet, mine again some blocks...") self.log.info("Stop node, remove wallet, mine again some blocks...")
self.stop_node(0) self.stop_node(0)
shutil.rmtree(os.path.join(self.nodes[0].datadir, self.chain, 'wallets')) shutil.rmtree(os.path.join(self.nodes[0].datadir, self.chain, 'wallets'))
self.start_node(0, ['-nowallet']) self.start_node(0)
self.import_deterministic_coinbase_privkeys()
self.nodes[0].generate(110) self.nodes[0].generate(110)
scan = self.nodes[0].scantxoutset("start", []) scan = self.nodes[0].scantxoutset("start", [])

View File

@ -117,18 +117,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.rpc_timeout = 60 # Wait for up to 60 seconds for the RPC server to respond self.rpc_timeout = 60 # Wait for up to 60 seconds for the RPC server to respond
self.supports_cli = True self.supports_cli = True
self.bind_to_localhost_only = True self.bind_to_localhost_only = True
self.parse_args()
self.default_wallet_name = ""
self.wallet_data_filename = "wallet.dat"
self.extra_args_from_options = [] self.extra_args_from_options = []
# Optional list of wallet names that can be set in set_test_params to
# create and import keys to. If unset, default is len(nodes) *
# [default_wallet_name]. If wallet names are None, wallet creation is
# skipped. If list is truncated, wallet creation is skipped and keys
# are not imported.
self.wallet_names = None
self.set_test_params() self.set_test_params()
assert self.wallet_names is None or len(self.wallet_names) <= self.num_nodes self.parse_args()
if self.options.timeout_factor == 0 : if self.options.timeout_factor == 0 :
self.options.timeout_factor = 99999 self.options.timeout_factor = 99999
self.rpc_timeout = int(self.rpc_timeout * self.options.timeout_factor) # optionally, increase timeout by a factor self.rpc_timeout = int(self.rpc_timeout * self.options.timeout_factor) # optionally, increase timeout by a factor
@ -396,8 +387,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
extra_args = self.extra_args extra_args = self.extra_args
self.add_nodes(self.num_nodes, extra_args) self.add_nodes(self.num_nodes, extra_args)
self.start_nodes() self.start_nodes()
if self.is_wallet_compiled(): self.import_deterministic_coinbase_privkeys()
self.import_deterministic_coinbase_privkeys()
if not self.setup_clean_chain: if not self.setup_clean_chain:
for n in self.nodes: for n in self.nodes:
assert_equal(n.getblockchaininfo()["blocks"], 199) assert_equal(n.getblockchaininfo()["blocks"], 199)
@ -414,15 +404,13 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
assert_equal(chain_info["initialblockdownload"], False) assert_equal(chain_info["initialblockdownload"], False)
def import_deterministic_coinbase_privkeys(self): def import_deterministic_coinbase_privkeys(self):
for i in range(len(self.nodes)): for n in self.nodes:
self.init_wallet(i) try:
n.getwalletinfo()
except JSONRPCException as e:
assert str(e).startswith('Method not found')
continue
def init_wallet(self, i):
wallet_name = self.default_wallet_name if self.wallet_names is None else self.wallet_names[i] if i < len(self.wallet_names) else False
if wallet_name is not False:
n = self.nodes[i]
if wallet_name is not None:
n.createwallet(wallet_name=wallet_name, load_on_startup=True)
n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase') n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase')
def run_test(self): def run_test(self):
@ -940,7 +928,6 @@ class DashTestFramework(BitcoinTestFramework):
idx = len(self.nodes) idx = len(self.nodes)
self.add_nodes(1, extra_args=[self.extra_args[idx]]) self.add_nodes(1, extra_args=[self.extra_args[idx]])
self.start_node(idx) self.start_node(idx)
self.nodes[idx].createwallet(self.default_wallet_name)
for i in range(0, idx): for i in range(0, idx):
self.connect_nodes(i, idx) self.connect_nodes(i, idx)
@ -1100,6 +1087,7 @@ class DashTestFramework(BitcoinTestFramework):
self.prepare_masternodes() self.prepare_masternodes()
self.prepare_datadirs() self.prepare_datadirs()
self.start_masternodes() self.start_masternodes()
self.import_deterministic_coinbase_privkeys()
# non-masternodes where disconnected from the control node during prepare_datadirs, # non-masternodes where disconnected from the control node during prepare_datadirs,
# let's reconnect them back to make sure they receive updates # let's reconnect them back to make sure they receive updates

View File

@ -72,7 +72,7 @@ class ToolWalletTest(BitcoinTestFramework):
locked_dir = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets") locked_dir = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets")
self.assert_raises_tool_error( self.assert_raises_tool_error(
'Error initializing wallet database environment "{}"!'.format(locked_dir), 'Error initializing wallet database environment "{}"!'.format(locked_dir),
'-wallet=' + self.default_wallet_name, '-wallet=wallet.dat',
'info', 'info',
) )
path = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets", "nonexistent.dat") path = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets", "nonexistent.dat")
@ -118,7 +118,7 @@ class ToolWalletTest(BitcoinTestFramework):
Transactions: 0 Transactions: 0
Address Book: 1 Address Book: 1
''') ''')
self.assert_tool_output(out, '-wallet=' + self.default_wallet_name, 'info') self.assert_tool_output(out, '-wallet=wallet.dat', 'info')
timestamp_after = self.wallet_timestamp() timestamp_after = self.wallet_timestamp()
self.log.debug('Wallet file timestamp after calling info: {}'.format(timestamp_after)) self.log.debug('Wallet file timestamp after calling info: {}'.format(timestamp_after))
self.log_wallet_timestamp_comparison(timestamp_before, timestamp_after) self.log_wallet_timestamp_comparison(timestamp_before, timestamp_after)
@ -157,7 +157,7 @@ class ToolWalletTest(BitcoinTestFramework):
Transactions: 1 Transactions: 1
Address Book: 1 Address Book: 1
''') ''')
self.assert_tool_output(out, '-wallet=' + self.default_wallet_name, 'info') self.assert_tool_output(out, '-wallet=wallet.dat', 'info')
shasum_after = self.wallet_shasum() shasum_after = self.wallet_shasum()
timestamp_after = self.wallet_timestamp() timestamp_after = self.wallet_timestamp()
self.log.debug('Wallet file timestamp after calling info: {}'.format(timestamp_after)) self.log.debug('Wallet file timestamp after calling info: {}'.format(timestamp_after))
@ -195,7 +195,7 @@ class ToolWalletTest(BitcoinTestFramework):
def test_getwalletinfo_on_different_wallet(self): def test_getwalletinfo_on_different_wallet(self):
self.log.info('Starting node with arg -wallet=foo') self.log.info('Starting node with arg -wallet=foo')
self.start_node(0, ['-nowallet', '-wallet=foo']) self.start_node(0, ['-wallet=foo'])
self.log.info('Calling getwalletinfo on a different wallet ("foo"), testing output') self.log.info('Calling getwalletinfo on a different wallet ("foo"), testing output')
shasum_before = self.wallet_shasum() shasum_before = self.wallet_shasum()
@ -219,14 +219,13 @@ class ToolWalletTest(BitcoinTestFramework):
def test_salvage(self): def test_salvage(self):
# TODO: Check salvage actually salvages and doesn't break things. https://github.com/bitcoin/bitcoin/issues/7463 # TODO: Check salvage actually salvages and doesn't break things. https://github.com/bitcoin/bitcoin/issues/7463
self.log.info('Check salvage') self.log.info('Check salvage')
self.start_node(0) self.start_node(0, ['-wallet=salvage'])
self.nodes[0].createwallet("salvage")
self.stop_node(0) self.stop_node(0)
self.assert_tool_output('', '-wallet=salvage', 'salvage') self.assert_tool_output('', '-wallet=salvage', 'salvage')
def run_test(self): def run_test(self):
self.wallet_path = os.path.join(self.nodes[0].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename) self.wallet_path = os.path.join(self.nodes[0].datadir, self.chain, 'wallets', 'wallet.dat')
self.test_invalid_tool_commands_and_args() self.test_invalid_tool_commands_and_args()
# Warning: The following tests are order-dependent. # Warning: The following tests are order-dependent.
self.test_tool_wallet_info() self.test_tool_wallet_info()

View File

@ -87,10 +87,10 @@ class WalletBackupTest(BitcoinTestFramework):
self.sync_blocks() self.sync_blocks()
# As above, this mirrors the original bash test. # As above, this mirrors the original bash test.
def start_three(self, args=()): def start_three(self):
self.start_node(0, self.extra_args[0] + list(args)) self.start_node(0)
self.start_node(1, self.extra_args[1] + list(args)) self.start_node(1)
self.start_node(2, self.extra_args[2] + list(args)) self.start_node(2)
self.connect_nodes(0, 3) self.connect_nodes(0, 3)
self.connect_nodes(1, 3) self.connect_nodes(1, 3)
self.connect_nodes(2, 3) self.connect_nodes(2, 3)
@ -102,14 +102,9 @@ class WalletBackupTest(BitcoinTestFramework):
self.stop_node(2) self.stop_node(2)
def erase_three(self): def erase_three(self):
os.remove(os.path.join(self.nodes[0].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename)) os.remove(os.path.join(self.nodes[0].datadir, self.chain, 'wallets', 'wallet.dat'))
os.remove(os.path.join(self.nodes[1].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename)) os.remove(os.path.join(self.nodes[1].datadir, self.chain, 'wallets', 'wallet.dat'))
os.remove(os.path.join(self.nodes[2].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename)) os.remove(os.path.join(self.nodes[2].datadir, self.chain, 'wallets', 'wallet.dat'))
def init_three(self):
self.init_wallet(0)
self.init_wallet(1)
self.init_wallet(2)
def run_test(self): def run_test(self):
self.log.info("Generating initial blockchain") self.log.info("Generating initial blockchain")
@ -173,9 +168,9 @@ class WalletBackupTest(BitcoinTestFramework):
shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'llmq')) shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'llmq'))
# Restore wallets from backup # Restore wallets from backup
shutil.copyfile(os.path.join(self.nodes[0].datadir, 'wallet.bak'), os.path.join(self.nodes[0].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename)) shutil.copyfile(os.path.join(self.nodes[0].datadir, 'wallet.bak'), os.path.join(self.nodes[0].datadir, self.chain, 'wallets', 'wallet.dat'))
shutil.copyfile(os.path.join(self.nodes[1].datadir, 'wallet.bak'), os.path.join(self.nodes[1].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename)) shutil.copyfile(os.path.join(self.nodes[1].datadir, 'wallet.bak'), os.path.join(self.nodes[1].datadir, self.chain, 'wallets', 'wallet.dat'))
shutil.copyfile(os.path.join(self.nodes[2].datadir, 'wallet.bak'), os.path.join(self.nodes[2].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename)) shutil.copyfile(os.path.join(self.nodes[2].datadir, 'wallet.bak'), os.path.join(self.nodes[2].datadir, self.chain, 'wallets', 'wallet.dat'))
self.log.info("Re-starting nodes") self.log.info("Re-starting nodes")
self.start_three() self.start_three()
@ -195,8 +190,7 @@ class WalletBackupTest(BitcoinTestFramework):
shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'evodb')) shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'evodb'))
shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'llmq')) shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'llmq'))
self.start_three(["-nowallet"]) self.start_three()
self.init_three()
assert_equal(self.nodes[0].getbalance(), 0) assert_equal(self.nodes[0].getbalance(), 0)
assert_equal(self.nodes[1].getbalance(), 0) assert_equal(self.nodes[1].getbalance(), 0)
@ -214,9 +208,9 @@ class WalletBackupTest(BitcoinTestFramework):
# Backup to source wallet file must fail # Backup to source wallet file must fail
sourcePaths = [ sourcePaths = [
os.path.join(self.nodes[0].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename), os.path.join(self.nodes[0].datadir, self.chain, 'wallets', 'wallet.dat'),
os.path.join(self.nodes[0].datadir, self.chain, '.', 'wallets', self.default_wallet_name, self.wallet_data_filename), os.path.join(self.nodes[0].datadir, self.chain, '.', 'wallets', 'wallet.dat'),
os.path.join(self.nodes[0].datadir, self.chain, 'wallets', self.default_wallet_name), os.path.join(self.nodes[0].datadir, self.chain, 'wallets', ''),
os.path.join(self.nodes[0].datadir, self.chain, 'wallets')] os.path.join(self.nodes[0].datadir, self.chain, 'wallets')]
for sourcePath in sourcePaths: for sourcePath in sourcePaths:

View File

@ -165,10 +165,10 @@ class WalletTest(BitcoinTestFramework):
# dynamically loading the wallet. # dynamically loading the wallet.
before = self.nodes[1].getunconfirmedbalance() before = self.nodes[1].getunconfirmedbalance()
dst = self.nodes[1].getnewaddress() dst = self.nodes[1].getnewaddress()
self.nodes[1].unloadwallet(self.default_wallet_name) self.nodes[1].unloadwallet('')
self.nodes[0].sendtoaddress(dst, 0.1) self.nodes[0].sendtoaddress(dst, 0.1)
self.sync_all() self.sync_all()
self.nodes[1].loadwallet(self.default_wallet_name) self.nodes[1].loadwallet('')
after = self.nodes[1].getunconfirmedbalance() after = self.nodes[1].getunconfirmedbalance()
assert_equal(before + Decimal('0.1'), after) assert_equal(before + Decimal('0.1'), after)

View File

@ -16,7 +16,6 @@ class DisableWalletTest (BitcoinTestFramework):
self.setup_clean_chain = True self.setup_clean_chain = True
self.num_nodes = 1 self.num_nodes = 1
self.extra_args = [["-disablewallet"]] self.extra_args = [["-disablewallet"]]
self.wallet_names = []
def run_test (self): def run_test (self):
# Make sure wallet is really disabled # Make sure wallet is really disabled

View File

@ -91,8 +91,6 @@ class WalletDumpTest(BitcoinTestFramework):
self.start_nodes() self.start_nodes()
def run_test(self): def run_test(self):
self.nodes[0].createwallet("dump")
wallet_unenc_dump = os.path.join(self.nodes[0].datadir, "wallet.unencrypted.dump") wallet_unenc_dump = os.path.join(self.nodes[0].datadir, "wallet.unencrypted.dump")
wallet_enc_dump = os.path.join(self.nodes[0].datadir, "wallet.encrypted.dump") wallet_enc_dump = os.path.join(self.nodes[0].datadir, "wallet.encrypted.dump")
@ -142,8 +140,8 @@ class WalletDumpTest(BitcoinTestFramework):
assert_raises_rpc_error(-8, "already exists", lambda: self.nodes[0].dumpwallet(wallet_enc_dump)) assert_raises_rpc_error(-8, "already exists", lambda: self.nodes[0].dumpwallet(wallet_enc_dump))
# Restart node with new wallet, and test importwallet # Restart node with new wallet, and test importwallet
self.restart_node(0) self.stop_node(0)
self.nodes[0].createwallet("w2") self.start_node(0, ['-wallet=w2'])
# Make sure the address is not IsMine before import # Make sure the address is not IsMine before import
result = self.nodes[0].getaddressinfo(multisig_addr) result = self.nodes[0].getaddressinfo(multisig_addr)

View File

@ -81,10 +81,7 @@ class WalletHDTest(BitcoinTestFramework):
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "chainstate")) shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "chainstate"))
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "evodb")) shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "evodb"))
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "llmq")) shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "llmq"))
shutil.copyfile( shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, self.chain, "wallets", "wallet.dat"))
os.path.join(self.nodes[1].datadir, "hd.bak"),
os.path.join(self.nodes[1].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename),
)
self.start_node(1) self.start_node(1)
# Assert that derivation is deterministic # Assert that derivation is deterministic
@ -109,10 +106,7 @@ class WalletHDTest(BitcoinTestFramework):
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "chainstate")) shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "chainstate"))
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "evodb")) shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "evodb"))
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "llmq")) shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "llmq"))
shutil.copyfile( shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, self.chain, "wallets", "wallet.dat"))
os.path.join(self.nodes[1].datadir, "hd.bak"),
os.path.join(self.nodes[1].datadir, self.chain, "wallets", self.default_wallet_name, self.wallet_data_filename),
)
self.start_node(1, extra_args=self.extra_args[1]) self.start_node(1, extra_args=self.extra_args[1])
self.connect_nodes(0, 1) self.connect_nodes(0, 1)
self.sync_all() self.sync_all()

View File

@ -135,7 +135,8 @@ class ImportRescanTest(BitcoinTestFramework):
# Import keys with pruning disabled # Import keys with pruning disabled
self.start_nodes(extra_args=[[]] * self.num_nodes) self.start_nodes(extra_args=[[]] * self.num_nodes)
self.import_deterministic_coinbase_privkeys() for n in self.nodes:
n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase')
self.stop_nodes() self.stop_nodes()
self.start_nodes() self.start_nodes()

View File

@ -673,7 +673,7 @@ class ImportMultiTest(BitcoinTestFramework):
# Cannot import those pubkeys to keypool of wallet with privkeys # Cannot import those pubkeys to keypool of wallet with privkeys
self.log.info("Pubkeys cannot be added to the keypool of a wallet with private keys") self.log.info("Pubkeys cannot be added to the keypool of a wallet with private keys")
wrpc = self.nodes[1].get_wallet_rpc(self.default_wallet_name) wrpc = self.nodes[1].get_wallet_rpc("")
assert wrpc.getwalletinfo()['private_keys_enabled'] assert wrpc.getwalletinfo()['private_keys_enabled']
result = wrpc.importmulti( result = wrpc.importmulti(
[{ [{

View File

@ -29,7 +29,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
self.skip_if_no_wallet() self.skip_if_no_wallet()
def run_test(self): def run_test(self):
wallet_path = os.path.join(self.nodes[1].datadir, self.chain, "wallets", self.default_wallet_name, self.wallet_data_filename) wallet_path = os.path.join(self.nodes[1].datadir, self.chain, "wallets", "wallet.dat")
wallet_backup_path = os.path.join(self.nodes[1].datadir, "wallet.bak") wallet_backup_path = os.path.join(self.nodes[1].datadir, "wallet.bak")
self.nodes[0].generate(101) self.nodes[0].generate(101)

View File

@ -43,7 +43,6 @@ class MultiWalletTest(BitcoinTestFramework):
self.setup_clean_chain = True self.setup_clean_chain = True
self.num_nodes = 2 self.num_nodes = 2
self.rpc_timeout = 120 self.rpc_timeout = 120
self.extra_args = [["-nowallet"], []]
def skip_test_if_missing_module(self): def skip_test_if_missing_module(self):
self.skip_if_no_wallet() self.skip_if_no_wallet()
@ -64,14 +63,14 @@ class MultiWalletTest(BitcoinTestFramework):
def wallet_file(name): def wallet_file(name):
if os.path.isdir(wallet_dir(name)): if os.path.isdir(wallet_dir(name)):
return wallet_dir(name, self.wallet_data_filename) return wallet_dir(name, "wallet.dat")
return wallet_dir(name) return wallet_dir(name)
assert_equal(self.nodes[0].listwalletdir(), { 'wallets': [{ 'name': self.default_wallet_name }] }) assert_equal(self.nodes[0].listwalletdir(), { 'wallets': [{ 'name': '' }] })
# check wallet.dat is created # check wallet.dat is created
self.stop_nodes() self.stop_nodes()
assert_equal(os.path.isfile(wallet_dir(self.default_wallet_name, self.wallet_data_filename)), True) assert_equal(os.path.isfile(wallet_dir('wallet.dat')), True)
# create symlink to verify wallet directory path can be referenced # create symlink to verify wallet directory path can be referenced
# through symlink # through symlink
@ -81,16 +80,13 @@ class MultiWalletTest(BitcoinTestFramework):
# rename wallet.dat to make sure plain wallet file paths (as opposed to # rename wallet.dat to make sure plain wallet file paths (as opposed to
# directory paths) can be loaded # directory paths) can be loaded
os.rename(wallet_dir(self.default_wallet_name, self.wallet_data_filename), wallet_dir("w8")) os.rename(wallet_dir("wallet.dat"), wallet_dir("w8"))
# create another dummy wallet for use in testing backups later # create another dummy wallet for use in testing backups later
self.start_node(0) self.start_node(0, [])
node.createwallet("empty")
node.createwallet(self.default_wallet_name)
self.stop_nodes() self.stop_nodes()
empty_wallet = os.path.join(self.options.tmpdir, 'empty.dat') empty_wallet = os.path.join(self.options.tmpdir, 'empty.dat')
os.rename(wallet_file("empty"), empty_wallet) os.rename(wallet_dir("wallet.dat"), empty_wallet)
shutil.rmtree(wallet_dir("empty"))
# restart node with a mix of wallet names: # restart node with a mix of wallet names:
# w1, w2, w3 - to verify new wallets created when non-existing paths specified # w1, w2, w3 - to verify new wallets created when non-existing paths specified
@ -100,27 +96,24 @@ class MultiWalletTest(BitcoinTestFramework):
# w7_symlink - to verify symlinked wallet path is initialized correctly # w7_symlink - to verify symlinked wallet path is initialized correctly
# w8 - to verify existing wallet file is loaded correctly # w8 - to verify existing wallet file is loaded correctly
# '' - to verify default wallet file is created correctly # '' - to verify default wallet file is created correctly
wallet_names = ['w1', 'w2', 'w3', 'w', 'sub/w5', os.path.join(self.options.tmpdir, 'extern/w6'), 'w7_symlink', 'w8', self.default_wallet_name] wallet_names = ['w1', 'w2', 'w3', 'w', 'sub/w5', os.path.join(self.options.tmpdir, 'extern/w6'), 'w7_symlink', 'w8', '']
if os.name == 'nt': if os.name == 'nt':
wallet_names.remove('w7_symlink') wallet_names.remove('w7_symlink')
self.start_node(0) extra_args = ['-wallet={}'.format(n) for n in wallet_names]
self.start_node(0, extra_args)
for wallet_name in wallet_names[:-2]: assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8'])
self.nodes[0].createwallet(wallet_name)
for wallet_name in wallet_names[-2:]:
self.nodes[0].loadwallet(wallet_name)
assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), [self.default_wallet_name, os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8'])
assert_equal(set(node.listwallets()), set(wallet_names)) assert_equal(set(node.listwallets()), set(wallet_names))
# should raise rpc error if wallet path can't be created
assert_raises_rpc_error(-1, "boost::filesystem::create_directory:", self.nodes[0].createwallet, "w8/bad")
# check that all requested wallets were created # check that all requested wallets were created
self.stop_node(0) self.stop_node(0)
for wallet_name in wallet_names: for wallet_name in wallet_names:
assert_equal(os.path.isfile(wallet_file(wallet_name)), True) assert_equal(os.path.isfile(wallet_file(wallet_name)), True)
# should not initialize if wallet path can't be created
exp_stderr = "boost::filesystem::create_directory:"
self.nodes[0].assert_start_raises_init_error(['-wallet=wallet.dat/bad'], exp_stderr, match=ErrorMatch.PARTIAL_REGEX)
self.nodes[0].assert_start_raises_init_error(['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" does not exist') self.nodes[0].assert_start_raises_init_error(['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" does not exist')
self.nodes[0].assert_start_raises_init_error(['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" is a relative path', cwd=data_dir()) self.nodes[0].assert_start_raises_init_error(['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" is a relative path', cwd=data_dir())
self.nodes[0].assert_start_raises_init_error(['-walletdir=debug.log'], 'Error: Specified -walletdir "debug.log" is not a directory', cwd=data_dir()) self.nodes[0].assert_start_raises_init_error(['-walletdir=debug.log'], 'Error: Specified -walletdir "debug.log" is not a directory', cwd=data_dir())
@ -152,18 +145,14 @@ class MultiWalletTest(BitcoinTestFramework):
# if wallets/ doesn't exist, datadir should be the default wallet dir # if wallets/ doesn't exist, datadir should be the default wallet dir
wallet_dir2 = data_dir('walletdir') wallet_dir2 = data_dir('walletdir')
os.rename(wallet_dir(), wallet_dir2) os.rename(wallet_dir(), wallet_dir2)
self.start_node(0) self.start_node(0, ['-wallet=w4', '-wallet=w5'])
self.nodes[0].createwallet("w4")
self.nodes[0].createwallet("w5")
assert_equal(set(node.listwallets()), {"w4", "w5"}) assert_equal(set(node.listwallets()), {"w4", "w5"})
w5 = wallet("w5") w5 = wallet("w5")
node.generatetoaddress(nblocks=1, address=w5.getnewaddress()) node.generatetoaddress(nblocks=1, address=w5.getnewaddress())
# now if wallets/ exists again, but the rootdir is specified as the walletdir, w4 and w5 should still be loaded # 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()) os.rename(wallet_dir2, wallet_dir())
self.restart_node(0, ['-nowallet', '-walletdir=' + data_dir()]) self.restart_node(0, ['-wallet=w4', '-wallet=w5', '-walletdir=' + data_dir()])
self.nodes[0].loadwallet("w4")
self.nodes[0].loadwallet("w5")
assert_equal(set(node.listwallets()), {"w4", "w5"}) assert_equal(set(node.listwallets()), {"w4", "w5"})
w5 = wallet("w5") w5 = wallet("w5")
w5_info = w5.getwalletinfo() w5_info = w5.getwalletinfo()
@ -171,16 +160,13 @@ class MultiWalletTest(BitcoinTestFramework):
competing_wallet_dir = os.path.join(self.options.tmpdir, 'competing_walletdir') competing_wallet_dir = os.path.join(self.options.tmpdir, 'competing_walletdir')
os.mkdir(competing_wallet_dir) os.mkdir(competing_wallet_dir)
self.restart_node(0, ['-nowallet', '-walletdir=' + competing_wallet_dir]) self.restart_node(0, ['-walletdir=' + competing_wallet_dir])
self.nodes[0].createwallet(self.default_wallet_name)
exp_stderr = r"Error: Error initializing wallet database environment \"\S+competing_walletdir\"!" exp_stderr = r"Error: Error initializing wallet database environment \"\S+competing_walletdir\"!"
self.nodes[1].assert_start_raises_init_error(['-walletdir=' + competing_wallet_dir], exp_stderr, match=ErrorMatch.PARTIAL_REGEX) self.nodes[1].assert_start_raises_init_error(['-walletdir=' + competing_wallet_dir], exp_stderr, match=ErrorMatch.PARTIAL_REGEX)
self.restart_node(0) self.restart_node(0, extra_args)
for wallet_name in wallet_names:
self.nodes[0].loadwallet(wallet_name)
assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), [self.default_wallet_name, os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy']) assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy'])
wallets = [wallet(w) for w in wallet_names] wallets = [wallet(w) for w in wallet_names]
wallet_bad = wallet("bad") wallet_bad = wallet("bad")
@ -270,12 +256,12 @@ class MultiWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-18, "Wallet file verification failed. Failed to load database path '{}'. Path does not exist.".format(path), self.nodes[0].loadwallet, 'wallets') assert_raises_rpc_error(-18, "Wallet file verification failed. Failed to load database path '{}'. Path does not exist.".format(path), self.nodes[0].loadwallet, 'wallets')
# Fail to load duplicate wallets # Fail to load duplicate wallets
path = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets", "w1", self.wallet_data_filename) path = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets", "w1", "wallet.dat")
assert_raises_rpc_error(-4, "Wallet file verification failed. Refusing to load database. Data file '{}' is already loaded.".format(path), self.nodes[0].loadwallet, wallet_names[0]) assert_raises_rpc_error(-4, "Wallet file verification failed. Refusing to load database. Data file '{}' is already loaded.".format(path), self.nodes[0].loadwallet, wallet_names[0])
# Fail to load duplicate wallets by different ways (directory and filepath) # Fail to load duplicate wallets by different ways (directory and filepath)
path = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets", self.wallet_data_filename) path = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets", "wallet.dat")
assert_raises_rpc_error(-4, "Wallet file verification failed. Refusing to load database. Data file '{}' is already loaded.".format(path), self.nodes[0].loadwallet, self.wallet_data_filename) assert_raises_rpc_error(-4, "Wallet file verification failed. Refusing to load database. Data file '{}' is already loaded.".format(path), self.nodes[0].loadwallet, 'wallet.dat')
# Fail to load if one wallet is a copy of another # Fail to load if one wallet is a copy of another
assert_raises_rpc_error(-4, "BerkeleyDatabase: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy') assert_raises_rpc_error(-4, "BerkeleyDatabase: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
@ -348,7 +334,7 @@ class MultiWalletTest(BitcoinTestFramework):
assert_equal(self.nodes[0].listwallets(), ['w1']) assert_equal(self.nodes[0].listwallets(), ['w1'])
assert_equal(w1.getwalletinfo()['walletname'], 'w1') assert_equal(w1.getwalletinfo()['walletname'], 'w1')
assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), [self.default_wallet_name, os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy', 'w9']) assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy', 'w9'])
# Test backing up and restoring wallets # Test backing up and restoring wallets
self.log.info("Test wallet backup") self.log.info("Test wallet backup")

View File

@ -88,7 +88,7 @@ class ReorgsRestoreTest(BitcoinTestFramework):
# Node0 wallet file is loaded on longest sync'ed node1 # Node0 wallet file is loaded on longest sync'ed node1
self.stop_node(1) self.stop_node(1)
self.nodes[0].backupwallet(os.path.join(self.nodes[0].datadir, 'wallet.bak')) self.nodes[0].backupwallet(os.path.join(self.nodes[0].datadir, 'wallet.bak'))
shutil.copyfile(os.path.join(self.nodes[0].datadir, 'wallet.bak'), os.path.join(self.nodes[1].datadir, self.chain, self.default_wallet_name, self.wallet_data_filename)) shutil.copyfile(os.path.join(self.nodes[0].datadir, 'wallet.bak'), os.path.join(self.nodes[1].datadir, self.chain, 'wallet.dat'))
self.start_node(1) self.start_node(1)
tx_after_reorg = self.nodes[1].gettransaction(txid) tx_after_reorg = self.nodes[1].gettransaction(txid)
# Check that normal confirmed tx is confirmed again but with different blockhash # Check that normal confirmed tx is confirmed again but with different blockhash

View File

@ -26,16 +26,6 @@ class WalletStartupTest(BitcoinTestFramework):
self.start_nodes() self.start_nodes()
def run_test(self): def run_test(self):
self.log.info('Should start without any wallets')
assert_equal(self.nodes[0].listwallets(), [])
assert_equal(self.nodes[0].listwalletdir(), {'wallets': []})
self.log.info('New default wallet should load by default when there are no other wallets')
self.nodes[0].createwallet(wallet_name='', load_on_startup=False)
self.restart_node(0)
assert_equal(self.nodes[0].listwallets(), [''])
self.log.info('Test load on startup behavior')
self.nodes[0].createwallet(wallet_name='w0', load_on_startup=True) self.nodes[0].createwallet(wallet_name='w0', load_on_startup=True)
self.nodes[0].createwallet(wallet_name='w1', load_on_startup=False) self.nodes[0].createwallet(wallet_name='w1', load_on_startup=False)
self.nodes[0].createwallet(wallet_name='w2', load_on_startup=True) self.nodes[0].createwallet(wallet_name='w2', load_on_startup=True)