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
{
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.args = &args;
@ -598,8 +599,8 @@ public:
m_rpc_handlers.emplace_back(m_context.chain->handleRpc(m_rpc_commands.back()));
}
}
bool verify() override { return VerifyWallets(*m_context.chain); }
bool load() override { return LoadWallets(*m_context.chain); }
bool verify() override { return VerifyWallets(*m_context.chain, m_wallet_filenames); }
bool load() override { return LoadWallets(*m_context.chain, m_wallet_filenames); }
void start(CScheduler& scheduler) override { return StartWallets(scheduler, *Assert(m_context.args)); }
void flush() override { return FlushWallets(); }
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<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

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
//! 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

View File

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

View File

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

View File

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

View File

@ -2,8 +2,6 @@
// Distributed under the MIT software license, see the accompanying
// 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/walletmodel.h>
@ -14,11 +12,8 @@
#include <cassert>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
WalletFrame::WalletFrame(BitcoinGUI* _gui) :
QFrame(_gui),
@ -31,25 +26,9 @@ WalletFrame::WalletFrame(BitcoinGUI* _gui) :
walletFrameLayout->setContentsMargins(0,0,0,0);
walletFrameLayout->addWidget(walletStack);
// hbox for no wallet
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 -"));
QLabel *noWallet = new QLabel(tr("No wallet has been loaded."));
noWallet->setAlignment(Qt::AlignCenter);
no_wallet_layout->addWidget(noWallet, 0, Qt::AlignHCenter | Qt::AlignBottom);
// 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);
walletStack->addWidget(noWallet);
masternodeListPage = new MasternodeList();
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);
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("-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("-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);
@ -166,7 +166,16 @@ void WalletInit::Construct(NodeContext& node) const
LogPrintf("Wallet disabled!\n");
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.chain_clients.emplace_back(std::move(wallet_client));
}

View File

@ -19,7 +19,7 @@
#include <univalue.h>
bool VerifyWallets(interfaces::Chain& chain)
bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
{
if (gArgs.IsArgSet("-walletdir")) {
fs::path wallet_dir = gArgs.GetArg("-walletdir", "");
@ -44,27 +44,10 @@ bool VerifyWallets(interfaces::Chain& chain)
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.
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());
if (!wallet_paths.insert(path).second) {
@ -74,36 +57,27 @@ bool VerifyWallets(interfaces::Chain& chain)
DatabaseOptions options;
DatabaseStatus status;
options.require_existing = true;
options.verify = true;
bilingual_str error_string;
if (!MakeWalletDatabase(wallet_file, options, status, error_string)) {
if (status == DatabaseStatus::FAILED_NOT_FOUND) {
chain.initWarning(Untranslated(strprintf("Skipping -wallet path that doesn't exist. %s\n", error_string.original)));
} else {
chain.initError(error_string);
return false;
}
chain.initError(error_string);
return false;
}
}
return true;
}
bool LoadWallets(interfaces::Chain& chain)
bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
{
try {
for (const std::string& name : gArgs.GetArgs("-wallet")) {
for (const std::string& name : wallet_files) {
DatabaseOptions options;
DatabaseStatus status;
options.require_existing = true;
options.verify = false; // No need to verify, assuming verified earlier in VerifyWallets()
bilingual_str error_string;
std::vector<bilingual_str> warnings;
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;
if (!warnings.empty()) chain.initWarning(Join(warnings, Untranslated("\n")));
if (!pwallet) {

View File

@ -18,10 +18,10 @@ class Chain;
} // namespace interfaces
//! 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.
bool LoadWallets(interfaces::Chain& chain);
bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
//! Complete startup of wallets.
void StartWallets(CScheduler& scheduler, const ArgsManager& args);

View File

@ -10,7 +10,7 @@
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;
sep += fs::path::preferred_separator;

View File

@ -21,7 +21,7 @@ struct WalletTestingSetup : public TestingSetup {
explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
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;
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
};

View File

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

View File

@ -14,7 +14,6 @@ class ConfArgsTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
self.supports_cli = False
self.wallet_names = []
def test_config_file_parser(self):
# Assume node is stopped
@ -148,15 +147,19 @@ class ConfArgsTest(BitcoinTestFramework):
# Create the directory and ensure the config file now works
os.mkdir(new_data_dir)
# 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)
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
os.mkdir(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'))
if self.is_wallet_compiled():
assert os.path.exists(os.path.join(new_data_dir_2, self.chain, 'wallets', 'w2'))
if __name__ == '__main__':

View File

@ -15,7 +15,7 @@ class FilelockTest(BitcoinTestFramework):
def setup_network(self):
self.add_nodes(self.num_nodes, extra_args=None)
self.nodes[0].start()
self.nodes[0].start([])
self.nodes[0].wait_for_rpc_connection()
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)
if self.is_wallet_compiled():
self.nodes[0].createwallet(self.default_wallet_name)
wallet_dir = os.path.join(datadir, 'wallets')
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"
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__':
FilelockTest().main()

View File

@ -43,8 +43,8 @@ class NotificationsTest(BitcoinTestFramework):
"-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s'))],
["-blockversion=211",
"-rescan",
"-wallet={}".format(self.wallet),
"-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()
def run_test(self):

View File

@ -106,7 +106,8 @@ class PruneTest(BitcoinTestFramework):
def setup_nodes(self):
self.add_nodes(self.num_nodes, self.extra_args)
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):
# Start by creating some coinbases we can spend later

View File

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

View File

@ -18,10 +18,6 @@ class HTTPBasicsTest(BitcoinTestFramework):
self.num_nodes = 1
self.supports_cli = False
def setup_nodes(self):
self.add_nodes(self.num_nodes)
self.start_nodes()
def setup_chain(self):
super().setup_chain()
# Append rpcauth to dash.conf before initialization
@ -40,6 +36,7 @@ class HTTPBasicsTest(BitcoinTestFramework):
f.write(rpcauthoperator+"\n")
def run_test(self):
url = urllib.parse.urlparse(self.nodes[0].url)
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.stop_node(0)
shutil.rmtree(os.path.join(self.nodes[0].datadir, self.chain, 'wallets'))
self.start_node(0, ['-nowallet'])
self.import_deterministic_coinbase_privkeys()
self.start_node(0)
self.nodes[0].generate(110)
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.supports_cli = 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 = []
# 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()
assert self.wallet_names is None or len(self.wallet_names) <= self.num_nodes
self.parse_args()
if self.options.timeout_factor == 0 :
self.options.timeout_factor = 99999
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
self.add_nodes(self.num_nodes, extra_args)
self.start_nodes()
if self.is_wallet_compiled():
self.import_deterministic_coinbase_privkeys()
self.import_deterministic_coinbase_privkeys()
if not self.setup_clean_chain:
for n in self.nodes:
assert_equal(n.getblockchaininfo()["blocks"], 199)
@ -414,15 +404,13 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
assert_equal(chain_info["initialblockdownload"], False)
def import_deterministic_coinbase_privkeys(self):
for i in range(len(self.nodes)):
self.init_wallet(i)
for n in self.nodes:
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')
def run_test(self):
@ -940,7 +928,6 @@ class DashTestFramework(BitcoinTestFramework):
idx = len(self.nodes)
self.add_nodes(1, extra_args=[self.extra_args[idx]])
self.start_node(idx)
self.nodes[idx].createwallet(self.default_wallet_name)
for i in range(0, idx):
self.connect_nodes(i, idx)
@ -1100,6 +1087,7 @@ class DashTestFramework(BitcoinTestFramework):
self.prepare_masternodes()
self.prepare_datadirs()
self.start_masternodes()
self.import_deterministic_coinbase_privkeys()
# non-masternodes where disconnected from the control node during prepare_datadirs,
# 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")
self.assert_raises_tool_error(
'Error initializing wallet database environment "{}"!'.format(locked_dir),
'-wallet=' + self.default_wallet_name,
'-wallet=wallet.dat',
'info',
)
path = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets", "nonexistent.dat")
@ -118,7 +118,7 @@ class ToolWalletTest(BitcoinTestFramework):
Transactions: 0
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()
self.log.debug('Wallet file timestamp after calling info: {}'.format(timestamp_after))
self.log_wallet_timestamp_comparison(timestamp_before, timestamp_after)
@ -157,7 +157,7 @@ class ToolWalletTest(BitcoinTestFramework):
Transactions: 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()
timestamp_after = self.wallet_timestamp()
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):
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')
shasum_before = self.wallet_shasum()
@ -219,14 +219,13 @@ class ToolWalletTest(BitcoinTestFramework):
def test_salvage(self):
# TODO: Check salvage actually salvages and doesn't break things. https://github.com/bitcoin/bitcoin/issues/7463
self.log.info('Check salvage')
self.start_node(0)
self.nodes[0].createwallet("salvage")
self.start_node(0, ['-wallet=salvage'])
self.stop_node(0)
self.assert_tool_output('', '-wallet=salvage', 'salvage')
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()
# Warning: The following tests are order-dependent.
self.test_tool_wallet_info()

View File

@ -87,10 +87,10 @@ class WalletBackupTest(BitcoinTestFramework):
self.sync_blocks()
# As above, this mirrors the original bash test.
def start_three(self, args=()):
self.start_node(0, self.extra_args[0] + list(args))
self.start_node(1, self.extra_args[1] + list(args))
self.start_node(2, self.extra_args[2] + list(args))
def start_three(self):
self.start_node(0)
self.start_node(1)
self.start_node(2)
self.connect_nodes(0, 3)
self.connect_nodes(1, 3)
self.connect_nodes(2, 3)
@ -102,14 +102,9 @@ class WalletBackupTest(BitcoinTestFramework):
self.stop_node(2)
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[1].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename))
os.remove(os.path.join(self.nodes[2].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename))
def init_three(self):
self.init_wallet(0)
self.init_wallet(1)
self.init_wallet(2)
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', 'wallet.dat'))
os.remove(os.path.join(self.nodes[2].datadir, self.chain, 'wallets', 'wallet.dat'))
def run_test(self):
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'))
# 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[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[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[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', 'wallet.dat'))
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.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, 'llmq'))
self.start_three(["-nowallet"])
self.init_three()
self.start_three()
assert_equal(self.nodes[0].getbalance(), 0)
assert_equal(self.nodes[1].getbalance(), 0)
@ -214,9 +208,9 @@ class WalletBackupTest(BitcoinTestFramework):
# Backup to source wallet file must fail
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', self.default_wallet_name, self.wallet_data_filename),
os.path.join(self.nodes[0].datadir, self.chain, 'wallets', self.default_wallet_name),
os.path.join(self.nodes[0].datadir, self.chain, 'wallets', 'wallet.dat'),
os.path.join(self.nodes[0].datadir, self.chain, '.', 'wallets', 'wallet.dat'),
os.path.join(self.nodes[0].datadir, self.chain, 'wallets', ''),
os.path.join(self.nodes[0].datadir, self.chain, 'wallets')]
for sourcePath in sourcePaths:

View File

@ -165,10 +165,10 @@ class WalletTest(BitcoinTestFramework):
# dynamically loading the wallet.
before = self.nodes[1].getunconfirmedbalance()
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.sync_all()
self.nodes[1].loadwallet(self.default_wallet_name)
self.nodes[1].loadwallet('')
after = self.nodes[1].getunconfirmedbalance()
assert_equal(before + Decimal('0.1'), after)

View File

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

View File

@ -91,8 +91,6 @@ class WalletDumpTest(BitcoinTestFramework):
self.start_nodes()
def run_test(self):
self.nodes[0].createwallet("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")
@ -142,8 +140,8 @@ class WalletDumpTest(BitcoinTestFramework):
assert_raises_rpc_error(-8, "already exists", lambda: self.nodes[0].dumpwallet(wallet_enc_dump))
# Restart node with new wallet, and test importwallet
self.restart_node(0)
self.nodes[0].createwallet("w2")
self.stop_node(0)
self.start_node(0, ['-wallet=w2'])
# Make sure the address is not IsMine before import
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, "evodb"))
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "llmq"))
shutil.copyfile(
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),
)
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, self.chain, "wallets", "wallet.dat"))
self.start_node(1)
# 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, "evodb"))
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "llmq"))
shutil.copyfile(
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),
)
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, self.chain, "wallets", "wallet.dat"))
self.start_node(1, extra_args=self.extra_args[1])
self.connect_nodes(0, 1)
self.sync_all()

View File

@ -135,7 +135,8 @@ class ImportRescanTest(BitcoinTestFramework):
# Import keys with pruning disabled
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.start_nodes()

View File

@ -673,7 +673,7 @@ class ImportMultiTest(BitcoinTestFramework):
# 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")
wrpc = self.nodes[1].get_wallet_rpc(self.default_wallet_name)
wrpc = self.nodes[1].get_wallet_rpc("")
assert wrpc.getwalletinfo()['private_keys_enabled']
result = wrpc.importmulti(
[{

View File

@ -29,7 +29,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
self.skip_if_no_wallet()
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")
self.nodes[0].generate(101)

View File

@ -43,7 +43,6 @@ class MultiWalletTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 2
self.rpc_timeout = 120
self.extra_args = [["-nowallet"], []]
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@ -64,14 +63,14 @@ class MultiWalletTest(BitcoinTestFramework):
def wallet_file(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)
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
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
# through symlink
@ -81,16 +80,13 @@ class MultiWalletTest(BitcoinTestFramework):
# rename wallet.dat to make sure plain wallet file paths (as opposed to
# 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
self.start_node(0)
node.createwallet("empty")
node.createwallet(self.default_wallet_name)
self.start_node(0, [])
self.stop_nodes()
empty_wallet = os.path.join(self.options.tmpdir, 'empty.dat')
os.rename(wallet_file("empty"), empty_wallet)
shutil.rmtree(wallet_dir("empty"))
os.rename(wallet_dir("wallet.dat"), empty_wallet)
# restart node with a mix of wallet names:
# 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
# w8 - to verify existing wallet file is loaded 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':
wallet_names.remove('w7_symlink')
self.start_node(0)
for wallet_name in wallet_names[:-2]:
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'])
extra_args = ['-wallet={}'.format(n) for n in wallet_names]
self.start_node(0, extra_args)
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'])
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
self.stop_node(0)
for wallet_name in wallet_names:
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" 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())
@ -152,18 +145,14 @@ class MultiWalletTest(BitcoinTestFramework):
# if wallets/ doesn't exist, datadir should be the default wallet dir
wallet_dir2 = data_dir('walletdir')
os.rename(wallet_dir(), wallet_dir2)
self.start_node(0)
self.nodes[0].createwallet("w4")
self.nodes[0].createwallet("w5")
self.start_node(0, ['-wallet=w4', '-wallet=w5'])
assert_equal(set(node.listwallets()), {"w4", "w5"})
w5 = wallet("w5")
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
os.rename(wallet_dir2, wallet_dir())
self.restart_node(0, ['-nowallet', '-walletdir=' + data_dir()])
self.nodes[0].loadwallet("w4")
self.nodes[0].loadwallet("w5")
self.restart_node(0, ['-wallet=w4', '-wallet=w5', '-walletdir=' + data_dir()])
assert_equal(set(node.listwallets()), {"w4", "w5"})
w5 = wallet("w5")
w5_info = w5.getwalletinfo()
@ -171,16 +160,13 @@ class MultiWalletTest(BitcoinTestFramework):
competing_wallet_dir = os.path.join(self.options.tmpdir, 'competing_walletdir')
os.mkdir(competing_wallet_dir)
self.restart_node(0, ['-nowallet', '-walletdir=' + competing_wallet_dir])
self.nodes[0].createwallet(self.default_wallet_name)
self.restart_node(0, ['-walletdir=' + competing_wallet_dir])
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.restart_node(0)
for wallet_name in wallet_names:
self.nodes[0].loadwallet(wallet_name)
self.restart_node(0, extra_args)
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]
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')
# 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])
# 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)
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)
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, 'wallet.dat')
# 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')
@ -348,7 +334,7 @@ class MultiWalletTest(BitcoinTestFramework):
assert_equal(self.nodes[0].listwallets(), ['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
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
self.stop_node(1)
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)
tx_after_reorg = self.nodes[1].gettransaction(txid)
# Check that normal confirmed tx is confirmed again but with different blockhash

View File

@ -26,16 +26,6 @@ class WalletStartupTest(BitcoinTestFramework):
self.start_nodes()
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='w1', load_on_startup=False)
self.nodes[0].createwallet(wallet_name='w2', load_on_startup=True)