aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/walletdb.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/walletdb.cpp')
-rw-r--r--src/wallet/walletdb.cpp145
1 files changed, 28 insertions, 117 deletions
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index f3dd5b328e..3ba43cdb73 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -3,6 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <config/bitcoin-config.h> // IWYU pragma: keep
+
#include <wallet/walletdb.h>
#include <common/system.h>
@@ -804,10 +806,10 @@ static DBErrors LoadDescriptorWalletRecords(CWallet* pwallet, DatabaseBatch& bat
strErr = strprintf("%s\nDetails: %s", strErr, e.what());
return DBErrors::UNKNOWN_DESCRIPTOR;
}
- pwallet->LoadDescriptorScriptPubKeyMan(id, desc);
+ DescriptorScriptPubKeyMan& spkm = pwallet->LoadDescriptorScriptPubKeyMan(id, desc);
// Prior to doing anything with this spkm, verify ID compatibility
- if (id != pwallet->GetDescriptorScriptPubKeyMan(desc)->GetID()) {
+ if (id != spkm.GetID()) {
strErr = "The descriptor ID calculated by the wallet differs from the one in DB";
return DBErrors::CORRUPT;
}
@@ -1230,88 +1232,33 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
return result;
}
-DBErrors WalletBatch::FindWalletTxHashes(std::vector<uint256>& tx_hashes)
+static bool RunWithinTxn(WalletBatch& batch, std::string_view process_desc, const std::function<bool(WalletBatch&)>& func)
{
- DBErrors result = DBErrors::LOAD_OK;
-
- try {
- int nMinVersion = 0;
- if (m_batch->Read(DBKeys::MINVERSION, nMinVersion)) {
- if (nMinVersion > FEATURE_LATEST)
- return DBErrors::TOO_NEW;
- }
-
- // Get cursor
- std::unique_ptr<DatabaseCursor> cursor = m_batch->GetNewCursor();
- if (!cursor)
- {
- LogPrintf("Error getting wallet database cursor\n");
- return DBErrors::CORRUPT;
- }
+ if (!batch.TxnBegin()) {
+ LogPrint(BCLog::WALLETDB, "Error: cannot create db txn for %s\n", process_desc);
+ return false;
+ }
- while (true)
- {
- // Read next record
- DataStream ssKey{};
- DataStream ssValue{};
- DatabaseCursor::Status status = cursor->Next(ssKey, ssValue);
- if (status == DatabaseCursor::Status::DONE) {
- break;
- } else if (status == DatabaseCursor::Status::FAIL) {
- LogPrintf("Error reading next record from wallet database\n");
- return DBErrors::CORRUPT;
- }
+ // Run procedure
+ if (!func(batch)) {
+ LogPrint(BCLog::WALLETDB, "Error: %s failed\n", process_desc);
+ batch.TxnAbort();
+ return false;
+ }
- std::string strType;
- ssKey >> strType;
- if (strType == DBKeys::TX) {
- uint256 hash;
- ssKey >> hash;
- tx_hashes.push_back(hash);
- }
- }
- } catch (...) {
- result = DBErrors::CORRUPT;
+ if (!batch.TxnCommit()) {
+ LogPrint(BCLog::WALLETDB, "Error: cannot commit db txn for %s\n", process_desc);
+ return false;
}
- return result;
+ // All good
+ return true;
}
-DBErrors WalletBatch::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<uint256>& vTxHashOut)
+bool RunWithinTxn(WalletDatabase& database, std::string_view process_desc, const std::function<bool(WalletBatch&)>& func)
{
- // build list of wallet TX hashes
- std::vector<uint256> vTxHash;
- DBErrors err = FindWalletTxHashes(vTxHash);
- if (err != DBErrors::LOAD_OK) {
- return err;
- }
-
- std::sort(vTxHash.begin(), vTxHash.end());
- std::sort(vTxHashIn.begin(), vTxHashIn.end());
-
- // erase each matching wallet TX
- bool delerror = false;
- std::vector<uint256>::iterator it = vTxHashIn.begin();
- for (const uint256& hash : vTxHash) {
- while (it < vTxHashIn.end() && (*it) < hash) {
- it++;
- }
- if (it == vTxHashIn.end()) {
- break;
- }
- else if ((*it) == hash) {
- if(!EraseTx(hash)) {
- LogPrint(BCLog::WALLETDB, "Transaction was found for deletion but returned database error: %s\n", hash.GetHex());
- delerror = true;
- }
- vTxHashOut.push_back(hash);
- }
- }
-
- if (delerror) {
- return DBErrors::CORRUPT;
- }
- return DBErrors::LOAD_OK;
+ WalletBatch batch(database);
+ return RunWithinTxn(batch, process_desc, func);
}
void MaybeCompactWalletDB(WalletContext& context)
@@ -1376,47 +1323,11 @@ bool WalletBatch::WriteWalletFlags(const uint64_t flags)
bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
{
- // Begin db txn
- if (!m_batch->TxnBegin()) return false;
-
- // Get cursor
- std::unique_ptr<DatabaseCursor> cursor = m_batch->GetNewCursor();
- if (!cursor)
- {
- return false;
- }
-
- // Iterate the DB and look for any records that have the type prefixes
- while (true) {
- // Read next record
- DataStream key{};
- DataStream value{};
- DatabaseCursor::Status status = cursor->Next(key, value);
- if (status == DatabaseCursor::Status::DONE) {
- break;
- } else if (status == DatabaseCursor::Status::FAIL) {
- cursor.reset(nullptr);
- m_batch->TxnAbort(); // abort db txn
- return false;
- }
-
- // Make a copy of key to avoid data being deleted by the following read of the type
- const SerializeData key_data{key.begin(), key.end()};
-
- std::string type;
- key >> type;
-
- if (types.count(type) > 0) {
- if (!m_batch->Erase(Span{key_data})) {
- cursor.reset(nullptr);
- m_batch->TxnAbort();
- return false; // erase failed
- }
- }
- }
- // Finish db txn
- cursor.reset(nullptr);
- return m_batch->TxnCommit();
+ return RunWithinTxn(*this, "erase records", [&types](WalletBatch& self) {
+ return std::all_of(types.begin(), types.end(), [&self](const std::string& type) {
+ return self.m_batch->ErasePrefix(DataStream() << type);
+ });
+ });
}
bool WalletBatch::TxnBegin()