mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
Merge pull request #5198 from kittywhiskers/sqlite_tests
test: adjust functional tests to account for SQLite-only builds, add CI run
This commit is contained in:
commit
e50d96d06f
@ -251,6 +251,13 @@ linux64_cxx20-build:
|
||||
variables:
|
||||
BUILD_TARGET: linux64_cxx20
|
||||
|
||||
linux64_sqlite-build:
|
||||
extends: .build-template
|
||||
needs:
|
||||
- x86_64-pc-linux-gnu-debug
|
||||
variables:
|
||||
BUILD_TARGET: linux64_sqlite
|
||||
|
||||
linux64_fuzz-build:
|
||||
extends: .build-template
|
||||
needs:
|
||||
@ -312,6 +319,13 @@ linux64-test:
|
||||
variables:
|
||||
BUILD_TARGET: linux64
|
||||
|
||||
linux64_sqlite-test:
|
||||
extends: .test-template
|
||||
needs:
|
||||
- linux64_sqlite-build
|
||||
variables:
|
||||
BUILD_TARGET: linux64_sqlite
|
||||
|
||||
linux64_tsan-test:
|
||||
extends:
|
||||
- .test-template
|
||||
|
@ -30,6 +30,8 @@ elif [ "$BUILD_TARGET" = "linux64_fuzz" ]; then
|
||||
source ./ci/test/00_setup_env_native_fuzz.sh
|
||||
elif [ "$BUILD_TARGET" = "linux64_cxx20" ]; then
|
||||
source ./ci/test/00_setup_env_native_cxx20.sh
|
||||
elif [ "$BUILD_TARGET" = "linux64_sqlite" ]; then
|
||||
source ./ci/test/00_setup_env_native_sqlite.sh
|
||||
elif [ "$BUILD_TARGET" = "linux64_nowallet" ]; then
|
||||
source ./ci/test/00_setup_env_native_nowallet.sh
|
||||
elif [ "$BUILD_TARGET" = "mac" ]; then
|
||||
|
12
ci/test/00_setup_env_native_sqlite.sh
Normal file
12
ci/test/00_setup_env_native_sqlite.sh
Normal file
@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2019 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
export PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libdbus-1-dev libharfbuzz-dev"
|
||||
export DEP_OPTS="NO_BDB=1 NO_UPNP=1 DEBUG=1"
|
||||
export GOAL="install"
|
||||
export BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports --with-sqlite --without-bdb LDFLAGS=-static-libstdc++"
|
@ -40,7 +40,6 @@ void DummyWalletInit::AddWalletOptions(ArgsManager& argsman) const
|
||||
"-rescan=<mode>",
|
||||
"-salvagewallet",
|
||||
"-spendzeroconfchange",
|
||||
"-upgradewallet",
|
||||
"-wallet=<path>",
|
||||
"-walletbackupsdir=<dir>",
|
||||
"-walletbroadcast",
|
||||
|
@ -1465,36 +1465,13 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QPushButton" name="btn_upgradewallet">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>180</width>
|
||||
<height>23</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Upgrade wallet format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="label_repair_upgrade">
|
||||
<property name="text">
|
||||
<string>-upgradewallet: Upgrade wallet to latest format on startup. (Note: this is NOT an update of the wallet itself!)</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QPushButton" name="btn_reindex">
|
||||
<property name="text">
|
||||
<string>Rebuild index</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="label_repair_reindex">
|
||||
<property name="text">
|
||||
<string>-reindex: Rebuild block chain index from current blk000??.dat files.</string>
|
||||
@ -1504,7 +1481,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="6" column="1">
|
||||
<spacer name="verticalSpacerRepair">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
|
@ -60,7 +60,6 @@ const TrafficGraphData::GraphRange INITIAL_TRAFFIC_GRAPH_SETTING = TrafficGraphD
|
||||
// Repair parameters
|
||||
const QString RESCAN1("-rescan=1");
|
||||
const QString RESCAN2("-rescan=2");
|
||||
const QString UPGRADEWALLET("-upgradewallet");
|
||||
const QString REINDEX("-reindex");
|
||||
|
||||
namespace {
|
||||
@ -496,10 +495,8 @@ RPCConsole::RPCConsole(interfaces::Node& node, QWidget* parent, Qt::WindowFlags
|
||||
// Disable wallet repair options that require a wallet (enable them later when a wallet is added)
|
||||
ui->btn_rescan1->setEnabled(false);
|
||||
ui->btn_rescan2->setEnabled(false);
|
||||
ui->btn_upgradewallet->setEnabled(false);
|
||||
connect(ui->btn_rescan1, &QPushButton::clicked, this, &RPCConsole::walletRescan1);
|
||||
connect(ui->btn_rescan2, &QPushButton::clicked, this, &RPCConsole::walletRescan2);
|
||||
connect(ui->btn_upgradewallet, &QPushButton::clicked, this, &RPCConsole::walletUpgrade);
|
||||
connect(ui->btn_reindex, &QPushButton::clicked, this, &RPCConsole::walletReindex);
|
||||
|
||||
// Register RPC timer interface
|
||||
@ -726,7 +723,6 @@ void RPCConsole::addWallet(WalletModel * const walletModel)
|
||||
// The only loaded wallet
|
||||
ui->btn_rescan1->setEnabled(true);
|
||||
ui->btn_rescan2->setEnabled(true);
|
||||
ui->btn_upgradewallet->setEnabled(true);
|
||||
QString wallet_path = QString::fromStdString(GetWalletDir().string() + QDir::separator().toLatin1());
|
||||
QString wallet_name = walletModel->getWalletName().isEmpty() ? "wallet.dat" : walletModel->getWalletName();
|
||||
ui->wallet_path->setText(wallet_path + wallet_name);
|
||||
@ -736,7 +732,6 @@ void RPCConsole::addWallet(WalletModel * const walletModel)
|
||||
// No wallet recovery for multiple loaded wallets
|
||||
ui->btn_rescan1->setEnabled(false);
|
||||
ui->btn_rescan2->setEnabled(false);
|
||||
ui->btn_upgradewallet->setEnabled(false);
|
||||
ui->wallet_path->clear();
|
||||
}
|
||||
}
|
||||
@ -750,7 +745,6 @@ void RPCConsole::removeWallet(WalletModel * const walletModel)
|
||||
// Back to the only loaded wallet
|
||||
ui->btn_rescan1->setEnabled(true);
|
||||
ui->btn_rescan2->setEnabled(true);
|
||||
ui->btn_upgradewallet->setEnabled(true);
|
||||
WalletModel* wallet_model = ui->WalletSelector->itemData(1).value<WalletModel*>();
|
||||
QString wallet_path = QString::fromStdString(GetWalletDir().string() + QDir::separator().toLatin1());
|
||||
QString wallet_name = wallet_model->getWalletName().isEmpty() ? "wallet.dat" : wallet_model->getWalletName();
|
||||
@ -759,7 +753,6 @@ void RPCConsole::removeWallet(WalletModel * const walletModel)
|
||||
// No wallet recovery for multiple loaded wallets
|
||||
ui->btn_rescan1->setEnabled(false);
|
||||
ui->btn_rescan2->setEnabled(false);
|
||||
ui->btn_upgradewallet->setEnabled(false);
|
||||
ui->wallet_path->clear();
|
||||
}
|
||||
}
|
||||
@ -821,12 +814,6 @@ void RPCConsole::walletRescan2()
|
||||
buildParameterlist(RESCAN2);
|
||||
}
|
||||
|
||||
/** Restart wallet with "-upgradewallet" */
|
||||
void RPCConsole::walletUpgrade()
|
||||
{
|
||||
buildParameterlist(UPGRADEWALLET);
|
||||
}
|
||||
|
||||
/** Restart wallet with "-reindex" */
|
||||
void RPCConsole::walletReindex()
|
||||
{
|
||||
@ -852,7 +839,6 @@ void RPCConsole::buildParameterlist(QString arg)
|
||||
// Remove existing repair-options
|
||||
args.removeAll(RESCAN1);
|
||||
args.removeAll(RESCAN2);
|
||||
args.removeAll(UPGRADEWALLET);
|
||||
args.removeAll(REINDEX);
|
||||
|
||||
// Append repair parameter to command line.
|
||||
|
@ -108,7 +108,6 @@ public Q_SLOTS:
|
||||
/** Wallet repair options */
|
||||
void walletRescan1();
|
||||
void walletRescan2();
|
||||
void walletUpgrade();
|
||||
void walletReindex();
|
||||
|
||||
/** Append the message to the message widget */
|
||||
|
@ -182,6 +182,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "getspecialtxes", 3, "skip" },
|
||||
{ "getspecialtxes", 4, "verbosity" },
|
||||
{ "disconnectnode", 1, "nodeid" },
|
||||
{ "upgradewallet", 0, "version" },
|
||||
// Echo with conversion (For testing only)
|
||||
{ "echojson", 0, "arg0" },
|
||||
{ "echojson", 1, "arg1" },
|
||||
|
@ -62,7 +62,6 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const
|
||||
argsman.AddArg("-rescan=<mode>", "Rescan the block chain for missing wallet transactions on startup"
|
||||
" (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("-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);
|
||||
@ -129,8 +128,6 @@ bool WalletInit::ParameterInteraction() const
|
||||
return InitError(_("You can not start a masternode with wallet enabled."));
|
||||
}
|
||||
|
||||
const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;
|
||||
|
||||
if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && gArgs.SoftSetBoolArg("-walletbroadcast", false)) {
|
||||
LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__);
|
||||
}
|
||||
@ -146,12 +143,6 @@ bool WalletInit::ParameterInteraction() const
|
||||
gArgs.ForceRemoveArg("rescan");
|
||||
}
|
||||
|
||||
if (is_multiwallet) {
|
||||
if (gArgs.GetBoolArg("-upgradewallet", false)) {
|
||||
return InitError(strprintf(_("%s is only allowed with a single wallet file"), "-upgradewallet"));
|
||||
}
|
||||
}
|
||||
|
||||
if (gArgs.GetBoolArg("-sysperms", false))
|
||||
return InitError(Untranslated("-sysperms is not allowed in combination with enabled wallet functionality"));
|
||||
|
||||
|
@ -2748,7 +2748,7 @@ static UniValue loadwallet(const JSONRPCRequest& request)
|
||||
RPCHelpMan{"loadwallet",
|
||||
"\nLoads a wallet from a wallet file or directory."
|
||||
"\nNote that all wallet command-line options used when starting dashd will be"
|
||||
"\napplied to the new wallet (eg -upgradewallet, rescan, etc).\n",
|
||||
"\napplied to the new wallet (eg, rescan, etc).\n",
|
||||
{
|
||||
{"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet directory or .dat file."},
|
||||
{"load_on_startup", RPCArg::Type::BOOL, /* default */ "null", "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
|
||||
@ -4064,6 +4064,42 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
|
||||
return result;
|
||||
}
|
||||
|
||||
static UniValue upgradewallet(const JSONRPCRequest& request)
|
||||
{
|
||||
RPCHelpMan{"upgradewallet",
|
||||
"\nUpgrade the wallet. Upgrades to the latest version if no version number is specified\n"
|
||||
"New keys may be generated and a new wallet backup will need to be made.",
|
||||
{
|
||||
{"version", RPCArg::Type::NUM, /* default */ strprintf("%d", FEATURE_LATEST), "The version number to upgrade to. Default is the latest wallet version"}
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{
|
||||
HelpExampleCli("upgradewallet", "120200")
|
||||
+ HelpExampleRpc("upgradewallet", "120200")
|
||||
}
|
||||
}.Check(request);
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
RPCTypeCheck(request.params, {UniValue::VNUM}, true);
|
||||
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
|
||||
int version = 0;
|
||||
if (!request.params[0].isNull()) {
|
||||
version = request.params[0].get_int();
|
||||
}
|
||||
|
||||
bilingual_str error;
|
||||
std::vector<bilingual_str> warnings;
|
||||
if (!pwallet->UpgradeWallet(version, error, warnings)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, error.original);
|
||||
}
|
||||
return error.original;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
static const CRPCCommand commands[] =
|
||||
{ // category name actor (function) argNames
|
||||
@ -4123,6 +4159,7 @@ static const CRPCCommand commands[] =
|
||||
{ "wallet", "signmessage", &signmessage, {"address","message"} },
|
||||
{ "wallet", "signrawtransactionwithwallet", &signrawtransactionwithwallet, {"hexstring","prevtxs","sighashtype"} },
|
||||
{ "wallet", "unloadwallet", &unloadwallet, {"wallet_name", "load_on_startup"} },
|
||||
{ "wallet", "upgradewallet", &upgradewallet, {"version"} },
|
||||
{ "wallet", "upgradetohd", &upgradetohd, {"mnemonic", "mnemonicpassphrase", "walletpassphrase", "rescan"} },
|
||||
{ "wallet", "walletlock", &walletlock, {} },
|
||||
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
|
||||
|
@ -4306,27 +4306,9 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
|
||||
}
|
||||
}
|
||||
|
||||
if (gArgs.GetBoolArg("-upgradewallet", fFirstRun))
|
||||
{
|
||||
int nMaxVersion = gArgs.GetArg("-upgradewallet", 0);
|
||||
auto nMinVersion = DEFAULT_USE_HD_WALLET ? FEATURE_LATEST : FEATURE_COMPRPUBKEY;
|
||||
if (nMaxVersion == 0) // the -upgradewallet without argument case
|
||||
{
|
||||
walletInstance->WalletLogPrintf("Performing wallet upgrade to %i\n", nMinVersion);
|
||||
nMaxVersion = FEATURE_LATEST;
|
||||
walletInstance->SetMinVersion(nMinVersion); // permanently upgrade the wallet immediately
|
||||
}
|
||||
else
|
||||
walletInstance->WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
|
||||
if (nMaxVersion < walletInstance->GetVersion())
|
||||
{
|
||||
return unload_wallet(_("Cannot downgrade wallet"));
|
||||
}
|
||||
walletInstance->SetMaxVersion(nMaxVersion);
|
||||
}
|
||||
|
||||
if (fFirstRun)
|
||||
{
|
||||
walletInstance->SetMaxVersion(FEATURE_LATEST);
|
||||
walletInstance->SetWalletFlags(wallet_creation_flags, false);
|
||||
if (!(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
|
||||
// Create new HD chain
|
||||
@ -4596,6 +4578,27 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
|
||||
return walletInstance;
|
||||
}
|
||||
|
||||
bool CWallet::UpgradeWallet(int version, bilingual_str& error, std::vector<bilingual_str>& warnings)
|
||||
{
|
||||
int nMaxVersion = version;
|
||||
auto nMinVersion = DEFAULT_USE_HD_WALLET ? FEATURE_LATEST : FEATURE_COMPRPUBKEY;
|
||||
if (nMaxVersion == 0) {
|
||||
WalletLogPrintf("Performing wallet upgrade to %i\n", nMinVersion);
|
||||
nMaxVersion = FEATURE_LATEST;
|
||||
SetMinVersion(nMinVersion); // permanently upgrade the wallet immediately
|
||||
} else {
|
||||
WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
|
||||
}
|
||||
|
||||
if (nMaxVersion < GetVersion()) {
|
||||
error = Untranslated("Cannot downgrade wallet");
|
||||
return false;
|
||||
}
|
||||
|
||||
SetMaxVersion(nMaxVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CWallet::postInitProcess()
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
|
@ -1241,6 +1241,9 @@ public:
|
||||
LogPrintf(("%s " + fmt).c_str(), GetDisplayName(), parameters...);
|
||||
};
|
||||
|
||||
/** Upgrade the wallet */
|
||||
bool UpgradeWallet(int version, bilingual_str& error, std::vector<bilingual_str>& warnings);
|
||||
|
||||
/** Get last block processed height */
|
||||
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
|
||||
{
|
||||
|
@ -16,6 +16,8 @@ RPCAUTH=@abs_top_srcdir@/share/rpcauth/rpcauth.py
|
||||
[components]
|
||||
# Which components are enabled. These are commented out by `configure` if they were disabled when running config.
|
||||
@ENABLE_WALLET_TRUE@ENABLE_WALLET=true
|
||||
@USE_SQLITE_TRUE@USE_SQLITE=true
|
||||
@USE_BDB_TRUE@USE_BDB=true
|
||||
@BUILD_BITCOIN_CLI_TRUE@ENABLE_CLI=true
|
||||
@BUILD_BITCOIN_WALLET_TRUE@ENABLE_WALLET_TOOL=true
|
||||
@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=true
|
||||
|
@ -4,6 +4,8 @@
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Check that it's not possible to start a second bitcoind instance using the same datadir or wallet."""
|
||||
import os
|
||||
import random
|
||||
import string
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.test_node import ErrorMatch
|
||||
@ -27,11 +29,14 @@ 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_name = ''.join([random.choice(string.ascii_lowercase) for _ in range(6)])
|
||||
self.nodes[0].createwallet(wallet_name=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: SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another dashd?"
|
||||
if self.is_bdb_compiled():
|
||||
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), '-wallet=' + wallet_name, '-noserver'], expected_msg=expected_msg, match=ErrorMatch.PARTIAL_REGEX)
|
||||
|
||||
if __name__ == '__main__':
|
||||
FilelockTest().main()
|
||||
|
@ -48,6 +48,12 @@ class NotificationsTest(BitcoinTestFramework):
|
||||
super().setup_network()
|
||||
|
||||
def run_test(self):
|
||||
if self.is_wallet_compiled():
|
||||
# Make the wallets
|
||||
# Ensures that node 0 and node 1 share the same wallet for the conflicting transaction tests below.
|
||||
for i, name in enumerate(self.wallet_names):
|
||||
self.nodes[i].createwallet(wallet_name=name, load_on_startup=True)
|
||||
|
||||
self.log.info("test -blocknotify")
|
||||
block_count = 10
|
||||
blocks = self.nodes[1].generatetoaddress(block_count, self.nodes[1].getnewaddress() if self.is_wallet_compiled() else ADDRESS_BCRT1_UNSPENDABLE)
|
||||
|
@ -23,6 +23,7 @@ class TestBitcoinCli(BitcoinTestFramework):
|
||||
|
||||
self.log.info("Compare responses from getwalletinfo RPC and `dash-cli getwalletinfo`")
|
||||
if self.is_wallet_compiled():
|
||||
self.nodes[0].createwallet(self.default_wallet_name)
|
||||
cli_response = self.nodes[0].cli.getwalletinfo()
|
||||
rpc_response = self.nodes[0].getwalletinfo()
|
||||
assert_equal(cli_response, rpc_response)
|
||||
|
@ -120,7 +120,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
self.supports_cli = True
|
||||
self.bind_to_localhost_only = True
|
||||
self.parse_args()
|
||||
self.default_wallet_name = ""
|
||||
self.default_wallet_name = "default_wallet" if self.options.is_sqlite_only else ""
|
||||
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
|
||||
@ -129,6 +129,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
# skipped. If list is truncated, wallet creation is skipped and keys
|
||||
# are not imported.
|
||||
self.wallet_names = None
|
||||
# By default the wallet is not required. Set to true by skip_if_no_wallet().
|
||||
# When False, we ignore wallet_names regardless of what it is.
|
||||
self.requires_wallet = False
|
||||
self.set_test_params()
|
||||
assert self.wallet_names is None or len(self.wallet_names) <= self.num_nodes
|
||||
if self.options.timeout_factor == 0 :
|
||||
@ -203,12 +206,21 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
parser.add_argument("--randomseed", type=int,
|
||||
help="set a random seed for deterministically reproducing a previous test run")
|
||||
parser.add_argument('--timeout-factor', dest="timeout_factor", type=float, default=1.0, help='adjust test timeouts by a factor. Setting it to 0 disables all timeouts')
|
||||
|
||||
self.add_options(parser)
|
||||
self.options = parser.parse_args()
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read_file(open(self.options.configfile))
|
||||
self.config = config
|
||||
|
||||
# Passthrough SQLite-only availability check output as option
|
||||
self.options.is_sqlite_only = self.is_sqlite_compiled() and not self.is_bdb_compiled()
|
||||
|
||||
# Running TestShell in a Jupyter notebook causes an additional -f argument
|
||||
# To keep TestShell from failing with an "unrecognized argument" error, we add a dummy "-f" argument
|
||||
# source: https://stackoverflow.com/questions/48796169/how-to-fix-ipykernel-launcher-py-error-unrecognized-arguments-in-jupyter/56349168#56349168
|
||||
parser.add_argument("-f", "--fff", help="a dummy argument to fool ipython", default="1")
|
||||
self.options = parser.parse_args()
|
||||
|
||||
def setup(self):
|
||||
"""Call this method to start up the test framework object with options set."""
|
||||
@ -224,9 +236,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
|
||||
self.options.cachedir = os.path.abspath(self.options.cachedir)
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read_file(open(self.options.configfile))
|
||||
self.config = config
|
||||
config = self.config
|
||||
|
||||
self.options.bitcoind = os.getenv("BITCOIND", default=config["environment"]["BUILDDIR"] + '/src/dashd' + config["environment"]["EXEEXT"])
|
||||
self.options.bitcoincli = os.getenv("BITCOINCLI", default=config["environment"]["BUILDDIR"] + '/src/dash-cli' + config["environment"]["EXEEXT"])
|
||||
|
||||
@ -398,7 +409,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():
|
||||
if self.requires_wallet:
|
||||
self.import_deterministic_coinbase_privkeys()
|
||||
if not self.setup_clean_chain:
|
||||
for n in self.nodes:
|
||||
@ -866,9 +877,20 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
|
||||
def skip_if_no_wallet(self):
|
||||
"""Skip the running test if wallet has not been compiled."""
|
||||
self.requires_wallet = True
|
||||
if not self.is_wallet_compiled():
|
||||
raise SkipTest("wallet has not been compiled.")
|
||||
|
||||
def skip_if_no_sqlite(self):
|
||||
"""Skip the running test if sqlite has not been compiled."""
|
||||
if not self.is_sqlite_compiled():
|
||||
raise SkipTest("sqlite has not been compiled.")
|
||||
|
||||
def skip_if_no_bdb(self):
|
||||
"""Skip the running test if BDB has not been compiled."""
|
||||
if not self.is_bdb_compiled():
|
||||
raise SkipTest("BDB has not been compiled.")
|
||||
|
||||
def skip_if_no_wallet_tool(self):
|
||||
"""Skip the running test if dash-wallet has not been compiled."""
|
||||
if not self.is_wallet_tool_compiled():
|
||||
@ -895,6 +917,13 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
"""Checks whether the zmq module was compiled."""
|
||||
return self.config["components"].getboolean("ENABLE_ZMQ")
|
||||
|
||||
def is_sqlite_compiled(self):
|
||||
"""Checks whether the wallet module was compiled with Sqlite support."""
|
||||
return self.config["components"].getboolean("USE_SQLITE")
|
||||
|
||||
def is_bdb_compiled(self):
|
||||
"""Checks whether the wallet module was compiled with BDB support."""
|
||||
return self.config["components"].getboolean("USE_BDB")
|
||||
|
||||
MASTERNODE_COLLATERAL = 1000
|
||||
HIGHPERFORMANCE_MASTERNODE_COLLATERAL = 4000
|
||||
|
@ -70,8 +70,11 @@ class ToolWalletTest(BitcoinTestFramework):
|
||||
self.assert_raises_tool_error('Error: two methods provided (info and create). Only one method should be provided.', 'info', 'create')
|
||||
self.assert_raises_tool_error('Error parsing command line arguments: Invalid parameter -foo', '-foo')
|
||||
locked_dir = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets")
|
||||
error = "SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another dashd?"
|
||||
if self.is_bdb_compiled():
|
||||
error = 'Error initializing wallet database environment "{}"!'.format(locked_dir)
|
||||
self.assert_raises_tool_error(
|
||||
'Error initializing wallet database environment "{}"!'.format(locked_dir),
|
||||
error,
|
||||
'-wallet=' + self.default_wallet_name,
|
||||
'info',
|
||||
)
|
||||
@ -103,7 +106,7 @@ class ToolWalletTest(BitcoinTestFramework):
|
||||
Transactions: 0
|
||||
Address Book: 1
|
||||
''')
|
||||
self.assert_tool_output(out, '-wallet=wallet.dat', 'info')
|
||||
self.assert_tool_output(out, '-wallet=' + self.default_wallet_name, 'info')
|
||||
|
||||
self.start_node(0)
|
||||
self.nodes[0].upgradetohd()
|
||||
@ -233,6 +236,7 @@ class ToolWalletTest(BitcoinTestFramework):
|
||||
self.test_tool_wallet_info_after_transaction()
|
||||
self.test_tool_wallet_create_on_existing_wallet()
|
||||
self.test_getwalletinfo_on_different_wallet()
|
||||
if self.is_bdb_compiled():
|
||||
self.test_salvage()
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -190,6 +190,7 @@ class WalletDumpTest(BitcoinTestFramework):
|
||||
result = self.nodes[0].getaddressinfo(multisig_addr)
|
||||
assert result['ismine'] == True
|
||||
|
||||
if self.is_bdb_compiled():
|
||||
self.log.info('Check that wallet is flushed')
|
||||
with self.nodes[0].assert_debug_log(['Flushing wallet.dat'], timeout=20):
|
||||
self.nodes[0].getnewaddress()
|
||||
|
@ -11,6 +11,9 @@ class WalletRBFTest(BitcoinTestFramework):
|
||||
self.num_nodes = 1
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
self.nodes[0].generate(101)
|
||||
|
||||
|
@ -29,7 +29,7 @@ class WalletHDTest(BitcoinTestFramework):
|
||||
def run_test(self):
|
||||
# Make sure can't switch off usehd after wallet creation
|
||||
self.stop_node(1)
|
||||
self.nodes[1].assert_start_raises_init_error(['-usehd=0'], "Error: Error loading : You can't disable HD on an already existing HD wallet")
|
||||
self.nodes[1].assert_start_raises_init_error(['-usehd=0'], "Error: Error loading %s: You can't disable HD on an already existing HD wallet" % self.default_wallet_name)
|
||||
self.start_node(1)
|
||||
self.connect_nodes(0, 1)
|
||||
|
||||
|
@ -24,6 +24,7 @@ from test_framework.util import (
|
||||
FEATURE_LATEST = 120200
|
||||
|
||||
got_loading_error = False
|
||||
|
||||
def test_load_unload(node, name):
|
||||
global got_loading_error
|
||||
for i in range(10):
|
||||
@ -37,7 +38,6 @@ def test_load_unload(node, name):
|
||||
got_loading_error = True
|
||||
return
|
||||
|
||||
|
||||
class MultiWalletTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.setup_clean_chain = True
|
||||
@ -98,23 +98,32 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
# sub/w5 - to verify relative wallet path is created correctly
|
||||
# extern/w6 - to verify absolute wallet path is created 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. Not tested for SQLite wallets as this is a deprecated BDB behavior.
|
||||
# '' - 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]
|
||||
to_create = ['w1', 'w2', 'w3', 'w', 'sub/w5', 'w7_symlink']
|
||||
in_wallet_dir = to_create.copy() # Wallets in the wallet dir
|
||||
in_wallet_dir.append('w7') # w7 is not loaded or created, but will be listed by listwalletdir because w7_symlink
|
||||
to_create.append(os.path.join(self.options.tmpdir, 'extern/w6')) # External, not in the wallet dir, so we need to avoid adding it to in_wallet_dir
|
||||
to_load = [self.default_wallet_name]
|
||||
if not self.options.is_sqlite_only:
|
||||
to_load.append('w8')
|
||||
wallet_names = to_create + to_load # Wallet names loaded in the wallet
|
||||
in_wallet_dir += to_load # The loaded wallets are also in the wallet dir
|
||||
if os.name == 'nt':
|
||||
wallet_names.remove('w7_symlink')
|
||||
self.start_node(0)
|
||||
|
||||
for wallet_name in wallet_names[:-2]:
|
||||
for wallet_name in to_create:
|
||||
self.nodes[0].createwallet(wallet_name)
|
||||
for wallet_name in wallet_names[-2:]:
|
||||
for wallet_name in to_load:
|
||||
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(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), sorted(in_wallet_dir))
|
||||
|
||||
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")
|
||||
err_code = -4 if self.options.is_sqlite_only else -1
|
||||
assert_raises_rpc_error(err_code, "boost::filesystem::create_directory:", self.nodes[0].createwallet, "w8/bad")
|
||||
|
||||
# check that all requested wallets were created
|
||||
self.stop_node(0)
|
||||
@ -128,8 +137,11 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
self.start_node(0, ['-wallet=w1', '-wallet=w1'])
|
||||
self.stop_node(0, 'Warning: Ignoring duplicate -wallet w1.')
|
||||
|
||||
if not self.options.is_sqlite_only:
|
||||
# Only BDB doesn't open duplicate wallet files. SQLite does not have this limitation. While this may be desired in the future, it is not necessary
|
||||
# should not initialize if one wallet is a copy of another
|
||||
shutil.copyfile(wallet_dir('w8'), wallet_dir('w8_copy'))
|
||||
in_wallet_dir.append('w8_copy')
|
||||
exp_stderr = r"Can't open database w8_copy \(duplicates fileid \w+ from w8\)"
|
||||
self.nodes[0].assert_start_raises_init_error(['-wallet=w8', '-wallet=w8_copy'], exp_stderr, match=ErrorMatch.PARTIAL_REGEX)
|
||||
|
||||
@ -145,10 +157,6 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
open(not_a_dir, 'a', encoding="utf8").close()
|
||||
self.nodes[0].assert_start_raises_init_error(['-walletdir=' + not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory')
|
||||
|
||||
self.log.info("Do not allow -upgradewallet with multiwallet")
|
||||
self.nodes[0].assert_start_raises_init_error(['-upgradewallet', '-wallet=w1', '-wallet=w2'], "Error: -upgradewallet is only allowed with a single wallet file")
|
||||
self.nodes[0].assert_start_raises_init_error(['-upgradewallet=1', '-wallet=w1', '-wallet=w2'], "Error: -upgradewallet is only allowed with a single wallet file")
|
||||
|
||||
# if wallets/ doesn't exist, datadir should be the default wallet dir
|
||||
wallet_dir2 = data_dir('walletdir')
|
||||
os.rename(wallet_dir(), wallet_dir2)
|
||||
@ -173,14 +181,17 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
os.mkdir(competing_wallet_dir)
|
||||
self.restart_node(0, ['-nowallet', '-walletdir=' + competing_wallet_dir])
|
||||
self.nodes[0].createwallet(self.default_wallet_name)
|
||||
exp_stderr = r"Error: Error initializing wallet database environment \"\S+competing_walletdir\"!"
|
||||
if self.options.is_sqlite_only:
|
||||
exp_stderr = r"Error: SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another dashd?"
|
||||
else:
|
||||
exp_stderr = r"Error: Error initializing wallet database environment \"\S+competing_walletdir\S*\"!"
|
||||
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)
|
||||
|
||||
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'])), sorted(in_wallet_dir))
|
||||
|
||||
wallets = [wallet(w) for w in wallet_names]
|
||||
wallet_bad = wallet("bad")
|
||||
@ -271,19 +282,23 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
|
||||
# Fail to load duplicate wallets
|
||||
path = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets", "w1", self.wallet_data_filename)
|
||||
if self.options.is_sqlite_only:
|
||||
assert_raises_rpc_error(-4, "Wallet file verification failed. SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another dashd?", self.nodes[0].loadwallet, wallet_names[0])
|
||||
else:
|
||||
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])
|
||||
|
||||
# This tests the default wallet that BDB makes, so SQLite wallet doesn't need to test this
|
||||
# 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)
|
||||
|
||||
# Only BDB doesn't open duplicate wallet files. SQLite does not have this limitation. While this may be desired in the future, it is not necessary
|
||||
# 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')
|
||||
|
||||
# Fail to load if one wallet is a copy of another, test this twice to make sure that we don't re-introduce #14304
|
||||
assert_raises_rpc_error(-4, "BerkeleyDatabase: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
|
||||
|
||||
|
||||
# Fail to load if wallet file is a symlink
|
||||
if os.name != 'nt':
|
||||
assert_raises_rpc_error(-4, "Wallet file verification failed. Invalid -wallet path 'w8_symlink'", self.nodes[0].loadwallet, 'w8_symlink')
|
||||
@ -296,6 +311,7 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
|
||||
# Successfully create a wallet with a new name
|
||||
loadwallet_name = self.nodes[0].createwallet('w9')
|
||||
in_wallet_dir.append('w9')
|
||||
assert_equal(loadwallet_name['name'], 'w9')
|
||||
w9 = node.get_wallet_rpc('w9')
|
||||
assert_equal(w9.getwalletinfo()['walletname'], 'w9')
|
||||
@ -348,7 +364,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'])), sorted(in_wallet_dir))
|
||||
|
||||
# Test backing up and restoring wallets
|
||||
self.log.info("Test wallet backup")
|
||||
@ -373,22 +389,13 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
self.start_node(1)
|
||||
wallet = os.path.join(self.options.tmpdir, 'my_wallet')
|
||||
self.nodes[0].createwallet(wallet)
|
||||
assert_raises_rpc_error(-4, "Error initializing wallet database environment", self.nodes[1].loadwallet, wallet)
|
||||
if self.options.is_sqlite_only:
|
||||
exp_stderr = "SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another dashd?"
|
||||
else:
|
||||
exp_stderr = "Error initializing wallet database environment"
|
||||
assert_raises_rpc_error(-4, exp_stderr, self.nodes[1].loadwallet, wallet)
|
||||
self.nodes[0].unloadwallet(wallet)
|
||||
self.nodes[1].loadwallet(wallet)
|
||||
|
||||
# Fail to load if wallet is downgraded
|
||||
shutil.copytree(os.path.join(self.options.data_wallets_dir, 'high_minversion'), wallet_dir('high_minversion'))
|
||||
self.restart_node(0, extra_args=['-upgradewallet={}'.format(FEATURE_LATEST)])
|
||||
assert {'name': 'high_minversion'} in self.nodes[0].listwalletdir()['wallets']
|
||||
self.log.info("Fail -upgradewallet that results in downgrade")
|
||||
assert_raises_rpc_error(
|
||||
-4,
|
||||
'Wallet loading failed. Error loading {}: Wallet requires newer version of {}'.format(
|
||||
wallet_dir('high_minversion', 'wallet.dat'), "Dash Core"),
|
||||
lambda: self.nodes[0].loadwallet(filename='high_minversion'),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
MultiWalletTest().main()
|
||||
|
@ -34,7 +34,7 @@ class WalletUpgradeToHDTest(BitcoinTestFramework):
|
||||
self.log.info("Recover non-HD wallet to check different upgrade paths")
|
||||
node = self.nodes[0]
|
||||
self.stop_node(0)
|
||||
shutil.copyfile(os.path.join(node.datadir, "non_hd.bak"), os.path.join(node.datadir, "regtest", "wallet.dat"))
|
||||
shutil.copyfile(os.path.join(node.datadir, "non_hd.bak"), os.path.join(node.datadir, self.chain, self.default_wallet_name, self.wallet_data_filename))
|
||||
self.start_node(0)
|
||||
assert 'hdchainid' not in node.getwalletinfo()
|
||||
|
||||
@ -68,7 +68,7 @@ class WalletUpgradeToHDTest(BitcoinTestFramework):
|
||||
|
||||
self.log.info("Should no longer be able to start it with HD disabled")
|
||||
self.stop_node(0)
|
||||
node.assert_start_raises_init_error(['-usehd=0'], "Error: Error loading : You can't disable HD on an already existing HD wallet")
|
||||
node.assert_start_raises_init_error(['-usehd=0'], "Error: Error loading %s: You can't disable HD on an already existing HD wallet" % self.default_wallet_name)
|
||||
self.start_node(0)
|
||||
balance_after = node.getbalance()
|
||||
|
||||
|
@ -32,6 +32,7 @@ class UpgradeWalletTest(BitcoinTestFramework):
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
self.skip_if_no_bdb()
|
||||
|
||||
def setup_network(self):
|
||||
self.setup_nodes()
|
||||
|
Loading…
Reference in New Issue
Block a user