aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/rpcwallet.cpp7
-rw-r--r--src/wallet/scriptpubkeyman.cpp13
-rw-r--r--src/wallet/scriptpubkeyman.h6
-rw-r--r--src/wallet/test/wallet_tests.cpp4
-rw-r--r--src/wallet/wallet.cpp56
-rw-r--r--src/wallet/wallet.h18
-rw-r--r--src/wallet/walletutil.cpp57
-rw-r--r--src/wallet/walletutil.h3
8 files changed, 85 insertions, 79 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 25c6cf306d..6efa3d0c27 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -8,6 +8,7 @@
#include <interfaces/chain.h>
#include <key_io.h>
#include <node/context.h>
+#include <optional.h>
#include <outputtype.h>
#include <policy/feerate.h>
#include <policy/fees.h>
@@ -3603,7 +3604,7 @@ static RPCHelpMan rescanblockchain()
}
int start_height = 0;
- Optional<int> stop_height;
+ Optional<int> stop_height = MakeOptional(false, int());
uint256 start_block;
{
LOCK(pwallet->cs_wallet);
@@ -4500,10 +4501,8 @@ static RPCHelpMan upgradewallet()
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)) {
+ if (!pwallet->UpgradeWallet(version, error)) {
throw JSONRPCError(RPC_WALLET_ERROR, error.original);
}
UniValue obj(UniValue::VOBJ);
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index 188289b010..d2e1be6402 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -438,12 +438,12 @@ bool LegacyScriptPubKeyMan::CanGetAddresses(bool internal) const
return keypool_has_keys;
}
-bool LegacyScriptPubKeyMan::Upgrade(int prev_version, bilingual_str& error)
+bool LegacyScriptPubKeyMan::Upgrade(int prev_version, int new_version, bilingual_str& error)
{
LOCK(cs_KeyStore);
bool hd_upgrade = false;
bool split_upgrade = false;
- if (m_storage.CanSupportFeature(FEATURE_HD) && !IsHDEnabled()) {
+ if (IsFeatureSupported(new_version, FEATURE_HD) && !IsHDEnabled()) {
WalletLogPrintf("Upgrading wallet to HD\n");
m_storage.SetMinVersion(FEATURE_HD);
@@ -453,10 +453,17 @@ bool LegacyScriptPubKeyMan::Upgrade(int prev_version, bilingual_str& error)
hd_upgrade = true;
}
// Upgrade to HD chain split if necessary
- if (m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) {
+ if (IsFeatureSupported(new_version, FEATURE_HD_SPLIT)) {
WalletLogPrintf("Upgrading wallet to use HD chain split\n");
m_storage.SetMinVersion(FEATURE_PRE_SPLIT_KEYPOOL);
split_upgrade = FEATURE_HD_SPLIT > prev_version;
+ // Upgrade the HDChain
+ if (m_hd_chain.nVersion < CHDChain::VERSION_HD_CHAIN_SPLIT) {
+ m_hd_chain.nVersion = CHDChain::VERSION_HD_CHAIN_SPLIT;
+ if (!WalletBatch(m_storage.GetDatabase()).WriteHDChain(m_hd_chain)) {
+ throw std::runtime_error(std::string(__func__) + ": writing chain failed");
+ }
+ }
}
// Mark all keys currently in the keypool as pre-split
if (split_upgrade) {
diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h
index 63c10b7a0d..3bf8f78120 100644
--- a/src/wallet/scriptpubkeyman.h
+++ b/src/wallet/scriptpubkeyman.h
@@ -37,7 +37,7 @@ public:
virtual bool IsWalletFlagSet(uint64_t) const = 0;
virtual void UnsetBlankWalletFlag(WalletBatch&) = 0;
virtual bool CanSupportFeature(enum WalletFeature) const = 0;
- virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr, bool = false) = 0;
+ virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr) = 0;
virtual const CKeyingMaterial& GetEncryptionKey() const = 0;
virtual bool HasEncryptionKeys() const = 0;
virtual bool IsLocked() const = 0;
@@ -206,7 +206,7 @@ public:
virtual bool CanGetAddresses(bool internal = false) const { return false; }
/** Upgrades the wallet to the specified version */
- virtual bool Upgrade(int prev_version, bilingual_str& error) { return false; }
+ virtual bool Upgrade(int prev_version, int new_version, bilingual_str& error) { return false; }
virtual bool HavePrivateKeys() const { return false; }
@@ -371,7 +371,7 @@ public:
bool SetupGeneration(bool force = false) override;
- bool Upgrade(int prev_version, bilingual_str& error) override;
+ bool Upgrade(int prev_version, int new_version, bilingual_str& error) override;
bool HavePrivateKeys() const override;
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index c42114c394..4911af08c6 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -688,7 +688,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup)
BOOST_CHECK_EXCEPTION(vr >> w_desc, std::ios_base::failure, malformed_descriptor);
}
-//! Test CreateWalletFromFile function and its behavior handling potential race
+//! Test CWallet::Create() and its behavior handling potential race
//! conditions if it's called the same time an incoming transaction shows up in
//! the mempool or a new block.
//!
@@ -706,7 +706,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup)
//! wallet rescan and notifications are immediately synced, to verify the wallet
//! must already have a handler in place for them, and there's no gap after
//! rescanning where new transactions in new blocks could be lost.
-BOOST_FIXTURE_TEST_CASE(CreateWalletFromFile, TestChain100Setup)
+BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
{
// Create new wallet with known key and unload it.
auto chain = interfaces::MakeChain(m_node);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 37f6a4a7dc..ff8bfff872 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -436,21 +436,13 @@ void CWallet::chainStateFlushed(const CBlockLocator& loc)
batch.WriteBestBlock(loc);
}
-void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool fExplicit)
+void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in)
{
LOCK(cs_wallet);
if (nWalletVersion >= nVersion)
return;
-
- // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
- if (fExplicit && nVersion > nWalletMaxVersion)
- nVersion = FEATURE_LATEST;
-
nWalletVersion = nVersion;
- if (nVersion > nWalletMaxVersion)
- nWalletMaxVersion = nVersion;
-
{
WalletBatch* batch = batch_in ? batch_in : new WalletBatch(*database);
if (nWalletVersion > 40000)
@@ -460,18 +452,6 @@ void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in,
}
}
-bool CWallet::SetMaxVersion(int nVersion)
-{
- LOCK(cs_wallet);
- // cannot downgrade below current version
- if (nWalletVersion > nVersion)
- return false;
-
- nWalletMaxVersion = nVersion;
-
- return true;
-}
-
std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
{
std::set<uint256> result;
@@ -656,7 +636,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
}
// Encryption was introduced in version 0.4.0
- SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch, true);
+ SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch);
if (!encrypted_batch->TxnCommit()) {
delete encrypted_batch;
@@ -1778,7 +1758,11 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
double progress_current = progress_begin;
int block_height = start_height;
while (!fAbortRescan && !chain().shutdownRequested()) {
- m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
+ if (progress_end - progress_begin > 0.0) {
+ m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
+ } else { // avoid divide-by-zero for single block scan range (i.e. start and stop hashes are equal)
+ m_scanning_progress = 0;
+ }
if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
ShowProgress(strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
}
@@ -3106,10 +3090,10 @@ bool CWallet::CreateTransactionInternal(
WalletLogPrintf("Fee Calculation: Fee:%d Bytes:%u Needed:%d Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n",
nFeeRet, nBytes, nFeeNeeded, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay,
feeCalc.est.pass.start, feeCalc.est.pass.end,
- 100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool),
+ (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool) > 0.0 ? 100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool) : 0.0,
feeCalc.est.pass.withinTarget, feeCalc.est.pass.totalConfirmed, feeCalc.est.pass.inMempool, feeCalc.est.pass.leftMempool,
feeCalc.est.fail.start, feeCalc.est.fail.end,
- 100 * feeCalc.est.fail.withinTarget / (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool),
+ (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool) > 0.0 ? 100 * feeCalc.est.fail.withinTarget / (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool) : 0.0,
feeCalc.est.fail.withinTarget, feeCalc.est.fail.totalConfirmed, feeCalc.est.fail.inMempool, feeCalc.est.fail.leftMempool);
return true;
}
@@ -4118,36 +4102,34 @@ const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest
return &address_book_it->second;
}
-bool CWallet::UpgradeWallet(int version, bilingual_str& error, std::vector<bilingual_str>& warnings)
+bool CWallet::UpgradeWallet(int version, bilingual_str& error)
{
int prev_version = GetVersion();
- int nMaxVersion = version;
- if (nMaxVersion == 0) // the -upgradewallet without argument case
- {
+ if (version == 0) {
WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
- nMaxVersion = FEATURE_LATEST;
- SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
+ version = FEATURE_LATEST;
} else {
- WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
+ WalletLogPrintf("Allowing wallet upgrade up to %i\n", version);
}
- if (nMaxVersion < GetVersion())
+ if (version < prev_version)
{
error = _("Cannot downgrade wallet");
return false;
}
- SetMaxVersion(nMaxVersion);
LOCK(cs_wallet);
// Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
- int max_version = GetVersion();
- if (!CanSupportFeature(FEATURE_HD_SPLIT) && max_version >= FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) {
+ if (!CanSupportFeature(FEATURE_HD_SPLIT) && version >= FEATURE_HD_SPLIT && version < FEATURE_PRE_SPLIT_KEYPOOL) {
error = _("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.");
return false;
}
+ // Permanently upgrade to the version
+ SetMinVersion(GetClosestWalletFeature(version));
+
for (auto spk_man : GetActiveScriptPubKeyMans()) {
- if (!spk_man->Upgrade(prev_version, error)) {
+ if (!spk_man->Upgrade(prev_version, version, error)) {
return false;
}
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 00e0e3c84d..69cf6b66a4 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -636,9 +636,6 @@ private:
//! the current wallet version: clients below this version are not able to load the wallet
int nWalletVersion GUARDED_BY(cs_wallet){FEATURE_BASE};
- //! the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
- int nWalletMaxVersion GUARDED_BY(cs_wallet) = FEATURE_BASE;
-
int64_t nNextResend = 0;
bool fBroadcastTransactions = false;
// Local time that the tip block was received. Used to schedule wallet rebroadcasts.
@@ -800,8 +797,8 @@ public:
const CWalletTx* GetWalletTx(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool IsTrusted(const CWalletTx& wtx, std::set<uint256>& trusted_parents) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- //! check whether we are allowed to upgrade (or already support) to the named feature
- bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
+ //! check whether we support the named feature
+ bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return IsFeatureSupported(nWalletVersion, wf); }
/**
* populate vCoins with vector of available COutputs.
@@ -853,7 +850,7 @@ public:
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
+ bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; return true; }
/**
* Adds a destination data tuple to the store, and saves it to disk
@@ -1076,11 +1073,8 @@ public:
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- //! signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
- void SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr, bool fExplicit = false) override;
-
- //! change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
- bool SetMaxVersion(int nVersion);
+ //! signify that a particular wallet feature is now used.
+ void SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr) override;
//! get the current wallet format (the oldest client version guaranteed to understand this wallet)
int GetVersion() const { LOCK(cs_wallet); return nWalletVersion; }
@@ -1201,7 +1195,7 @@ public:
};
/** Upgrade the wallet */
- bool UpgradeWallet(int version, bilingual_str& error, std::vector<bilingual_str>& warnings);
+ bool UpgradeWallet(int version, bilingual_str& error);
//! Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers
std::set<ScriptPubKeyMan*> GetActiveScriptPubKeyMans() const;
diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp
index 2f3e597b90..702293e6c7 100644
--- a/src/wallet/walletutil.cpp
+++ b/src/wallet/walletutil.cpp
@@ -49,28 +49,51 @@ std::vector<fs::path> ListWalletDir()
continue;
}
- // Get wallet path relative to walletdir by removing walletdir from the wallet path.
- // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
- const fs::path path = it->path().string().substr(offset);
+ try {
+ // Get wallet path relative to walletdir by removing walletdir from the wallet path.
+ // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
+ const fs::path path = it->path().string().substr(offset);
- if (it->status().type() == fs::directory_file &&
- (ExistsBerkeleyDatabase(it->path()) || ExistsSQLiteDatabase(it->path()))) {
- // Found a directory which contains wallet.dat btree file, add it as a wallet.
- paths.emplace_back(path);
- } else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && ExistsBerkeleyDatabase(it->path())) {
- if (it->path().filename() == "wallet.dat") {
- // Found top-level wallet.dat btree file, add top level directory ""
- // as a wallet.
- paths.emplace_back();
- } else {
- // Found top-level btree file not called wallet.dat. Current bitcoin
- // software will never create these files but will allow them to be
- // opened in a shared database environment for backwards compatibility.
- // Add it to the list of available wallets.
+ if (it->status().type() == fs::directory_file &&
+ (ExistsBerkeleyDatabase(it->path()) || ExistsSQLiteDatabase(it->path()))) {
+ // Found a directory which contains wallet.dat btree file, add it as a wallet.
paths.emplace_back(path);
+ } else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && ExistsBerkeleyDatabase(it->path())) {
+ if (it->path().filename() == "wallet.dat") {
+ // Found top-level wallet.dat btree file, add top level directory ""
+ // as a wallet.
+ paths.emplace_back();
+ } else {
+ // Found top-level btree file not called wallet.dat. Current bitcoin
+ // software will never create these files but will allow them to be
+ // opened in a shared database environment for backwards compatibility.
+ // Add it to the list of available wallets.
+ paths.emplace_back(path);
+ }
}
+ } catch (const std::exception& e) {
+ LogPrintf("%s: Error scanning %s: %s\n", __func__, it->path().string(), e.what());
+ it.no_push();
}
}
return paths;
}
+
+bool IsFeatureSupported(int wallet_version, int feature_version)
+{
+ return wallet_version >= feature_version;
+}
+
+WalletFeature GetClosestWalletFeature(int version)
+{
+ if (version >= FEATURE_LATEST) return FEATURE_LATEST;
+ if (version >= FEATURE_PRE_SPLIT_KEYPOOL) return FEATURE_PRE_SPLIT_KEYPOOL;
+ if (version >= FEATURE_NO_DEFAULT_KEY) return FEATURE_NO_DEFAULT_KEY;
+ if (version >= FEATURE_HD_SPLIT) return FEATURE_HD_SPLIT;
+ if (version >= FEATURE_HD) return FEATURE_HD;
+ if (version >= FEATURE_COMPRPUBKEY) return FEATURE_COMPRPUBKEY;
+ if (version >= FEATURE_WALLETCRYPT) return FEATURE_WALLETCRYPT;
+ if (version >= FEATURE_BASE) return FEATURE_BASE;
+ return static_cast<WalletFeature>(0);
+}
diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h
index afdcb2e18a..27521abd81 100644
--- a/src/wallet/walletutil.h
+++ b/src/wallet/walletutil.h
@@ -29,7 +29,8 @@ enum WalletFeature
FEATURE_LATEST = FEATURE_PRE_SPLIT_KEYPOOL
};
-
+bool IsFeatureSupported(int wallet_version, int feature_version);
+WalletFeature GetClosestWalletFeature(int version);
enum WalletFlags : uint64_t {
// wallet flags in the upper section (> 1 << 31) will lead to not opening the wallet if flag is unknown