diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp --- a/src/bench/coin_selection.cpp +++ b/src/bench/coin_selection.cpp @@ -36,7 +36,7 @@ // (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484) static void CoinSelection(benchmark::State &state) { SelectParams(CBaseChainParams::REGTEST); - const CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); + const CWallet wallet(Params(), "dummy", WalletDatabase::CreateDummy()); LOCK(wallet.cs_wallet); // Add coins. @@ -96,7 +96,7 @@ static void BnBExhaustion(benchmark::State &state) { SelectParams(CBaseChainParams::REGTEST); - const CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); + const CWallet wallet(Params(), "dummy", WalletDatabase::CreateDummy()); LOCK(wallet.cs_wallet); // Setup diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -123,7 +123,7 @@ test.CreateAndProcessBlock( {}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey())); } - CWallet wallet(Params(), "mock", CWalletDBWrapper::CreateMock()); + CWallet wallet(Params(), "mock", WalletDatabase::CreateMock()); bool firstRun; wallet.LoadWallet(firstRun); { diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -64,7 +64,7 @@ BOOST_CHECK(result.size() == 4 && result[0] == 0x12 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78); - // Leading space must be supported (used in CDBEnv::Salvage) + // Leading space must be supported (used in BerkeleyEnvironment::Salvage) result = ParseHex(" 89 34 56 78"); BOOST_CHECK(result.size() == 4 && result[0] == 0x89 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78); diff --git a/src/wallet/db.h b/src/wallet/db.h --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -24,7 +24,7 @@ static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100; static const bool DEFAULT_WALLET_PRIVDB = true; -class CDBEnv { +class BerkeleyEnvironment { private: bool fDbEnvInit; bool fMockDb; @@ -38,8 +38,8 @@ std::map mapFileUseCount; std::map mapDb; - CDBEnv(const fs::path &env_directory); - ~CDBEnv(); + BerkeleyEnvironment(const fs::path &env_directory); + ~BerkeleyEnvironment(); void Reset(); void MakeMock(); @@ -87,25 +87,25 @@ } }; -/** Get CDBEnv and database filename given a wallet path. */ -CDBEnv *GetWalletEnv(const fs::path &wallet_path, - std::string &database_filename); +/** Get BerkeleyEnvironment and database filename given a wallet path. */ +BerkeleyEnvironment *GetWalletEnv(const fs::path &wallet_path, + std::string &database_filename); /** * An instance of this class represents one database. * For BerkeleyDB this is just a (env, strFile) tuple. */ -class CWalletDBWrapper { - friend class CDB; +class BerkeleyDatabase { + friend class BerkeleyBatch; public: /** Create dummy DB handle */ - CWalletDBWrapper() + BerkeleyDatabase() : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(nullptr) {} /** Create DB handle to real database */ - CWalletDBWrapper(const fs::path &wallet_path, bool mock = false) + BerkeleyDatabase(const fs::path &wallet_path, bool mock = false) : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0) { env = GetWalletEnv(wallet_path, strFile); @@ -117,23 +117,23 @@ } /** Return object for accessing database at specified path. */ - static std::unique_ptr Create(const fs::path &path) { - return std::make_unique(path); + static std::unique_ptr Create(const fs::path &path) { + return std::make_unique(path); } /** * Return object for accessing dummy database with no read/write * capabilities. */ - static std::unique_ptr CreateDummy() { - return std::make_unique(); + static std::unique_ptr CreateDummy() { + return std::make_unique(); } /** * Return object for accessing temporary in-memory database. */ - static std::unique_ptr CreateMock() { - return std::make_unique("", true /* mock */); + static std::unique_ptr CreateMock() { + return std::make_unique("", true /* mock */); } /** @@ -161,7 +161,7 @@ private: /** BerkeleyDB specific */ - CDBEnv *env; + BerkeleyEnvironment *env; std::string strFile; /** @@ -173,22 +173,23 @@ }; /** RAII class that provides access to a Berkeley database */ -class CDB { +class BerkeleyBatch { protected: Db *pdb; std::string strFile; DbTxn *activeTxn; bool fReadOnly; bool fFlushOnClose; - CDBEnv *env; + BerkeleyEnvironment *env; public: - explicit CDB(CWalletDBWrapper &dbw, const char *pszMode = "r+", - bool fFlushOnCloseIn = true); - ~CDB() { Close(); } + explicit BerkeleyBatch(BerkeleyDatabase &database, + const char *pszMode = "r+", + bool fFlushOnCloseIn = true); + ~BerkeleyBatch() { Close(); } - CDB(const CDB &) = delete; - CDB &operator=(const CDB &) = delete; + BerkeleyBatch(const BerkeleyBatch &) = delete; + BerkeleyBatch &operator=(const BerkeleyBatch &) = delete; void Flush(); void Close(); @@ -200,15 +201,15 @@ /* flush the wallet passively (TRY_LOCK) ideal to be called periodically */ - static bool PeriodicFlush(CWalletDBWrapper &dbw); + static bool PeriodicFlush(BerkeleyDatabase &database); /* verifies the database environment */ static bool VerifyEnvironment(const fs::path &file_path, std::string &errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const fs::path &file_path, - std::string &warningStr, - std::string &errorStr, - CDBEnv::recoverFunc_type recoverFunc); + static bool + VerifyDatabaseFile(const fs::path &file_path, std::string &warningStr, + std::string &errorStr, + BerkeleyEnvironment::recoverFunc_type recoverFunc); public: template bool Read(const K &key, T &value) { @@ -409,7 +410,8 @@ return Write(std::string("version"), nVersion); } - static bool Rewrite(CWalletDBWrapper &dbw, const char *pszSkip = nullptr); + static bool Rewrite(BerkeleyDatabase &database, + const char *pszSkip = nullptr); }; #endif // BITCOIN_WALLET_DB_H diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -30,7 +30,8 @@ //! (https://docs.oracle.com/cd/E17275_01/html/programmer_reference/program_copy.html), //! so bitcoin should never create different databases with the same fileid, but //! this error can be triggered if users manually copy database files. -void CheckUniqueFileid(const CDBEnv &env, const std::string &filename, Db &db) { +void CheckUniqueFileid(const BerkeleyEnvironment &env, + const std::string &filename, Db &db) { if (env.IsMock()) { return; } @@ -38,9 +39,9 @@ u_int8_t fileid[DB_FILE_ID_LEN]; int ret = db.get_mpf()->get_fileid(fileid); if (ret != 0) { - throw std::runtime_error( - strprintf("CDB: Can't open database %s (get_fileid failed with %d)", - filename, ret)); + throw std::runtime_error(strprintf( + "BerkeleyBatch: Can't open database %s (get_fileid failed with %d)", + filename, ret)); } for (const auto &item : env.mapDb) { @@ -51,7 +52,8 @@ const char *item_filename = nullptr; item.second->get_dbname(&item_filename, nullptr); throw std::runtime_error(strprintf( - "CDB: Can't open database %s (duplicates fileid %s from %s)", + "BerkeleyBatch: Can't open database %s (duplicates fileid %s " + "from %s)", filename, HexStr(std::begin(item_fileid), std::end(item_fileid)), item_filename ? item_filename : "(unknown database)")); @@ -60,12 +62,13 @@ } CCriticalSection cs_db; + //!< Map from directory name to open db environment. -std::map g_dbenvs; +std::map g_dbenvs; } // namespace -CDBEnv *GetWalletEnv(const fs::path &wallet_path, - std::string &database_filename) { +BerkeleyEnvironment *GetWalletEnv(const fs::path &wallet_path, + std::string &database_filename) { fs::path env_directory; if (fs::is_regular_file(wallet_path)) { // Special case for backwards compatibility: if wallet path points to an @@ -80,10 +83,10 @@ database_filename = "wallet.dat"; } LOCK(cs_db); - // Note: An ununsed temporary CDBEnv object may be created inside the - // emplace function if the key already exists. This is a little inefficient, - // but not a big concern since the map will be changed in the future to hold - // pointers instead of objects, anyway. + // Note: An ununsed temporary BerkeleyEnvironment object may be created + // inside the emplace function if the key already exists. This is a little + // inefficient, but not a big concern since the map will be changed in the + // future to hold pointers instead of objects, anyway. return &g_dbenvs .emplace(std::piecewise_construct, std::forward_as_tuple(env_directory.string()), @@ -92,10 +95,10 @@ } // -// CDB +// BerkeleyBatch // -void CDBEnv::Close() { +void BerkeleyEnvironment::Close() { if (!fDbEnvInit) { return; } @@ -114,31 +117,31 @@ int ret = dbenv->close(0); if (ret != 0) { - LogPrintf("CDBEnv::EnvShutdown: Error %d shutting down database " - "environment: %s\n", + LogPrintf("BerkeleyEnvironment::EnvShutdown: Error %d shutting down " + "database environment: %s\n", ret, DbEnv::strerror(ret)); } - if (!fMockDb) { - DbEnv(uint32_t(0)).remove(strPath.c_str(), 0); + DbEnv(u_int32_t(0)).remove(strPath.c_str(), 0); } } -void CDBEnv::Reset() { +void BerkeleyEnvironment::Reset() { dbenv.reset(new DbEnv(DB_CXX_NO_EXCEPTIONS)); fDbEnvInit = false; fMockDb = false; } -CDBEnv::CDBEnv(const fs::path &dir_path) : strPath(dir_path.string()) { +BerkeleyEnvironment::BerkeleyEnvironment(const fs::path &dir_path) + : strPath(dir_path.string()) { Reset(); } -CDBEnv::~CDBEnv() { +BerkeleyEnvironment::~BerkeleyEnvironment() { Close(); } -bool CDBEnv::Open(bool retry) { +bool BerkeleyEnvironment::Open(bool retry) { if (fDbEnvInit) { return true; } @@ -157,8 +160,8 @@ fs::path pathLogDir = pathIn / "database"; TryCreateDirectories(pathLogDir); fs::path pathErrorFile = pathIn / "db.log"; - LogPrintf("CDBEnv::Open: LogDir=%s ErrorFile=%s\n", pathLogDir.string(), - pathErrorFile.string()); + LogPrintf("BerkeleyEnvironment::Open: LogDir=%s ErrorFile=%s\n", + pathLogDir.string(), pathErrorFile.string()); unsigned int nEnvFlags = 0; if (gArgs.GetBoolArg("-privdb", DEFAULT_WALLET_PRIVDB)) { @@ -184,7 +187,8 @@ S_IRUSR | S_IWUSR); if (ret != 0) { dbenv->close(0); - LogPrintf("CDBEnv::Open: Error %d opening database environment: %s\n", + LogPrintf("BerkeleyEnvironment::Open: Error %d opening database " + "environment: %s\n", ret, DbEnv::strerror(ret)); if (retry) { // try moving the database env out of the way @@ -214,14 +218,15 @@ return true; } -void CDBEnv::MakeMock() { +void BerkeleyEnvironment::MakeMock() { if (fDbEnvInit) { - throw std::runtime_error("CDBEnv::MakeMock: Already initialized"); + throw std::runtime_error( + "BerkeleyEnvironment::MakeMock: Already initialized"); } boost::this_thread::interruption_point(); - LogPrint(BCLog::DB, "CDBEnv::MakeMock\n"); + LogPrint(BCLog::DB, "BerkeleyEnvironment::MakeMock\n"); dbenv->set_cachesize(1, 0, 1); dbenv->set_lg_bsize(10485760 * 4); @@ -236,17 +241,20 @@ DB_INIT_TXN | DB_THREAD | DB_PRIVATE, S_IRUSR | S_IWUSR); if (ret > 0) { - throw std::runtime_error(strprintf( - "CDBEnv::MakeMock: Error %d opening database environment.", ret)); + throw std::runtime_error( + strprintf("BerkeleyEnvironment::MakeMock: Error %d opening " + "database environment.", + ret)); } fDbEnvInit = true; fMockDb = true; } -CDBEnv::VerifyResult CDBEnv::Verify(const std::string &strFile, - recoverFunc_type recoverFunc, - std::string &out_backup_filename) { +BerkeleyEnvironment::VerifyResult +BerkeleyEnvironment::Verify(const std::string &strFile, + recoverFunc_type recoverFunc, + std::string &out_backup_filename) { LOCK(cs_db); assert(mapFileUseCount.count(strFile) == 0); @@ -264,13 +272,13 @@ return (fRecovered ? VerifyResult::RECOVER_OK : VerifyResult::RECOVER_FAIL); } -bool CDB::Recover(const fs::path &file_path, void *callbackDataIn, - bool (*recoverKVcallback)(void *callbackData, - CDataStream ssKey, - CDataStream ssValue), - std::string &newFilename) { +bool BerkeleyBatch::Recover(const fs::path &file_path, void *callbackDataIn, + bool (*recoverKVcallback)(void *callbackData, + CDataStream ssKey, + CDataStream ssValue), + std::string &newFilename) { std::string filename; - CDBEnv *env = GetWalletEnv(file_path, filename); + BerkeleyEnvironment *env = GetWalletEnv(file_path, filename); // Recovery procedure: // Move wallet file to walletfilename.timestamp.bak @@ -289,7 +297,7 @@ return false; } - std::vector salvagedData; + std::vector salvagedData; bool fSuccess = env->Salvage(newFilename, true, salvagedData); if (salvagedData.empty()) { LogPrintf("Salvage(aggressive) found no records in %s.\n", newFilename); @@ -311,7 +319,7 @@ } DbTxn *ptxn = env->TxnBegin(); - for (CDBEnv::KeyValPair &row : salvagedData) { + for (BerkeleyEnvironment::KeyValPair &row : salvagedData) { if (recoverKVcallback) { CDataStream ssKey(row.first, SER_DISK, CLIENT_VERSION); CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION); @@ -332,9 +340,10 @@ return fSuccess; } -bool CDB::VerifyEnvironment(const fs::path &file_path, std::string &errorStr) { +bool BerkeleyBatch::VerifyEnvironment(const fs::path &file_path, + std::string &errorStr) { std::string walletFile; - CDBEnv *env = GetWalletEnv(file_path, walletFile); + BerkeleyEnvironment *env = GetWalletEnv(file_path, walletFile); fs::path walletDir = env->Directory(); LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); @@ -356,26 +365,25 @@ return true; } -bool CDB::VerifyDatabaseFile(const fs::path &file_path, std::string &warningStr, - std::string &errorStr, - CDBEnv::recoverFunc_type recoverFunc) { +bool BerkeleyBatch::VerifyDatabaseFile( + const fs::path &file_path, std::string &warningStr, std::string &errorStr, + BerkeleyEnvironment::recoverFunc_type recoverFunc) { std::string walletFile; - CDBEnv *env = GetWalletEnv(file_path, walletFile); + BerkeleyEnvironment *env = GetWalletEnv(file_path, walletFile); fs::path walletDir = env->Directory(); if (fs::exists(walletDir / walletFile)) { std::string backup_filename; - CDBEnv::VerifyResult r = + BerkeleyEnvironment::VerifyResult r = env->Verify(walletFile, recoverFunc, backup_filename); - if (r == CDBEnv::VerifyResult::RECOVER_OK) { + if (r == BerkeleyEnvironment::VerifyResult::RECOVER_OK) { warningStr = strprintf( - _("Warning: Wallet file corrupt, data salvaged!" - " Original %s saved as %s in %s; if" - " your balance or transactions are incorrect you should" - " restore from a backup."), + _("Warning: Wallet file corrupt, data salvaged! Original %s " + "saved as %s in %s; if your balance or transactions are " + "incorrect you should restore from a backup."), walletFile, backup_filename, walletDir); } - if (r == CDBEnv::VerifyResult::RECOVER_FAIL) { + if (r == BerkeleyEnvironment::VerifyResult::RECOVER_FAIL) { errorStr = strprintf(_("%s corrupt, salvage failed"), walletFile); return false; } @@ -389,8 +397,9 @@ /* End of key/value data */ static const char *DATA_END = "DATA=END"; -bool CDBEnv::Salvage(const std::string &strFile, bool fAggressive, - std::vector &vResult) { +bool BerkeleyEnvironment::Salvage( + const std::string &strFile, bool fAggressive, + std::vector &vResult) { LOCK(cs_db); assert(mapFileUseCount.count(strFile) == 0); @@ -404,16 +413,17 @@ Db db(dbenv.get(), 0); int result = db.verify(strFile.c_str(), nullptr, &strDump, flags); if (result == DB_VERIFY_BAD) { - LogPrintf("CDBEnv::Salvage: Database salvage found errors, all data " - "may not be recoverable.\n"); + LogPrintf("BerkeleyEnvironment::Salvage: Database salvage found " + "errors, all data may not be recoverable.\n"); if (!fAggressive) { - LogPrintf("CDBEnv::Salvage: Rerun with aggressive mode to ignore " - "errors and continue.\n"); + LogPrintf("BerkeleyEnvironment::Salvage: Rerun with aggressive " + "mode to ignore errors and continue.\n"); return false; } } if (result != 0 && result != DB_VERIFY_BAD) { - LogPrintf("CDBEnv::Salvage: Database salvage failed with result %d.\n", + LogPrintf("BerkeleyEnvironment::Salvage: Database salvage failed with " + "result %d.\n", result); return false; } @@ -441,8 +451,8 @@ } getline(strDump, valueHex); if (valueHex == DATA_END) { - LogPrintf("CDBEnv::Salvage: WARNING: Number of keys in data " - "does not match number of values.\n"); + LogPrintf("BerkeleyEnvironment::Salvage: WARNING: Number of " + "keys in data does not match number of values.\n"); break; } vResult.push_back(make_pair(ParseHex(keyHex), ParseHex(valueHex))); @@ -450,15 +460,15 @@ } if (keyHex != DATA_END) { - LogPrintf("CDBEnv::Salvage: WARNING: Unexpected end of file while " - "reading salvage output.\n"); + LogPrintf("BerkeleyEnvironment::Salvage: WARNING: Unexpected end of " + "file while reading salvage output.\n"); return false; } return (result == 0); } -void CDBEnv::CheckpointLSN(const std::string &strFile) { +void BerkeleyEnvironment::CheckpointLSN(const std::string &strFile) { dbenv->txn_checkpoint(0, 0, 0); if (fMockDb) { return; @@ -466,16 +476,17 @@ dbenv->lsn_reset(strFile.c_str(), 0); } -CDB::CDB(CWalletDBWrapper &dbw, const char *pszMode, bool fFlushOnCloseIn) +BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase &database, const char *pszMode, + bool fFlushOnCloseIn) : pdb(nullptr), activeTxn(nullptr) { fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); fFlushOnClose = fFlushOnCloseIn; - env = dbw.env; - if (dbw.IsDummy()) { + env = database.env; + if (database.IsDummy()) { return; } - const std::string &strFilename = dbw.strFile; + const std::string &strFilename = database.strFile; bool fCreate = strchr(pszMode, 'c') != nullptr; unsigned int nFlags = DB_THREAD; @@ -487,7 +498,7 @@ LOCK(cs_db); if (!env->Open(false /* retry */)) { throw std::runtime_error( - "CDB: Failed to open database environment."); + "BerkeleyBatch: Failed to open database environment."); } pdb = env->mapDb[strFilename]; @@ -502,8 +513,8 @@ ret = mpf->set_flags(DB_MPOOL_NOFILE, 1); if (ret != 0) { throw std::runtime_error( - strprintf("CDB: Failed to configure for no temp file " - "backing for database %s", + strprintf("BerkeleyBatch: Failed to configure for no " + "temp file backing for database %s", strFilename)); } } @@ -517,8 +528,9 @@ 0); if (ret != 0) { - throw std::runtime_error(strprintf( - "CDB: Error %d, can't open database %s", ret, strFilename)); + throw std::runtime_error( + strprintf("BerkeleyBatch: Error %d, can't open database %s", + ret, strFilename)); } // Call CheckUniqueFileid on the containing BDB environment to @@ -555,7 +567,7 @@ } } -void CDB::Flush() { +void BerkeleyBatch::Flush() { if (activeTxn) { return; } @@ -572,11 +584,11 @@ nMinutes, 0); } -void CWalletDBWrapper::IncrementUpdateCounter() { +void BerkeleyDatabase::IncrementUpdateCounter() { ++nUpdateCounter; } -void CDB::Close() { +void BerkeleyBatch::Close() { if (!pdb) { return; } @@ -594,7 +606,7 @@ --env->mapFileUseCount[strFile]; } -void CDBEnv::CloseDb(const std::string &strFile) { +void BerkeleyEnvironment::CloseDb(const std::string &strFile) { LOCK(cs_db); if (mapDb[strFile] != nullptr) { // Close the database handle @@ -605,12 +617,12 @@ } } -bool CDB::Rewrite(CWalletDBWrapper &dbw, const char *pszSkip) { - if (dbw.IsDummy()) { +bool BerkeleyBatch::Rewrite(BerkeleyDatabase &database, const char *pszSkip) { + if (database.IsDummy()) { return true; } - CDBEnv *env = dbw.env; - const std::string &strFile = dbw.strFile; + BerkeleyEnvironment *env = database.env; + const std::string &strFile = database.strFile; while (true) { { LOCK(cs_db); @@ -622,11 +634,11 @@ env->mapFileUseCount.erase(strFile); bool fSuccess = true; - LogPrintf("CDB::Rewrite: Rewriting %s...\n", strFile); + LogPrintf("BerkeleyBatch::Rewrite: Rewriting %s...\n", strFile); std::string strFileRes = strFile + ".rewrite"; { // surround usage of db with extra {} - CDB db(dbw, "r"); + BerkeleyBatch db(database, "r"); std::unique_ptr pdbCopy = std::make_unique(env->dbenv.get(), 0); @@ -637,9 +649,9 @@ DB_CREATE, // Flags 0); if (ret > 0) { - LogPrintf( - "CDB::Rewrite: Can't create database file %s\n", - strFileRes); + LogPrintf("BerkeleyBatch::Rewrite: Can't create " + "database file %s\n", + strFileRes); fSuccess = false; } @@ -699,9 +711,9 @@ } } if (!fSuccess) { - LogPrintf( - "CDB::Rewrite: Failed to rewrite database file %s\n", - strFileRes); + LogPrintf("BerkeleyBatch::Rewrite: Failed to rewrite " + "database file %s\n", + strFileRes); } return fSuccess; } @@ -711,10 +723,10 @@ return false; } -void CDBEnv::Flush(bool fShutdown) { +void BerkeleyEnvironment::Flush(bool fShutdown) { int64_t nStart = GetTimeMillis(); // Flush log data to the actual data file on all files that are not in use - LogPrint(BCLog::DB, "CDBEnv::Flush: Flush(%s)%s\n", + LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started"); if (!fDbEnvInit) { @@ -726,25 +738,31 @@ while (mi != mapFileUseCount.end()) { std::string strFile = (*mi).first; int nRefCount = (*mi).second; - LogPrint(BCLog::DB, - "CDBEnv::Flush: Flushing %s (refcount = %d)...\n", strFile, - nRefCount); + LogPrint( + BCLog::DB, + "BerkeleyEnvironment::Flush: Flushing %s (refcount = %d)...\n", + strFile, nRefCount); if (nRefCount == 0) { // Move log data to the dat file CloseDb(strFile); - LogPrint(BCLog::DB, "CDBEnv::Flush: %s checkpoint\n", strFile); + LogPrint(BCLog::DB, + "BerkeleyEnvironment::Flush: %s checkpoint\n", + strFile); dbenv->txn_checkpoint(0, 0, 0); - LogPrint(BCLog::DB, "CDBEnv::Flush: %s detach\n", strFile); + LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: %s detach\n", + strFile); if (!fMockDb) { dbenv->lsn_reset(strFile.c_str(), 0); } - LogPrint(BCLog::DB, "CDBEnv::Flush: %s closed\n", strFile); + LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: %s closed\n", + strFile); mapFileUseCount.erase(mi++); } else { mi++; } } - LogPrint(BCLog::DB, "CDBEnv::Flush: Flush(%s)%s took %15dms\n", + LogPrint(BCLog::DB, + "BerkeleyEnvironment::Flush: Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart); @@ -761,13 +779,13 @@ } } -bool CDB::PeriodicFlush(CWalletDBWrapper &dbw) { - if (dbw.IsDummy()) { +bool BerkeleyBatch::PeriodicFlush(BerkeleyDatabase &database) { + if (database.IsDummy()) { return true; } bool ret = false; - CDBEnv *env = dbw.env; - const std::string &strFile = dbw.strFile; + BerkeleyEnvironment *env = database.env; + const std::string &strFile = database.strFile; TRY_LOCK(cs_db, lockDb); if (lockDb) { // Don't do this if any databases are in use @@ -801,11 +819,11 @@ return ret; } -bool CWalletDBWrapper::Rewrite(const char *pszSkip) { - return CDB::Rewrite(*this, pszSkip); +bool BerkeleyDatabase::Rewrite(const char *pszSkip) { + return BerkeleyBatch::Rewrite(*this, pszSkip); } -bool CWalletDBWrapper::Backup(const std::string &strDest) { +bool BerkeleyDatabase::Backup(const std::string &strDest) { if (IsDummy()) { return false; } @@ -849,7 +867,7 @@ return false; } -void CWalletDBWrapper::Flush(bool shutdown) { +void BerkeleyDatabase::Flush(bool shutdown) { if (!IsDummy()) { env->Flush(shutdown); } diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -340,25 +340,25 @@ } std::string strError; - if (!CWalletDB::VerifyEnvironment(wallet_path, strError)) { + if (!WalletBatch::VerifyEnvironment(wallet_path, strError)) { return InitError(strError); } if (gArgs.GetBoolArg("-salvagewallet", false)) { // Recover readable keypairs: CWallet dummyWallet(chainParams, "dummy", - CWalletDBWrapper::CreateDummy()); + WalletDatabase::CreateDummy()); std::string backup_filename; - if (!CWalletDB::Recover(wallet_path, (void *)&dummyWallet, - CWalletDB::RecoverKeysOnlyFilter, - backup_filename)) { + if (!WalletBatch::Recover(wallet_path, (void *)&dummyWallet, + WalletBatch::RecoverKeysOnlyFilter, + backup_filename)) { return false; } } std::string strWarning; bool dbV = - CWalletDB::VerifyDatabaseFile(wallet_path, strWarning, strError); + WalletBatch::VerifyDatabaseFile(wallet_path, strWarning, strError); if (!strWarning.empty()) { InitWarning(strWarning); } diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp --- a/src/wallet/test/coinselector_tests.cpp +++ b/src/wallet/test/coinselector_tests.cpp @@ -290,7 +290,7 @@ } BOOST_AUTO_TEST_CASE(knapsack_solver_test) { - CWallet testWallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); + CWallet testWallet(Params(), "dummy", WalletDatabase::CreateDummy()); CoinSet setCoinsRet, setCoinsRet2; Amount nValueRet; @@ -704,7 +704,7 @@ // Tests that with the ideal conditions, the coin selector will always be able // to find a solution that can pay the target value BOOST_AUTO_TEST_CASE(SelectCoins_test) { - CWallet testWallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); + CWallet testWallet(Params(), "dummy", WalletDatabase::CreateDummy()); // Random generator stuff std::default_random_engine generator; diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -12,7 +12,7 @@ WalletTestingSetup::WalletTestingSetup(const std::string &chainName) : TestingSetup(chainName), - m_wallet(Params(), "mock", CWalletDBWrapper::CreateMock()) { + m_wallet(Params(), "mock", WalletDatabase::CreateMock()) { bool fFirstRun; g_address_type = OutputType::DEFAULT; g_change_type = OutputType::DEFAULT; diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -44,7 +44,7 @@ // Verify ScanForWalletTransactions picks up transactions in both the old // and new block files. { - CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); + CWallet wallet(Params(), "dummy", WalletDatabase::CreateDummy()); AddKey(wallet, coinbaseKey); WalletRescanReserver reserver(&wallet); reserver.reserve(); @@ -60,7 +60,7 @@ // Verify ScanForWalletTransactions only picks transactions in the new block // file. { - CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); + CWallet wallet(Params(), "dummy", WalletDatabase::CreateDummy()); AddKey(wallet, coinbaseKey); WalletRescanReserver reserver(&wallet); reserver.reserve(); @@ -73,7 +73,7 @@ // before the missing block, and success for a key whose creation time is // after. { - CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); + CWallet wallet(Params(), "dummy", WalletDatabase::CreateDummy()); AddWallet(&wallet); UniValue keys; keys.setArray(); @@ -154,7 +154,7 @@ // Import key into wallet and call dumpwallet to create backup file. { - CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); + CWallet wallet(Params(), "dummy", WalletDatabase::CreateDummy()); LOCK(wallet.cs_wallet); wallet.mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME; @@ -171,7 +171,7 @@ // Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME // were scanned, and no prior blocks were scanned. { - CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); + CWallet wallet(Params(), "dummy", WalletDatabase::CreateDummy()); JSONRPCRequest request; request.params.setArray(); @@ -200,7 +200,7 @@ // function. Similar tests probably should be written for the other credit and // debit functions. BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup) { - CWallet wallet(Params(), "dummy", CWalletDBWrapper::CreateDummy()); + CWallet wallet(Params(), "dummy", WalletDatabase::CreateDummy()); CWalletTx wtx(&wallet, m_coinbase_txns.back()); LOCK2(cs_main, wallet.cs_wallet); wtx.hashBlock = chainActive.Tip()->GetBlockHash(); @@ -293,7 +293,7 @@ g_address_type = OutputType::DEFAULT; g_change_type = OutputType::DEFAULT; wallet = std::make_unique(Params(), "mock", - CWalletDBWrapper::CreateMock()); + WalletDatabase::CreateMock()); bool firstRun; wallet->LoadWallet(firstRun); AddKey(*wallet, coinbaseKey); diff --git a/src/wallet/test/walletdb_tests.cpp b/src/wallet/test/walletdb_tests.cpp --- a/src/wallet/test/walletdb_tests.cpp +++ b/src/wallet/test/walletdb_tests.cpp @@ -13,10 +13,10 @@ #include namespace { -static std::unique_ptr LoadWallet(CWalletDB *db) { +static std::unique_ptr LoadWallet(WalletBatch &batch) { std::unique_ptr wallet( - new CWallet(Params(), "dummy", CWalletDBWrapper::CreateDummy())); - DBErrors res = db->LoadWallet(wallet.get()); + new CWallet(Params(), "dummy", WalletDatabase::CreateDummy())); + DBErrors res = batch.LoadWallet(wallet.get()); BOOST_CHECK(res == DBErrors::LOAD_OK); return wallet; } @@ -25,65 +25,65 @@ BOOST_FIXTURE_TEST_SUITE(walletdb_tests, WalletTestingSetup) BOOST_AUTO_TEST_CASE(write_erase_name) { - CWalletDB walletdb(m_wallet.GetDBHandle(), "cr+"); + WalletBatch batch(m_wallet.GetDBHandle(), "cr+"); CTxDestination dst1 = CKeyID(uint160S("c0ffee")); CTxDestination dst2 = CKeyID(uint160S("f00d")); - BOOST_CHECK(walletdb.WriteName(dst1, "name1")); - BOOST_CHECK(walletdb.WriteName(dst2, "name2")); + BOOST_CHECK(batch.WriteName(dst1, "name1")); + BOOST_CHECK(batch.WriteName(dst2, "name2")); { - auto w = LoadWallet(&walletdb); + auto w = LoadWallet(batch); BOOST_CHECK_EQUAL(1, w->mapAddressBook.count(dst1)); BOOST_CHECK_EQUAL("name1", w->mapAddressBook[dst1].name); BOOST_CHECK_EQUAL("name2", w->mapAddressBook[dst2].name); } - walletdb.EraseName(dst1); + batch.EraseName(dst1); { - auto w = LoadWallet(&walletdb); + auto w = LoadWallet(batch); BOOST_CHECK_EQUAL(0, w->mapAddressBook.count(dst1)); BOOST_CHECK_EQUAL(1, w->mapAddressBook.count(dst2)); } } BOOST_AUTO_TEST_CASE(write_erase_purpose) { - CWalletDB walletdb(m_wallet.GetDBHandle(), "cr+"); + WalletBatch batch(m_wallet.GetDBHandle(), "cr+"); CTxDestination dst1 = CKeyID(uint160S("c0ffee")); CTxDestination dst2 = CKeyID(uint160S("f00d")); - BOOST_CHECK(walletdb.WritePurpose(dst1, "purpose1")); - BOOST_CHECK(walletdb.WritePurpose(dst2, "purpose2")); + BOOST_CHECK(batch.WritePurpose(dst1, "purpose1")); + BOOST_CHECK(batch.WritePurpose(dst2, "purpose2")); { - auto w = LoadWallet(&walletdb); + auto w = LoadWallet(batch); BOOST_CHECK_EQUAL(1, w->mapAddressBook.count(dst1)); BOOST_CHECK_EQUAL("purpose1", w->mapAddressBook[dst1].purpose); BOOST_CHECK_EQUAL("purpose2", w->mapAddressBook[dst2].purpose); } - walletdb.ErasePurpose(dst1); + batch.ErasePurpose(dst1); { - auto w = LoadWallet(&walletdb); + auto w = LoadWallet(batch); BOOST_CHECK_EQUAL(0, w->mapAddressBook.count(dst1)); BOOST_CHECK_EQUAL(1, w->mapAddressBook.count(dst2)); } } BOOST_AUTO_TEST_CASE(write_erase_destdata) { - CWalletDB walletdb(m_wallet.GetDBHandle(), "cr+"); + WalletBatch batch(m_wallet.GetDBHandle(), "cr+"); CTxDestination dst1 = CKeyID(uint160S("c0ffee")); CTxDestination dst2 = CKeyID(uint160S("f00d")); - BOOST_CHECK(walletdb.WriteDestData(dst1, "key1", "value1")); - BOOST_CHECK(walletdb.WriteDestData(dst1, "key2", "value2")); - BOOST_CHECK(walletdb.WriteDestData(dst2, "key1", "value3")); - BOOST_CHECK(walletdb.WriteDestData(dst2, "key2", "value4")); + BOOST_CHECK(batch.WriteDestData(dst1, "key1", "value1")); + BOOST_CHECK(batch.WriteDestData(dst1, "key2", "value2")); + BOOST_CHECK(batch.WriteDestData(dst2, "key1", "value3")); + BOOST_CHECK(batch.WriteDestData(dst2, "key2", "value4")); { - auto w = LoadWallet(&walletdb); + auto w = LoadWallet(batch); std::string val; BOOST_CHECK(w->GetDestData(dst1, "key1", &val)); BOOST_CHECK_EQUAL("value1", val); @@ -95,10 +95,10 @@ BOOST_CHECK_EQUAL("value4", val); } - walletdb.EraseDestData(dst1, "key2"); + batch.EraseDestData(dst1, "key2"); { - auto w = LoadWallet(&walletdb); + auto w = LoadWallet(batch); std::string dummy; BOOST_CHECK(w->GetDestData(dst1, "key1", &dummy)); BOOST_CHECK(!w->GetDestData(dst1, "key2", &dummy)); @@ -108,12 +108,12 @@ } BOOST_AUTO_TEST_CASE(no_dest_fails) { - CWalletDB walletdb(m_wallet.GetDBHandle(), "cr+"); + WalletBatch batch(m_wallet.GetDBHandle(), "cr+"); CTxDestination dst = CNoDestination{}; - BOOST_CHECK(!walletdb.WriteName(dst, "name")); - BOOST_CHECK(!walletdb.WritePurpose(dst, "purpose")); - BOOST_CHECK(!walletdb.WriteDestData(dst, "key", "value")); + BOOST_CHECK(!batch.WriteName(dst, "name")); + BOOST_CHECK(!batch.WritePurpose(dst, "purpose")); + BOOST_CHECK(!batch.WriteDestData(dst, "key", "value")); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -672,7 +672,7 @@ std::mutex mutexScanning; friend class WalletRescanReserver; - CWalletDB *pwalletdbEncryption = nullptr; + WalletBatch *encrypted_batch = nullptr; //! the current wallet version: clients below this version are not able to //! load the wallet @@ -716,7 +716,7 @@ CHDChain hdChain; /* HD derive new child key (on internal or external chain) */ - void DeriveNewChildKey(CWalletDB &walletdb, CKeyMetadata &metadata, + void DeriveNewChildKey(WalletBatch &batch, CKeyMetadata &metadata, CKey &secret, bool internal = false); std::set setInternalKeyPool; @@ -745,7 +745,7 @@ std::string m_name; /** Internal database handle. */ - std::unique_ptr dbw; + std::unique_ptr database; /** * The following is used to keep track of how far behind the wallet is @@ -771,7 +771,7 @@ * Get database handle used by this wallet. Ideally this function would not * be necessary. */ - CWalletDBWrapper &GetDBHandle() { return *dbw; } + WalletDatabase &GetDBHandle() { return *database; } /** * Select a set of coins such that nValueRet >= nTargetValue and at least @@ -804,13 +804,13 @@ /** Construct wallet with specified name and database implementation. */ CWallet(const CChainParams &chainParamsIn, std::string name, - std::unique_ptr dbwIn) - : m_name(std::move(name)), dbw(std::move(dbwIn)), + std::unique_ptr databaseIn) + : m_name(std::move(name)), database(std::move(databaseIn)), chainParams(chainParamsIn) {} ~CWallet() { - delete pwalletdbEncryption; - pwalletdbEncryption = nullptr; + delete encrypted_batch; + encrypted_batch = nullptr; } std::map mapWallet; @@ -895,10 +895,10 @@ * keystore implementation * Generate a new key */ - CPubKey GenerateNewKey(CWalletDB &walletdb, bool internal = false); + CPubKey GenerateNewKey(WalletBatch &batch, bool internal = false); //! Adds a key to the store, and saves it to disk. bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) override; - bool AddKeyPubKeyWithDB(CWalletDB &walletdb, const CKey &key, + bool AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &key, const CPubKey &pubkey); //! Adds a key to the store, without saving it to disk (used by LoadWallet) bool LoadKey(const CKey &key, const CPubKey &pubkey) { @@ -967,7 +967,7 @@ * Increment the next transaction order id * @return next transaction order id */ - int64_t IncOrderPosNext(CWalletDB *pwalletdb = nullptr); + int64_t IncOrderPosNext(WalletBatch *batch = nullptr); DBErrors ReorderTransactions(); bool AccountMove(std::string strFrom, std::string strTo, const Amount nAmount, std::string strComment = ""); @@ -1032,7 +1032,7 @@ CTransactionRef &tx, CReserveKey &reservekey, Amount &nFeeRet, int &nChangePosInOut, std::string &strFailReason, - const CCoinControl &coinControl, bool sign = true); + const CCoinControl &coin_control, bool sign = true); bool CommitTransaction( CTransactionRef tx, mapValue_t mapValue, std::vector> orderForm, @@ -1042,7 +1042,7 @@ void ListAccountCreditDebit(const std::string &strAccount, std::list &entries); bool AddAccountingEntry(const CAccountingEntry &); - bool AddAccountingEntry(const CAccountingEntry &, CWalletDB *pwalletdb); + bool AddAccountingEntry(const CAccountingEntry &, WalletBatch *batch); bool DummySignTx(CMutableTransaction &txNew, const std::set &txouts) const { std::vector v_txouts(txouts.size()); @@ -1132,7 +1132,7 @@ //! signify that a particular wallet feature is now used. this may change //! nWalletVersion and nWalletMaxVersion if those are lower - bool SetMinVersion(enum WalletFeature, CWalletDB *pwalletdbIn = nullptr, + bool SetMinVersion(enum WalletFeature, WalletBatch *batch_in = nullptr, bool fExplicit = false); //! change which version we're allowed to upgrade to (note that this does diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -156,7 +156,7 @@ return &(it->second); } -CPubKey CWallet::GenerateNewKey(CWalletDB &walletdb, bool internal) { +CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal) { // mapKeyMetadata AssertLockHeld(cs_wallet); // default to compressed public keys if we want 0.6.0 wallets @@ -171,7 +171,7 @@ // use HD key derivation if HD was enabled during wallet creation if (IsHDEnabled()) { DeriveNewChildKey( - walletdb, metadata, secret, + batch, metadata, secret, (CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false)); } else { secret.MakeNewKey(fCompressed); @@ -188,14 +188,14 @@ mapKeyMetadata[pubkey.GetID()] = metadata; UpdateTimeFirstKey(nCreationTime); - if (!AddKeyPubKeyWithDB(walletdb, secret, pubkey)) { + if (!AddKeyPubKeyWithDB(batch, secret, pubkey)) { throw std::runtime_error(std::string(__func__) + ": AddKey failed"); } return pubkey; } -void CWallet::DeriveNewChildKey(CWalletDB &walletdb, CKeyMetadata &metadata, +void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata &metadata, CKey &secret, bool internal) { // for now we use a fixed keypath scheme of m/0'/0'/k // master key seed (256bit) @@ -252,13 +252,13 @@ secret = childKey.key; metadata.hdMasterKeyID = hdChain.masterKeyID; // update the chain model in the database - if (!walletdb.WriteHDChain(hdChain)) { + if (!batch.WriteHDChain(hdChain)) { throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed"); } } -bool CWallet::AddKeyPubKeyWithDB(CWalletDB &walletdb, const CKey &secret, +bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &secret, const CPubKey &pubkey) { // mapKeyMetadata AssertLockHeld(cs_wallet); @@ -267,19 +267,19 @@ // AddCryptedKey // which is overridden below. To avoid flushes, the database handle is // tunneled through to it. - bool needsDB = !pwalletdbEncryption; + bool needsDB = !encrypted_batch; if (needsDB) { - pwalletdbEncryption = &walletdb; + encrypted_batch = &batch; } if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey)) { if (needsDB) { - pwalletdbEncryption = nullptr; + encrypted_batch = nullptr; } return false; } if (needsDB) { - pwalletdbEncryption = nullptr; + encrypted_batch = nullptr; } // Check if we need to remove from watch-only. @@ -298,13 +298,13 @@ return true; } - return walletdb.WriteKey(pubkey, secret.GetPrivKey(), - mapKeyMetadata[pubkey.GetID()]); + return batch.WriteKey(pubkey, secret.GetPrivKey(), + mapKeyMetadata[pubkey.GetID()]); } bool CWallet::AddKeyPubKey(const CKey &secret, const CPubKey &pubkey) { - CWalletDB walletdb(*dbw); - return CWallet::AddKeyPubKeyWithDB(walletdb, secret, pubkey); + WalletBatch batch(*database); + return CWallet::AddKeyPubKeyWithDB(batch, secret, pubkey); } bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, @@ -314,13 +314,13 @@ } LOCK(cs_wallet); - if (pwalletdbEncryption) { - return pwalletdbEncryption->WriteCryptedKey( + if (encrypted_batch) { + return encrypted_batch->WriteCryptedKey( vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); } - return CWalletDB(*dbw).WriteCryptedKey(vchPubKey, vchCryptedSecret, - mapKeyMetadata[vchPubKey.GetID()]); + return WalletBatch(*database).WriteCryptedKey( + vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); } bool CWallet::LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &meta) { @@ -365,7 +365,8 @@ return false; } - return CWalletDB(*dbw).WriteCScript(Hash160(redeemScript), redeemScript); + return WalletBatch(*database).WriteCScript(Hash160(redeemScript), + redeemScript); } bool CWallet::LoadCScript(const CScript &redeemScript) { @@ -396,7 +397,7 @@ const CKeyMetadata &meta = m_script_metadata[CScriptID(dest)]; UpdateTimeFirstKey(meta.nCreateTime); NotifyWatchonlyChanged(true); - return CWalletDB(*dbw).WriteWatchOnly(dest, meta); + return WalletBatch(*database).WriteWatchOnly(dest, meta); } bool CWallet::AddWatchOnly(const CScript &dest, int64_t nCreateTime) { @@ -414,7 +415,7 @@ NotifyWatchonlyChanged(false); } - return CWalletDB(*dbw).EraseWatchOnly(dest); + return WalletBatch(*database).EraseWatchOnly(dest); } bool CWallet::LoadWatchOnly(const CScript &dest) { @@ -511,7 +512,8 @@ return false; } - CWalletDB(*dbw).WriteMasterKey(pMasterKey.first, pMasterKey.second); + WalletBatch(*database).WriteMasterKey(pMasterKey.first, + pMasterKey.second); if (fWasLocked) { Lock(); } @@ -524,11 +526,11 @@ } void CWallet::ChainStateFlushed(const CBlockLocator &loc) { - CWalletDB walletdb(*dbw); - walletdb.WriteBestBlock(loc); + WalletBatch batch(*database); + batch.WriteBestBlock(loc); } -bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB *pwalletdbIn, +bool CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch *batch_in, bool fExplicit) { // nWalletVersion LOCK(cs_wallet); @@ -548,13 +550,12 @@ nWalletMaxVersion = nVersion; } - CWalletDB *pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(*dbw); + WalletBatch *batch = batch_in ? batch_in : new WalletBatch(*database); if (nWalletVersion > 40000) { - pwalletdb->WriteMinVersion(nWalletVersion); + batch->WriteMinVersion(nWalletVersion); } - - if (!pwalletdbIn) { - delete pwalletdb; + if (!batch_in) { + delete batch; } return true; @@ -610,7 +611,7 @@ } void CWallet::Flush(bool shutdown) { - dbw->Flush(shutdown); + database->Flush(shutdown); } void CWallet::SyncMetaData( @@ -752,35 +753,36 @@ { LOCK(cs_wallet); mapMasterKeys[++nMasterKeyMaxID] = kMasterKey; - assert(!pwalletdbEncryption); - pwalletdbEncryption = new CWalletDB(*dbw); - if (!pwalletdbEncryption->TxnBegin()) { - delete pwalletdbEncryption; - pwalletdbEncryption = nullptr; + assert(!encrypted_batch); + encrypted_batch = new WalletBatch(*database); + if (!encrypted_batch->TxnBegin()) { + delete encrypted_batch; + encrypted_batch = nullptr; return false; } - pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey); + encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey); if (!EncryptKeys(_vMasterKey)) { - pwalletdbEncryption->TxnAbort(); - delete pwalletdbEncryption; + encrypted_batch->TxnAbort(); + delete encrypted_batch; // We now probably have half of our keys encrypted in memory, and // half not... die and let the user reload the unencrypted wallet. assert(false); } // Encryption was introduced in version 0.4.0 - SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true); + SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch, true); - if (!pwalletdbEncryption->TxnCommit()) { - delete pwalletdbEncryption; - // We now have keys encrypted in memory, but not on disk... die to - // avoid confusion and let the user reload the unencrypted wallet. + if (!encrypted_batch->TxnCommit()) { + delete encrypted_batch; + // We now have keys encrypted in memory, but not on disk... + // die to avoid confusion and let the user reload the unencrypted + // wallet. assert(false); } - delete pwalletdbEncryption; - pwalletdbEncryption = nullptr; + delete encrypted_batch; + encrypted_batch = nullptr; Lock(); Unlock(strWalletPassphrase); @@ -798,7 +800,7 @@ // Need to completely rewrite the wallet file; if we don't, bdb might // keep bits of the unencrypted private key in slack space in the // database file. - dbw->Rewrite(); + database->Rewrite(); } NotifyStatusChanged(this); @@ -807,7 +809,7 @@ DBErrors CWallet::ReorderTransactions() { LOCK(cs_wallet); - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); // Old wallets didn't have any defined order for transactions. Probably a // bad idea to change the output of this. @@ -823,7 +825,7 @@ } std::list acentries; - walletdb.ListAccountCreditDebit("", acentries); + batch.ListAccountCreditDebit("", acentries); for (CAccountingEntry &entry : acentries) { txByTime.insert(std::make_pair(entry.nTime, TxPair(nullptr, &entry))); } @@ -841,11 +843,11 @@ nOrderPosOffsets.push_back(nOrderPos); if (pwtx) { - if (!walletdb.WriteTx(*pwtx)) { + if (!batch.WriteTx(*pwtx)) { return DBErrors::LOAD_FAIL; } - } else if (!walletdb.WriteAccountingEntry(pacentry->nEntryNo, - *pacentry)) { + } else if (!batch.WriteAccountingEntry(pacentry->nEntryNo, + *pacentry)) { return DBErrors::LOAD_FAIL; } } else { @@ -865,29 +867,29 @@ // Since we're changing the order, write it back. if (pwtx) { - if (!walletdb.WriteTx(*pwtx)) { + if (!batch.WriteTx(*pwtx)) { return DBErrors::LOAD_FAIL; } - } else if (!walletdb.WriteAccountingEntry(pacentry->nEntryNo, - *pacentry)) { + } else if (!batch.WriteAccountingEntry(pacentry->nEntryNo, + *pacentry)) { return DBErrors::LOAD_FAIL; } } } - walletdb.WriteOrderPosNext(nOrderPosNext); + batch.WriteOrderPosNext(nOrderPosNext); return DBErrors::LOAD_OK; } -int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb) { +int64_t CWallet::IncOrderPosNext(WalletBatch *batch) { // nOrderPosNext AssertLockHeld(cs_wallet); int64_t nRet = nOrderPosNext++; - if (pwalletdb) { - pwalletdb->WriteOrderPosNext(nOrderPosNext); + if (batch) { + batch->WriteOrderPosNext(nOrderPosNext); } else { - CWalletDB(*dbw).WriteOrderPosNext(nOrderPosNext); + WalletBatch(*database).WriteOrderPosNext(nOrderPosNext); } return nRet; @@ -895,8 +897,8 @@ bool CWallet::AccountMove(std::string strFrom, std::string strTo, const Amount nAmount, std::string strComment) { - CWalletDB walletdb(*dbw); - if (!walletdb.TxnBegin()) { + WalletBatch batch(*database); + if (!batch.TxnBegin()) { return false; } @@ -904,33 +906,33 @@ // Debit CAccountingEntry debit; - debit.nOrderPos = IncOrderPosNext(&walletdb); + debit.nOrderPos = IncOrderPosNext(&batch); debit.strAccount = strFrom; debit.nCreditDebit = -nAmount; debit.nTime = nNow; debit.strOtherAccount = strTo; debit.strComment = strComment; - AddAccountingEntry(debit, &walletdb); + AddAccountingEntry(debit, &batch); // Credit CAccountingEntry credit; - credit.nOrderPos = IncOrderPosNext(&walletdb); + credit.nOrderPos = IncOrderPosNext(&batch); credit.strAccount = strTo; credit.nCreditDebit = nAmount; credit.nTime = nNow; credit.strOtherAccount = strFrom; credit.strComment = strComment; - AddAccountingEntry(credit, &walletdb); + AddAccountingEntry(credit, &batch); - return walletdb.TxnCommit(); + return batch.TxnCommit(); } bool CWallet::GetLabelDestination(CTxDestination &dest, const std::string &label, bool bForceNew) { - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); CAccount account; - walletdb.ReadAccount(label, account); + batch.ReadAccount(label, account); if (!bForceNew) { if (!account.vchPubKey.IsValid()) { @@ -961,7 +963,7 @@ LearnRelatedScripts(account.vchPubKey, g_address_type); dest = GetDestinationForKey(account.vchPubKey, g_address_type); SetAddressBook(dest, label, "receive"); - walletdb.WriteAccount(label, account); + batch.WriteAccount(label, account); } else { dest = GetDestinationForKey(account.vchPubKey, g_address_type); } @@ -979,7 +981,7 @@ bool CWallet::AddToWallet(const CWalletTx &wtxIn, bool fFlushOnClose) { LOCK(cs_wallet); - CWalletDB walletdb(*dbw, "r+", fFlushOnClose); + WalletBatch batch(*database, "r+", fFlushOnClose); const TxId &txid = wtxIn.GetId(); @@ -991,7 +993,7 @@ bool fInsertedNew = ret.second; if (fInsertedNew) { wtx.nTimeReceived = GetAdjustedTime(); - wtx.nOrderPos = IncOrderPosNext(&walletdb); + wtx.nOrderPos = IncOrderPosNext(&batch); wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr))); wtx.nTimeSmart = ComputeTimeSmart(wtx); AddToSpends(txid); @@ -1027,7 +1029,7 @@ (fInsertedNew ? "new" : ""), (fUpdated ? "update" : "")); // Write to disk - if ((fInsertedNew || fUpdated) && !walletdb.WriteTx(wtx)) { + if ((fInsertedNew || fUpdated) && !batch.WriteTx(wtx)) { return false; } @@ -1169,7 +1171,7 @@ bool CWallet::AbandonTransaction(const TxId &txid) { LOCK2(cs_main, cs_wallet); - CWalletDB walletdb(*dbw, "r+"); + WalletBatch batch(*database, "r+"); std::set todo; std::set done; @@ -1203,7 +1205,7 @@ wtx.nIndex = -1; wtx.setAbandoned(); wtx.MarkDirty(); - walletdb.WriteTx(wtx); + batch.WriteTx(wtx); NotifyTransactionChanged(this, wtx.GetId(), CT_UPDATED); // Iterate over all its outputs, and mark transactions in the wallet // that spend them abandoned too. @@ -1248,7 +1250,7 @@ } // Do not flush the wallet here for performance reasons. - CWalletDB walletdb(*dbw, "r+", false); + WalletBatch batch(*database, "r+", false); std::set todo; std::set done; @@ -1269,7 +1271,7 @@ wtx.nIndex = -1; wtx.hashBlock = hashBlock; wtx.MarkDirty(); - walletdb.WriteTx(wtx); + batch.WriteTx(wtx); // Iterate over all its outputs, and mark transactions in the wallet // that spend them conflicted too. TxSpends::const_iterator iter = @@ -1280,7 +1282,6 @@ } iter++; } - // If a transaction changes 'conflicted' state, that changes the // balance available of the outputs it spends. So force those to be // recomputed. @@ -1596,7 +1597,7 @@ bool CWallet::SetHDChain(const CHDChain &chain, bool memonly) { LOCK(cs_wallet); - if (!memonly && !CWalletDB(*dbw).WriteHDChain(chain)) { + if (!memonly && !WalletBatch(*database).WriteHDChain(chain)) { throw std::runtime_error(std::string(__func__) + ": writing chain failed"); } @@ -2362,7 +2363,7 @@ } if (account) { - balance += CWalletDB(*dbw).GetAccountCreditDebit(*account); + balance += WalletBatch(*database).GetAccountCreditDebit(*account); } return balance; @@ -3358,18 +3359,19 @@ void CWallet::ListAccountCreditDebit(const std::string &strAccount, std::list &entries) { - CWalletDB walletdb(*dbw); - return walletdb.ListAccountCreditDebit(strAccount, entries); + WalletBatch batch(*database); + return batch.ListAccountCreditDebit(strAccount, entries); } bool CWallet::AddAccountingEntry(const CAccountingEntry &acentry) { - CWalletDB walletdb(*dbw); - return AddAccountingEntry(acentry, &walletdb); + WalletBatch batch(*database); + + return AddAccountingEntry(acentry, &batch); } bool CWallet::AddAccountingEntry(const CAccountingEntry &acentry, - CWalletDB *pwalletdb) { - if (!pwalletdb->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) { + WalletBatch *batch) { + if (!batch->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) { return false; } @@ -3384,9 +3386,9 @@ LOCK2(cs_main, cs_wallet); fFirstRunRet = false; - DBErrors nLoadWalletRet = CWalletDB(*dbw, "cr+").LoadWallet(this); + DBErrors nLoadWalletRet = WalletBatch(*database, "cr+").LoadWallet(this); if (nLoadWalletRet == DBErrors::NEED_REWRITE) { - if (dbw->Rewrite("\x04pool")) { + if (database->Rewrite("\x04pool")) { setInternalKeyPool.clear(); setExternalKeyPool.clear(); m_pool_key_to_index.clear(); @@ -3412,15 +3414,16 @@ DBErrors CWallet::ZapSelectTx(std::vector &txIdsIn, std::vector &txIdsOut) { - AssertLockHeld(cs_wallet); // mapWallet + // mapWallet + AssertLockHeld(cs_wallet); DBErrors nZapSelectTxRet = - CWalletDB(*dbw, "cr+").ZapSelectTx(txIdsIn, txIdsOut); + WalletBatch(*database, "cr+").ZapSelectTx(txIdsIn, txIdsOut); for (const TxId &txid : txIdsOut) { mapWallet.erase(txid); } if (nZapSelectTxRet == DBErrors::NEED_REWRITE) { - if (dbw->Rewrite("\x04pool")) { + if (database->Rewrite("\x04pool")) { setInternalKeyPool.clear(); setExternalKeyPool.clear(); m_pool_key_to_index.clear(); @@ -3440,9 +3443,9 @@ } DBErrors CWallet::ZapWalletTx(std::vector &vWtx) { - DBErrors nZapWalletTxRet = CWalletDB(*dbw, "cr+").ZapWalletTx(vWtx); + DBErrors nZapWalletTxRet = WalletBatch(*database, "cr+").ZapWalletTx(vWtx); if (nZapWalletTxRet == DBErrors::NEED_REWRITE) { - if (dbw->Rewrite("\x04pool")) { + if (database->Rewrite("\x04pool")) { LOCK(cs_wallet); setInternalKeyPool.clear(); setExternalKeyPool.clear(); @@ -3480,13 +3483,11 @@ NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != ISMINE_NO, strPurpose, (fUpdated ? CT_UPDATED : CT_NEW)); - if (!strPurpose.empty() && - !CWalletDB(*dbw).WritePurpose(address, strPurpose)) { + !WalletBatch(*database).WritePurpose(address, strPurpose)) { return false; } - - return CWalletDB(*dbw).WriteName(address, strName); + return WalletBatch(*database).WriteName(address, strName); } bool CWallet::DelAddressBook(const CTxDestination &address) { @@ -3497,7 +3498,7 @@ // Delete destdata tuples associated with address. for (const std::pair &item : mapAddressBook[address].destdata) { - CWalletDB(*dbw).EraseDestData(address, item.first); + WalletBatch(*database).EraseDestData(address, item.first); } mapAddressBook.erase(address); @@ -3507,8 +3508,8 @@ ::IsMine(*this, address) != ISMINE_NO, "", CT_DELETED); - CWalletDB(*dbw).ErasePurpose(address); - return CWalletDB(*dbw).EraseName(address); + WalletBatch(*database).ErasePurpose(address); + return WalletBatch(*database).EraseName(address); } const std::string &CWallet::GetLabelName(const CScript &scriptPubKey) const { @@ -3531,15 +3532,15 @@ */ bool CWallet::NewKeyPool() { LOCK(cs_wallet); - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); for (int64_t nIndex : setInternalKeyPool) { - walletdb.ErasePool(nIndex); + batch.ErasePool(nIndex); } setInternalKeyPool.clear(); for (int64_t nIndex : setExternalKeyPool) { - walletdb.ErasePool(nIndex); + batch.ErasePool(nIndex); } setExternalKeyPool.clear(); @@ -3607,7 +3608,7 @@ missingInternal = 0; } bool internal = false; - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); for (int64_t i = missingInternal + missingExternal; i--;) { if (i < missingInternal) { internal = true; @@ -3617,8 +3618,8 @@ assert(m_max_keypool_index < std::numeric_limits::max()); int64_t index = ++m_max_keypool_index; - CPubKey pubkey(GenerateNewKey(walletdb, internal)); - if (!walletdb.WritePool(index, CKeyPool(pubkey, internal))) { + CPubKey pubkey(GenerateNewKey(batch, internal)); + if (!batch.WritePool(index, CKeyPool(pubkey, internal))) { throw std::runtime_error(std::string(__func__) + ": writing generated key failed"); } @@ -3663,12 +3664,12 @@ return; } - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); auto it = setKeyPool.begin(); nIndex = *it; setKeyPool.erase(it); - if (!walletdb.ReadPool(nIndex, keypool)) { + if (!batch.ReadPool(nIndex, keypool)) { throw std::runtime_error(std::string(__func__) + ": read failed"); } if (!HaveKey(keypool.vchPubKey.GetID())) { @@ -3687,8 +3688,8 @@ void CWallet::KeepKey(int64_t nIndex) { // Remove from key pool. - CWalletDB walletdb(*dbw); - walletdb.ErasePool(nIndex); + WalletBatch batch(*database); + batch.ErasePool(nIndex); LogPrintf("keypool keep %d\n", nIndex); } @@ -3716,8 +3717,8 @@ if (IsLocked()) { return false; } - CWalletDB walletdb(*dbw); - result = GenerateNewKey(walletdb, internal); + WalletBatch batch(*database); + result = GenerateNewKey(batch, internal); return true; } @@ -3728,14 +3729,14 @@ } static int64_t GetOldestKeyTimeInPool(const std::set &setKeyPool, - CWalletDB &walletdb) { + WalletBatch &batch) { if (setKeyPool.empty()) { return GetTime(); } CKeyPool keypool; int64_t nIndex = *(setKeyPool.begin()); - if (!walletdb.ReadPool(nIndex, keypool)) { + if (!batch.ReadPool(nIndex, keypool)) { throw std::runtime_error(std::string(__func__) + ": read oldest key in keypool failed"); } @@ -3747,13 +3748,13 @@ int64_t CWallet::GetOldestKeyPoolTime() { LOCK(cs_wallet); - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); // load oldest key from keypool, get time and return - int64_t oldestKey = GetOldestKeyTimeInPool(setExternalKeyPool, walletdb); + int64_t oldestKey = GetOldestKeyTimeInPool(setExternalKeyPool, batch); if (IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT)) { - oldestKey = std::max( - GetOldestKeyTimeInPool(setInternalKeyPool, walletdb), oldestKey); + oldestKey = std::max(GetOldestKeyTimeInPool(setInternalKeyPool, batch), + oldestKey); } return oldestKey; @@ -3969,7 +3970,7 @@ internal ? &setInternalKeyPool : &setExternalKeyPool; auto it = setKeyPool->begin(); - CWalletDB walletdb(*dbw); + WalletBatch batch(*database); while (it != std::end(*setKeyPool)) { const int64_t &index = *(it); if (index > keypool_id) { @@ -3978,12 +3979,12 @@ } CKeyPool keypool; - if (walletdb.ReadPool(index, keypool)) { + if (batch.ReadPool(index, keypool)) { // TODO: This should be unnecessary m_pool_key_to_index.erase(keypool.vchPubKey.GetID()); } LearnAllRelatedScripts(keypool.vchPubKey); - walletdb.ErasePool(index); + batch.ErasePool(index); it = setKeyPool->erase(it); } } @@ -4177,7 +4178,7 @@ } mapAddressBook[dest].destdata.insert(std::make_pair(key, value)); - return CWalletDB(*dbw).WriteDestData(dest, key, value); + return WalletBatch(*database).WriteDestData(dest, key, value); } bool CWallet::EraseDestData(const CTxDestination &dest, @@ -4186,7 +4187,7 @@ return false; } - return CWalletDB(*dbw).EraseDestData(dest, key); + return WalletBatch(*database).EraseDestData(dest, key); } bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, @@ -4239,7 +4240,7 @@ uiInterface.InitMessage(_("Zapping all transactions from wallet...")); std::unique_ptr tempWallet = std::make_unique( - chainParams, name, CWalletDBWrapper::Create(path)); + chainParams, name, WalletDatabase::Create(path)); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); if (nZapWalletRet != DBErrors::LOAD_OK) { InitError( @@ -4253,7 +4254,7 @@ int64_t nStart = GetTimeMillis(); bool fFirstRun = true; CWallet *walletInstance = - new CWallet(chainParams, name, CWalletDBWrapper::Create(path)); + new CWallet(chainParams, name, WalletDatabase::Create(path)); DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); if (nLoadWalletRet != DBErrors::LOAD_OK) { if (nLoadWalletRet == DBErrors::CORRUPT) { @@ -4412,9 +4413,9 @@ CBlockIndex *pindexRescan = chainActive.Genesis(); if (!gArgs.GetBoolArg("-rescan", false)) { - CWalletDB walletdb(*walletInstance->dbw); + WalletBatch batch(*walletInstance->database); CBlockLocator locator; - if (walletdb.ReadBestBlock(locator)) { + if (batch.ReadBestBlock(locator)) { pindexRescan = FindForkInGlobalIndex(chainActive, locator); } } @@ -4468,12 +4469,12 @@ } LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); walletInstance->ChainStateFlushed(chainActive.GetLocator()); - walletInstance->dbw->IncrementUpdateCounter(); + walletInstance->database->IncrementUpdateCounter(); // Restore wallet transaction metadata after -zapwallettxes=1 if (gArgs.GetBoolArg("-zapwallettxes", false) && gArgs.GetArg("-zapwallettxes", "1") != "2") { - CWalletDB walletdb(*walletInstance->dbw); + WalletBatch batch(*walletInstance->database); for (const CWalletTx &wtxOld : vWtx) { const TxId txid = wtxOld.GetId(); @@ -4489,7 +4490,7 @@ copyTo->fFromMe = copyFrom->fFromMe; copyTo->strFromAccount = copyFrom->strFromAccount; copyTo->nOrderPos = copyFrom->nOrderPos; - walletdb.WriteTx(*copyTo); + batch.WriteTx(*copyTo); } } } @@ -4526,7 +4527,7 @@ } bool CWallet::BackupWallet(const std::string &strDest) { - return dbw->Backup(strDest); + return database->Backup(strDest); } CKeyPool::CKeyPool() { diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -22,19 +22,14 @@ /** * Overview of wallet database classes: * - * - CDBEnv is an environment in which the database exists (has no analog in - * dbwrapper.h) - * - CWalletDBWrapper represents a wallet database (similar to CDBWrapper in - * dbwrapper.h) - * - CDB is a low-level database transaction (similar to CDBBatch in - * dbwrapper.h) - * - CWalletDB is a modifier object for the wallet, and encapsulates a database - * transaction as well as methods to act on the database (no analog in - * dbwrapper.h) + * - WalletBatch is an abstract modifier object for the wallet database, and + * encapsulates a database batch update as well as methods to act on the + * database. It should be agnostic to the database implementation. * - * The latter two are named confusingly, in contrast to what the names CDB - * and CWalletDB suggest they are transient transaction objects and don't - * represent the database itself. + * The following classes are implementation specific: + * - BerkeleyEnvironment is an environment in which the database exists. + * - BerkeleyDatabase represents a wallet database. + * - BerkeleyBatch is a low-level database batch update. */ static const bool DEFAULT_FLUSHWALLET = true; @@ -50,6 +45,9 @@ class uint160; class uint256; +/** Backend-agnostic database type. */ +using WalletDatabase = BerkeleyDatabase; + /** Error statuses for the wallet database */ enum class DBErrors { LOAD_OK, @@ -134,36 +132,35 @@ /** * Access to the wallet database. - * This should really be named CWalletDBBatch, as it represents a single - * transaction at the database. It will be committed when the object goes out of - * scope. - * Optionally (on by default) it will flush to disk as well. + * This represents a single transaction at the database. It will be committed + * when the object goes out of scope. Optionally (on by default) it will flush + * to disk as well. */ -class CWalletDB { +class WalletBatch { private: template bool WriteIC(const K &key, const T &value, bool fOverwrite = true) { - if (!batch.Write(key, value, fOverwrite)) { + if (!m_batch.Write(key, value, fOverwrite)) { return false; } - m_dbw.IncrementUpdateCounter(); + m_database.IncrementUpdateCounter(); return true; } template bool EraseIC(const K &key) { - if (!batch.Erase(key)) { + if (!m_batch.Erase(key)) { return false; } - m_dbw.IncrementUpdateCounter(); + m_database.IncrementUpdateCounter(); return true; } public: - explicit CWalletDB(CWalletDBWrapper &dbw, const char *pszMode = "r+", - bool _fFlushOnClose = true) - : batch(dbw, pszMode, _fFlushOnClose), m_dbw(dbw) {} - CWalletDB(const CWalletDB &) = delete; - CWalletDB &operator=(const CWalletDB &) = delete; + explicit WalletBatch(WalletDatabase &database, const char *pszMode = "r+", + bool _fFlushOnClose = true) + : m_batch(database, pszMode, _fFlushOnClose), m_database(database) {} + WalletBatch(const WalletBatch &) = delete; + WalletBatch &operator=(const WalletBatch &) = delete; bool WriteName(const CTxDestination &address, const std::string &strName); bool EraseName(const CTxDestination &address); @@ -263,8 +260,8 @@ bool WriteVersion(int nVersion); private: - CDB batch; - CWalletDBWrapper &m_dbw; + BerkeleyBatch m_batch; + WalletDatabase &m_database; }; //! Compacts BDB state so that wallet.dat is self-contained (if there are diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -21,11 +21,11 @@ #include // -// CWalletDB +// WalletBatch // -bool CWalletDB::WriteName(const CTxDestination &address, - const std::string &strName) { +bool WalletBatch::WriteName(const CTxDestination &address, + const std::string &strName) { if (!IsValidDestination(address)) { return false; } @@ -34,7 +34,7 @@ strName); } -bool CWalletDB::EraseName(const CTxDestination &address) { +bool WalletBatch::EraseName(const CTxDestination &address) { // This should only be used for sending addresses, never for receiving // addresses, receiving addresses must always have an address book entry if // they're not change return. @@ -45,8 +45,8 @@ EncodeLegacyAddr(address, Params()))); } -bool CWalletDB::WritePurpose(const CTxDestination &address, - const std::string &strPurpose) { +bool WalletBatch::WritePurpose(const CTxDestination &address, + const std::string &strPurpose) { if (!IsValidDestination(address)) { return false; } @@ -55,7 +55,7 @@ strPurpose); } -bool CWalletDB::ErasePurpose(const CTxDestination &address) { +bool WalletBatch::ErasePurpose(const CTxDestination &address) { if (!IsValidDestination(address)) { return false; } @@ -63,16 +63,16 @@ EncodeLegacyAddr(address, Params()))); } -bool CWalletDB::WriteTx(const CWalletTx &wtx) { +bool WalletBatch::WriteTx(const CWalletTx &wtx) { return WriteIC(std::make_pair(std::string("tx"), wtx.GetId()), wtx); } -bool CWalletDB::EraseTx(uint256 hash) { +bool WalletBatch::EraseTx(uint256 hash) { return EraseIC(std::make_pair(std::string("tx"), hash)); } -bool CWalletDB::WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, - const CKeyMetadata &keyMeta) { +bool WalletBatch::WriteKey(const CPubKey &vchPubKey, const CPrivKey &vchPrivKey, + const CKeyMetadata &keyMeta) { if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) { return false; @@ -89,9 +89,9 @@ std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false); } -bool CWalletDB::WriteCryptedKey(const CPubKey &vchPubKey, - const std::vector &vchCryptedSecret, - const CKeyMetadata &keyMeta) { +bool WalletBatch::WriteCryptedKey(const CPubKey &vchPubKey, + const std::vector &vchCryptedSecret, + const CKeyMetadata &keyMeta) { if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) { return false; @@ -106,84 +106,88 @@ return true; } -bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey &kMasterKey) { +bool WalletBatch::WriteMasterKey(unsigned int nID, + const CMasterKey &kMasterKey) { return WriteIC(std::make_pair(std::string("mkey"), nID), kMasterKey, true); } -bool CWalletDB::WriteCScript(const uint160 &hash, const CScript &redeemScript) { +bool WalletBatch::WriteCScript(const uint160 &hash, + const CScript &redeemScript) { return WriteIC(std::make_pair(std::string("cscript"), hash), redeemScript, false); } -bool CWalletDB::WriteWatchOnly(const CScript &dest, - const CKeyMetadata &keyMeta) { +bool WalletBatch::WriteWatchOnly(const CScript &dest, + const CKeyMetadata &keyMeta) { if (!WriteIC(std::make_pair(std::string("watchmeta"), dest), keyMeta)) { return false; } return WriteIC(std::make_pair(std::string("watchs"), dest), '1'); } -bool CWalletDB::EraseWatchOnly(const CScript &dest) { +bool WalletBatch::EraseWatchOnly(const CScript &dest) { if (!EraseIC(std::make_pair(std::string("watchmeta"), dest))) { return false; } return EraseIC(std::make_pair(std::string("watchs"), dest)); } -bool CWalletDB::WriteBestBlock(const CBlockLocator &locator) { +bool WalletBatch::WriteBestBlock(const CBlockLocator &locator) { // Write empty block locator so versions that require a merkle branch // automatically rescan WriteIC(std::string("bestblock"), CBlockLocator()); return WriteIC(std::string("bestblock_nomerkle"), locator); } -bool CWalletDB::ReadBestBlock(CBlockLocator &locator) { - if (batch.Read(std::string("bestblock"), locator) && +bool WalletBatch::ReadBestBlock(CBlockLocator &locator) { + if (m_batch.Read(std::string("bestblock"), locator) && !locator.vHave.empty()) { return true; } - return batch.Read(std::string("bestblock_nomerkle"), locator); + return m_batch.Read(std::string("bestblock_nomerkle"), locator); } -bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext) { +bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext) { return WriteIC(std::string("orderposnext"), nOrderPosNext); } -bool CWalletDB::ReadPool(int64_t nPool, CKeyPool &keypool) { - return batch.Read(std::make_pair(std::string("pool"), nPool), keypool); +bool WalletBatch::ReadPool(int64_t nPool, CKeyPool &keypool) { + return m_batch.Read(std::make_pair(std::string("pool"), nPool), keypool); } -bool CWalletDB::WritePool(int64_t nPool, const CKeyPool &keypool) { +bool WalletBatch::WritePool(int64_t nPool, const CKeyPool &keypool) { return WriteIC(std::make_pair(std::string("pool"), nPool), keypool); } -bool CWalletDB::ErasePool(int64_t nPool) { +bool WalletBatch::ErasePool(int64_t nPool) { return EraseIC(std::make_pair(std::string("pool"), nPool)); } -bool CWalletDB::WriteMinVersion(int nVersion) { +bool WalletBatch::WriteMinVersion(int nVersion) { return WriteIC(std::string("minversion"), nVersion); } -bool CWalletDB::ReadAccount(const std::string &strAccount, CAccount &account) { +bool WalletBatch::ReadAccount(const std::string &strAccount, + CAccount &account) { account.SetNull(); - return batch.Read(std::make_pair(std::string("acc"), strAccount), account); + return m_batch.Read(std::make_pair(std::string("acc"), strAccount), + account); } -bool CWalletDB::WriteAccount(const std::string &strAccount, - const CAccount &account) { +bool WalletBatch::WriteAccount(const std::string &strAccount, + const CAccount &account) { return WriteIC(std::make_pair(std::string("acc"), strAccount), account); } -bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, - const CAccountingEntry &acentry) { +bool WalletBatch::WriteAccountingEntry(const uint64_t nAccEntryNum, + const CAccountingEntry &acentry) { return WriteIC( std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry); } -Amount CWalletDB::GetAccountCreditDebit(const std::string &strAccount) { +Amount WalletBatch::GetAccountCreditDebit(const std::string &strAccount) { std::list entries; ListAccountCreditDebit(strAccount, entries); @@ -195,11 +199,11 @@ return nCreditDebit; } -void CWalletDB::ListAccountCreditDebit(const std::string &strAccount, - std::list &entries) { +void WalletBatch::ListAccountCreditDebit(const std::string &strAccount, + std::list &entries) { bool fAllAccounts = (strAccount == "*"); - Dbc *pcursor = batch.GetCursor(); + Dbc *pcursor = m_batch.GetCursor(); if (!pcursor) { throw std::runtime_error(std::string(__func__) + ": cannot create DB cursor"); @@ -215,7 +219,7 @@ uint64_t(0))); } CDataStream ssValue(SER_DISK, CLIENT_VERSION); - int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue, setRange); + int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue, setRange); setRange = false; if (ret == DB_NOTFOUND) { break; @@ -513,12 +517,12 @@ return true; } -bool CWalletDB::IsKeyType(const std::string &strType) { +bool WalletBatch::IsKeyType(const std::string &strType) { return (strType == "key" || strType == "wkey" || strType == "mkey" || strType == "ckey"); } -DBErrors CWalletDB::LoadWallet(CWallet *pwallet) { +DBErrors WalletBatch::LoadWallet(CWallet *pwallet) { CWalletScanState wss; bool fNoncriticalErrors = false; DBErrors result = DBErrors::LOAD_OK; @@ -526,7 +530,7 @@ LOCK(pwallet->cs_wallet); try { int nMinVersion = 0; - if (batch.Read((std::string) "minversion", nMinVersion)) { + if (m_batch.Read((std::string) "minversion", nMinVersion)) { if (nMinVersion > CLIENT_VERSION) { return DBErrors::TOO_NEW; } @@ -534,7 +538,7 @@ } // Get cursor - Dbc *pcursor = batch.GetCursor(); + Dbc *pcursor = m_batch.GetCursor(); if (!pcursor) { LogPrintf("Error getting wallet database cursor\n"); return DBErrors::CORRUPT; @@ -544,7 +548,7 @@ // Read next record CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION); - int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue); + int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue); if (ret == DB_NOTFOUND) { break; } @@ -632,20 +636,20 @@ return result; } -DBErrors CWalletDB::FindWalletTx(std::vector &txIds, - std::vector &vWtx) { +DBErrors WalletBatch::FindWalletTx(std::vector &txIds, + std::vector &vWtx) { DBErrors result = DBErrors::LOAD_OK; try { int nMinVersion = 0; - if (batch.Read((std::string) "minversion", nMinVersion)) { + if (m_batch.Read((std::string) "minversion", nMinVersion)) { if (nMinVersion > CLIENT_VERSION) { return DBErrors::TOO_NEW; } } // Get cursor - Dbc *pcursor = batch.GetCursor(); + Dbc *pcursor = m_batch.GetCursor(); if (!pcursor) { LogPrintf("Error getting wallet database cursor\n"); return DBErrors::CORRUPT; @@ -655,7 +659,7 @@ // Read next record CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION); - int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue); + int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue); if (ret == DB_NOTFOUND) { break; } @@ -688,8 +692,8 @@ return result; } -DBErrors CWalletDB::ZapSelectTx(std::vector &txIdsIn, - std::vector &txIdsOut) { +DBErrors WalletBatch::ZapSelectTx(std::vector &txIdsIn, + std::vector &txIdsOut) { // Build list of wallet TXs and hashes. std::vector txIds; std::vector vWtx; @@ -730,7 +734,7 @@ return DBErrors::LOAD_OK; } -DBErrors CWalletDB::ZapWalletTx(std::vector &vWtx) { +DBErrors WalletBatch::ZapWalletTx(std::vector &vWtx) { // Build list of wallet TXs. std::vector txIds; DBErrors err = FindWalletTx(txIds, vWtx); @@ -758,7 +762,7 @@ } for (CWallet *pwallet : GetWallets()) { - CWalletDBWrapper &dbh = pwallet->GetDBHandle(); + WalletDatabase &dbh = pwallet->GetDBHandle(); unsigned int nUpdateCounter = dbh.nUpdateCounter; @@ -769,7 +773,7 @@ if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) { - if (CDB::PeriodicFlush(dbh)) { + if (BerkeleyBatch::PeriodicFlush(dbh)) { dbh.nLastFlushed = nUpdateCounter; } } @@ -781,25 +785,25 @@ // // Try to (very carefully!) recover wallet file if there is a problem. // -bool CWalletDB::Recover(const fs::path &wallet_path, void *callbackDataIn, - bool (*recoverKVcallback)(void *callbackData, - CDataStream ssKey, - CDataStream ssValue), - std::string &out_backup_filename) { - return CDB::Recover(wallet_path, callbackDataIn, recoverKVcallback, - out_backup_filename); +bool WalletBatch::Recover(const fs::path &wallet_path, void *callbackDataIn, + bool (*recoverKVcallback)(void *callbackData, + CDataStream ssKey, + CDataStream ssValue), + std::string &out_backup_filename) { + return BerkeleyBatch::Recover(wallet_path, callbackDataIn, + recoverKVcallback, out_backup_filename); } -bool CWalletDB::Recover(const fs::path &wallet_path, - std::string &out_backup_filename) { +bool WalletBatch::Recover(const fs::path &wallet_path, + std::string &out_backup_filename) { // recover without a key filter callback // results in recovering all record types - return CWalletDB::Recover(wallet_path, nullptr, nullptr, - out_backup_filename); + return WalletBatch::Recover(wallet_path, nullptr, nullptr, + out_backup_filename); } -bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, - CDataStream ssValue) { +bool WalletBatch::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, + CDataStream ssValue) { CWallet *dummyWallet = reinterpret_cast(callbackData); CWalletScanState dummyWss; std::string strType, strErr; @@ -814,7 +818,7 @@ return false; } if (!fReadOK) { - LogPrintf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType, + LogPrintf("WARNING: WalletBatch::Recover skipping %s: %s\n", strType, strErr); return false; } @@ -822,21 +826,21 @@ return true; } -bool CWalletDB::VerifyEnvironment(const fs::path &wallet_path, - std::string &errorStr) { - return CDB::VerifyEnvironment(wallet_path, errorStr); +bool WalletBatch::VerifyEnvironment(const fs::path &wallet_path, + std::string &errorStr) { + return BerkeleyBatch::VerifyEnvironment(wallet_path, errorStr); } -bool CWalletDB::VerifyDatabaseFile(const fs::path &wallet_path, - std::string &warningStr, - std::string &errorStr) { - return CDB::VerifyDatabaseFile(wallet_path, warningStr, errorStr, - CWalletDB::Recover); +bool WalletBatch::VerifyDatabaseFile(const fs::path &wallet_path, + std::string &warningStr, + std::string &errorStr) { + return BerkeleyBatch::VerifyDatabaseFile(wallet_path, warningStr, errorStr, + WalletBatch::Recover); } -bool CWalletDB::WriteDestData(const CTxDestination &address, - const std::string &key, - const std::string &value) { +bool WalletBatch::WriteDestData(const CTxDestination &address, + const std::string &key, + const std::string &value) { if (!IsValidDestination(address)) { return false; } @@ -847,8 +851,8 @@ value); } -bool CWalletDB::EraseDestData(const CTxDestination &address, - const std::string &key) { +bool WalletBatch::EraseDestData(const CTxDestination &address, + const std::string &key) { if (!IsValidDestination(address)) { return false; } @@ -857,26 +861,26 @@ std::make_pair(EncodeLegacyAddr(address, Params()), key))); } -bool CWalletDB::WriteHDChain(const CHDChain &chain) { +bool WalletBatch::WriteHDChain(const CHDChain &chain) { return WriteIC(std::string("hdchain"), chain); } -bool CWalletDB::TxnBegin() { - return batch.TxnBegin(); +bool WalletBatch::TxnBegin() { + return m_batch.TxnBegin(); } -bool CWalletDB::TxnCommit() { - return batch.TxnCommit(); +bool WalletBatch::TxnCommit() { + return m_batch.TxnCommit(); } -bool CWalletDB::TxnAbort() { - return batch.TxnAbort(); +bool WalletBatch::TxnAbort() { + return m_batch.TxnAbort(); } -bool CWalletDB::ReadVersion(int &nVersion) { - return batch.ReadVersion(nVersion); +bool WalletBatch::ReadVersion(int &nVersion) { + return m_batch.ReadVersion(nVersion); } -bool CWalletDB::WriteVersion(int nVersion) { - return batch.WriteVersion(nVersion); +bool WalletBatch::WriteVersion(int nVersion) { + return m_batch.WriteVersion(nVersion); } diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -85,7 +85,7 @@ # should not initialize if one wallet is a copy of another shutil.copyfile(wallet_dir('w8'), wallet_dir('w8_copy')) - exp_stderr = r"CDB: Can't open database w8_copy \(duplicates fileid \w+ from w8\)" + exp_stderr = r"BerkeleyBatch: 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, partial_match=True)