mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 06:49:38 -04:00
wallet: Disallow loading legacy wallets
Legacy wallets do not have the descriptors flag set. Don't load wallets without the descriptors flag. At the same time, we will no longer load BDB databases since they are only used for legacy wallets.
This commit is contained in:
parent
9f04e02ffa
commit
17bb63f9f9
7 changed files with 42 additions and 30 deletions
|
@ -182,7 +182,6 @@ public:
|
|||
};
|
||||
|
||||
enum class DatabaseFormat {
|
||||
BERKELEY,
|
||||
SQLITE,
|
||||
BERKELEY_RO,
|
||||
BERKELEY_SWAP,
|
||||
|
|
|
@ -98,11 +98,6 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const
|
|||
|
||||
bool WalletInit::ParameterInteraction() const
|
||||
{
|
||||
#ifdef USE_BDB
|
||||
if (!BerkeleyDatabaseSanityCheck()) {
|
||||
return InitError(Untranslated("A version conflict was detected between the run-time BerkeleyDB library and the one used during compilation."));
|
||||
}
|
||||
#endif
|
||||
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
|
||||
for (const std::string& wallet : gArgs.GetArgs("-wallet")) {
|
||||
LogPrintf("%s: parameter interaction: -disablewallet -> ignoring -wallet=%s\n", __func__, wallet);
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
#ifndef BITCOIN_WALLET_TEST_UTIL_H
|
||||
#define BITCOIN_WALLET_TEST_UTIL_H
|
||||
|
||||
#include <bitcoin-build-config.h> // IWYU pragma: keep
|
||||
|
||||
#include <addresstype.h>
|
||||
#include <wallet/db.h>
|
||||
#include <wallet/scriptpubkeyman.h>
|
||||
|
@ -28,9 +26,6 @@ struct WalletContext;
|
|||
|
||||
static const DatabaseFormat DATABASE_FORMATS[] = {
|
||||
DatabaseFormat::SQLITE,
|
||||
#ifdef USE_BDB
|
||||
DatabaseFormat::BERKELEY,
|
||||
#endif
|
||||
};
|
||||
|
||||
const std::string ADDRESS_BCRT1_UNSPENDABLE = "bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj";
|
||||
|
|
|
@ -3052,6 +3052,9 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
|
|||
error = strprintf(_("Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n"
|
||||
"The wallet might have been tampered with or created with malicious intent.\n"), walletFile);
|
||||
return nullptr;
|
||||
} else if (nLoadWalletRet == DBErrors::LEGACY_WALLET) {
|
||||
error = strprintf(_("Error loading %s: Wallet is a legacy wallet. Please migrate to a descriptor wallet using the migration tool (migratewallet RPC)."), walletFile);
|
||||
return nullptr;
|
||||
} else {
|
||||
error = strprintf(_("Error loading %s"), walletFile);
|
||||
return nullptr;
|
||||
|
|
|
@ -485,6 +485,11 @@ static DBErrors LoadWalletFlags(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIV
|
|||
pwallet->WalletLogPrintf("Error reading wallet database: Unknown non-tolerable wallet flags found\n");
|
||||
return DBErrors::TOO_NEW;
|
||||
}
|
||||
// All wallets must be descriptor wallets unless opened with a bdb_ro db
|
||||
// bdb_ro is only used for legacy to descriptor migration.
|
||||
if (pwallet->GetDatabase().Format() != "bdb_ro" && !pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
|
||||
return DBErrors::LEGACY_WALLET;
|
||||
}
|
||||
}
|
||||
return DBErrors::LOAD_OK;
|
||||
}
|
||||
|
@ -1432,7 +1437,7 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
|
|||
std::optional<DatabaseFormat> format;
|
||||
if (exists) {
|
||||
if (IsBDBFile(BDBDataFile(path))) {
|
||||
format = DatabaseFormat::BERKELEY;
|
||||
format = DatabaseFormat::BERKELEY_RO;
|
||||
}
|
||||
if (IsSQLiteFile(SQLiteDataFile(path))) {
|
||||
if (format) {
|
||||
|
@ -1460,9 +1465,11 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// If BERKELEY was the format, then change the format from BERKELEY to BERKELEY_RO
|
||||
if (format && options.require_format && format == DatabaseFormat::BERKELEY && options.require_format == DatabaseFormat::BERKELEY_RO) {
|
||||
format = DatabaseFormat::BERKELEY_RO;
|
||||
// BERKELEY_RO can only be opened if require_format was set, which only occurs in migration.
|
||||
if (format && format == DatabaseFormat::BERKELEY_RO && (!options.require_format || options.require_format != DatabaseFormat::BERKELEY_RO)) {
|
||||
error = Untranslated(strprintf("Failed to open database path '%s'. The wallet appears to be a Legacy wallet, please use the wallet migration tool (migratewallet RPC).", fs::PathToString(path)));
|
||||
status = DatabaseStatus::FAILED_BAD_FORMAT;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// A db already exists so format is set, but options also specifies the format, so make sure they agree
|
||||
|
@ -1475,12 +1482,8 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
|
|||
// Format is not set when a db doesn't already exist, so use the format specified by the options if it is set.
|
||||
if (!format && options.require_format) format = options.require_format;
|
||||
|
||||
// If the format is not specified or detected, choose the default format based on what is available. We prefer BDB over SQLite for now.
|
||||
if (!format) {
|
||||
format = DatabaseFormat::SQLITE;
|
||||
#ifdef USE_BDB
|
||||
format = DatabaseFormat::BERKELEY;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (format == DatabaseFormat::SQLITE) {
|
||||
|
@ -1491,15 +1494,8 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
|
|||
return MakeBerkeleyRODatabase(path, options, status, error);
|
||||
}
|
||||
|
||||
#ifdef USE_BDB
|
||||
if constexpr (true) {
|
||||
return MakeBerkeleyDatabase(path, options, status, error);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support Berkeley DB database format.", fs::PathToString(path)));
|
||||
error = Untranslated(STR_INTERNAL_BUG("Could not determine wallet format"));
|
||||
status = DatabaseStatus::FAILED_BAD_FORMAT;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
} // namespace wallet
|
||||
|
|
|
@ -55,7 +55,8 @@ enum class DBErrors : int
|
|||
UNKNOWN_DESCRIPTOR = 6,
|
||||
LOAD_FAIL = 7,
|
||||
UNEXPECTED_LEGACY_ENTRY = 8,
|
||||
CORRUPT = 9,
|
||||
LEGACY_WALLET = 9,
|
||||
CORRUPT = 10,
|
||||
};
|
||||
|
||||
namespace DBKeys {
|
||||
|
|
|
@ -285,5 +285,28 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
|
|||
info = wallet_res.getaddressinfo(address)
|
||||
assert_equal(info, addr_info)
|
||||
|
||||
self.log.info("Test that a wallet from a legacy only node must be migrated, from:")
|
||||
for node in legacy_nodes:
|
||||
self.log.info(f"- {node.version}")
|
||||
wallet_name = f"legacy_up_{node.version}"
|
||||
if self.major_version_at_least(node, 21):
|
||||
node.rpc.createwallet(wallet_name=wallet_name, descriptors=False)
|
||||
else:
|
||||
node.rpc.createwallet(wallet_name=wallet_name)
|
||||
wallet_prev = node.get_wallet_rpc(wallet_name)
|
||||
address = wallet_prev.getnewaddress('', "bech32")
|
||||
addr_info = wallet_prev.getaddressinfo(address)
|
||||
|
||||
# Make a backup of the wallet file
|
||||
backup_path = os.path.join(self.options.tmpdir, f"{wallet_name}.dat")
|
||||
wallet_prev.backupwallet(backup_path)
|
||||
|
||||
# Remove the wallet from old node
|
||||
wallet_prev.unloadwallet()
|
||||
|
||||
# Restore the wallet to master
|
||||
# Legacy wallets are no longer supported. Trying to load these should result in an error
|
||||
assert_raises_rpc_error(-18, "The wallet appears to be a Legacy wallet, please use the wallet migration tool (migratewallet RPC)", node_master.restorewallet, wallet_name, backup_path)
|
||||
|
||||
if __name__ == '__main__':
|
||||
BackwardsCompatibilityTest(__file__).main()
|
||||
|
|
Loading…
Add table
Reference in a new issue