dash/src/wallet/db.h

372 lines
11 KiB
C
Raw Normal View History

// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_WALLET_DB_H
#define BITCOIN_WALLET_DB_H
Backport 11651 (#3358) * scripted-diff: Replace #include "" with #include <> (ryanofsky) -BEGIN VERIFY SCRIPT- for f in \ src/*.cpp \ src/*.h \ src/bench/*.cpp \ src/bench/*.h \ src/compat/*.cpp \ src/compat/*.h \ src/consensus/*.cpp \ src/consensus/*.h \ src/crypto/*.cpp \ src/crypto/*.h \ src/crypto/ctaes/*.h \ src/policy/*.cpp \ src/policy/*.h \ src/primitives/*.cpp \ src/primitives/*.h \ src/qt/*.cpp \ src/qt/*.h \ src/qt/test/*.cpp \ src/qt/test/*.h \ src/rpc/*.cpp \ src/rpc/*.h \ src/script/*.cpp \ src/script/*.h \ src/support/*.cpp \ src/support/*.h \ src/support/allocators/*.h \ src/test/*.cpp \ src/test/*.h \ src/wallet/*.cpp \ src/wallet/*.h \ src/wallet/test/*.cpp \ src/wallet/test/*.h \ src/zmq/*.cpp \ src/zmq/*.h do base=${f%/*}/ relbase=${base#src/} sed -i "s:#include \"\(.*\)\"\(.*\):if test -e \$base'\\1'; then echo \"#include <\"\$relbase\"\\1>\\2\"; else echo \"#include <\\1>\\2\"; fi:e" $f done -END VERIFY SCRIPT- Signed-off-by: Pasta <pasta@dashboost.org> * scripted-diff: Replace #include "" with #include <> (Dash Specific) -BEGIN VERIFY SCRIPT- for f in \ src/bls/*.cpp \ src/bls/*.h \ src/evo/*.cpp \ src/evo/*.h \ src/governance/*.cpp \ src/governance/*.h \ src/llmq/*.cpp \ src/llmq/*.h \ src/masternode/*.cpp \ src/masternode/*.h \ src/privatesend/*.cpp \ src/privatesend/*.h do base=${f%/*}/ relbase=${base#src/} sed -i "s:#include \"\(.*\)\"\(.*\):if test -e \$base'\\1'; then echo \"#include <\"\$relbase\"\\1>\\2\"; else echo \"#include <\\1>\\2\"; fi:e" $f done -END VERIFY SCRIPT- Signed-off-by: Pasta <pasta@dashboost.org> * build: Remove -I for everything but project root Remove -I from build system for everything but the project root, and built-in dependencies. Signed-off-by: Pasta <pasta@dashboost.org> # Conflicts: # src/Makefile.test.include * qt: refactor: Use absolute include paths in .ui files * qt: refactor: Changes to make include paths absolute This makes all include paths in the GUI absolute. Many changes are involved as every single source file in src/qt/ assumes to be able to use relative includes. Signed-off-by: Pasta <pasta@dashboost.org> # Conflicts: # src/qt/dash.cpp # src/qt/optionsmodel.cpp # src/qt/test/rpcnestedtests.cpp * test: refactor: Use absolute include paths for test data files * Recommend #include<> syntax in developer notes * refactor: Include obj/build.h instead of build.h * END BACKPORT #11651 Remove trailing whitespace causing travis failure * fix backport 11651 Signed-off-by: Pasta <pasta@dashboost.org> * More of 11651 * fix blockchain.cpp Signed-off-by: pasta <pasta@dashboost.org> * Add missing "qt/" in includes * Add missing "test/" in includes * Fix trailing whitespaces Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com> Co-authored-by: Russell Yanofsky <russ@yanofsky.org> Co-authored-by: MeshCollider <dobsonsa68@gmail.com> Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
2020-03-19 23:46:56 +01:00
#include <clientversion.h>
#include <fs.h>
#include <serialize.h>
#include <streams.h>
#include <sync.h>
#include <version.h>
#include <atomic>
#include <map>
#include <string>
#include <vector>
#include <db_cxx.h>
static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
static const bool DEFAULT_WALLET_PRIVDB = true;
class CDBEnv
{
private:
bool fDbEnvInit;
2012-05-22 21:51:13 +02:00
bool fMockDb;
// Don't change into fs::path, as that can result in
// shutdown problems/crashes caused by a static initialized internal pointer.
std::string strPath;
void EnvShutdown();
public:
mutable CCriticalSection cs_db;
Merge #11043: Use std::unique_ptr (C++11) where possible a357293 Use MakeUnique<Db>(...) (practicalswift) 3e09b39 Use MakeUnique<T>(...) instead of std::unique_ptr<T>(new T(...)) (practicalswift) 8617989 Add MakeUnique (substitute for C++14 std::make_unique) (practicalswift) d223bc9 Use unique_ptr for pcoinscatcher/pcoinsdbview/pcoinsTip/pblocktree (practicalswift) b45c597 Use unique_ptr for pdbCopy (Db) and fix potential memory leak (practicalswift) 29ab96d Use unique_ptr for dbenv (DbEnv) (practicalswift) f72cbf9 Use unique_ptr for pfilter (CBloomFilter) (practicalswift) 8ccf1bb Use unique_ptr for sem{Addnode,Outbound} (CSemaphore) (practicalswift) 73db063 Use unique_ptr for upnp_thread (boost::thread) (practicalswift) 0024531 Use unique_ptr for dbw (CDBWrapper) (practicalswift) fa6d122 Use unique_ptr:s for {fee,short,long}Stats (TxConfirmStats) (practicalswift) 5a6f768 Use unique_ptr for httpRPCTimerInterface (HTTPRPCTimerInterface) (practicalswift) 860e912 Use unique_ptr for pwalletMain (CWallet) (practicalswift) Pull request description: Use `std::unique_ptr` (C++11) where possible. Rationale: 1. Avoid resource leaks (specifically: forgetting to `delete` an object created using `new`) 2. Avoid undefined behaviour (specifically: double `delete`:s) **Note to reviewers:** Please let me know if I've missed any obvious `std::unique_ptr` candidates. Hopefully this PR should cover all the trivial cases. Tree-SHA512: 9fbeb47b800ab8ff4e0be9f2a22ab63c23d5c613a0c6716d9183db8d22ddbbce592fb8384a8b7874bf7375c8161efb13ca2197ad6f24b75967148037f0f7b20c
2017-11-09 21:22:08 +01:00
std::unique_ptr<DbEnv> dbenv;
2012-05-18 08:49:50 +02:00
std::map<std::string, int> mapFileUseCount;
std::map<std::string, Db*> mapDb;
CDBEnv();
~CDBEnv();
void Reset();
2012-05-22 21:51:13 +02:00
void MakeMock();
2019-09-25 12:28:11 +02:00
bool IsMock() const { return fMockDb; }
/**
* Verify that database file strFile is OK. If it is not,
* call the callback to try to recover.
* This must be called BEFORE strFile is opened.
* Returns true if strFile is OK.
*/
enum VerifyResult { VERIFY_OK,
RECOVER_OK,
RECOVER_FAIL };
Backport #8694: Basic multiwallet support (#3022) * Merge #8694: Basic multiwallet support c237bd7 wallet: Update formatting (Luke Dashjr) 9cbe8c8 wallet: Forbid -salvagewallet, -zapwallettxes, and -upgradewallet with multiple wallets (Luke Dashjr) a2a5f3f wallet: Base backup filenames on original wallet filename (Luke Dashjr) b823a4c wallet: Include actual backup filename in recovery warning message (Luke Dashjr) 84dcb45 Bugfix: wallet: Fix warningStr, errorStr argument order (Luke Dashjr) 008c360 Wallet: Move multiwallet sanity checks to CWallet::Verify, and do other checks on all wallets (Luke Dashjr) 0f08575 Wallet: Support loading multiple wallets if -wallet used more than once (Luke Dashjr) b124cf0 Wallet: Replace pwalletMain with a vector of wallet pointers (Luke Dashjr) 19b3648 CWalletDB: Store the update counter per wallet (Luke Dashjr) 74e8738 Bugfix: ForceSetArg should replace entr(ies) in mapMultiArgs, not append (Luke Dashjr) 23fb9ad wallet: Move nAccountingEntryNumber from static/global to CWallet (Luke Dashjr) 9d15d55 Bugfix: wallet: Increment "update counter" when modifying account stuff (Luke Dashjr) f28eb80 Bugfix: wallet: Increment "update counter" only after actually making the applicable db changes to avoid potential races (Luke Dashjr) Tree-SHA512: 23f5dda58477307bc07997010740f1dc729164cdddefd2f9a2c9c7a877111eb1516d3e2ad4f9b104621f0b7f17369c69fcef13d28b85cb6c01d35f09a8845f23 * pwalletMain -> vpwallets Signed-off-by: Pasta <pasta@dashboost.org> * add gArgs Signed-off-by: Pasta <pasta@dashboost.org> * continued pwalletsMain -> vpwallets Signed-off-by: Pasta <pasta@dashboost.org> * remove external pwalletMains and pwalletMain -> vpwallet Signed-off-by: Pasta <pasta@dashboost.org> * add external referance to vpwallets Signed-off-by: Pasta <pasta@dashboost.org> * more pWalletMain -> vpwallets[0] Signed-off-by: Pasta <pasta@dashboost.org> * code review Signed-off-by: Pasta <pasta@dashboost.org> * revert LOCK(cs_main) move Signed-off-by: Pasta <pasta@dashboost.org> * import wallet.h and remove extern Signed-off-by: Pasta <pasta@dashboost.org> * batch.* -> WriteIC and EraseIC Signed-off-by: Pasta <pasta@dashboost.org> * wrap wallet.h include inside of an ifdef Signed-off-by: Pasta <pasta@dashboost.org> * drop wallet.h Signed-off-by: Pasta <pasta@dashboost.org> * add dropped "!" Signed-off-by: Pasta <pasta@dashboost.org>
2019-07-11 09:50:52 +02:00
typedef bool (*recoverFunc_type)(const std::string& strFile, std::string& out_backup_filename);
VerifyResult Verify(const std::string& strFile, recoverFunc_type recoverFunc, std::string& out_backup_filename);
/**
* Salvage data from a file that Verify says is bad.
* fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation).
* Appends binary key/value pairs to vResult, returns true if successful.
* NOTE: reads the entire database into memory, so cannot be used
* for huge databases.
*/
typedef std::pair<std::vector<unsigned char>, std::vector<unsigned char> > KeyValPair;
bool Salvage(const std::string& strFile, bool fAggressive, std::vector<KeyValPair>& vResult);
bool Open(const fs::path& path);
void Close();
void Flush(bool fShutdown);
void CheckpointLSN(const std::string& strFile);
2012-05-18 08:49:50 +02:00
void CloseDb(const std::string& strFile);
DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC)
{
DbTxn* ptxn = nullptr;
int ret = dbenv->txn_begin(nullptr, &ptxn, flags);
if (!ptxn || ret != 0)
return nullptr;
return ptxn;
}
};
extern CDBEnv bitdb;
/** An instance of this class represents one database.
* For BerkeleyDB this is just a (env, strFile) tuple.
**/
class CWalletDBWrapper
{
friend class CDB;
public:
/** Create dummy DB handle */
CWalletDBWrapper() : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(nullptr)
{
}
/** Create DB handle to real database */
Backport #8694: Basic multiwallet support (#3022) * Merge #8694: Basic multiwallet support c237bd7 wallet: Update formatting (Luke Dashjr) 9cbe8c8 wallet: Forbid -salvagewallet, -zapwallettxes, and -upgradewallet with multiple wallets (Luke Dashjr) a2a5f3f wallet: Base backup filenames on original wallet filename (Luke Dashjr) b823a4c wallet: Include actual backup filename in recovery warning message (Luke Dashjr) 84dcb45 Bugfix: wallet: Fix warningStr, errorStr argument order (Luke Dashjr) 008c360 Wallet: Move multiwallet sanity checks to CWallet::Verify, and do other checks on all wallets (Luke Dashjr) 0f08575 Wallet: Support loading multiple wallets if -wallet used more than once (Luke Dashjr) b124cf0 Wallet: Replace pwalletMain with a vector of wallet pointers (Luke Dashjr) 19b3648 CWalletDB: Store the update counter per wallet (Luke Dashjr) 74e8738 Bugfix: ForceSetArg should replace entr(ies) in mapMultiArgs, not append (Luke Dashjr) 23fb9ad wallet: Move nAccountingEntryNumber from static/global to CWallet (Luke Dashjr) 9d15d55 Bugfix: wallet: Increment "update counter" when modifying account stuff (Luke Dashjr) f28eb80 Bugfix: wallet: Increment "update counter" only after actually making the applicable db changes to avoid potential races (Luke Dashjr) Tree-SHA512: 23f5dda58477307bc07997010740f1dc729164cdddefd2f9a2c9c7a877111eb1516d3e2ad4f9b104621f0b7f17369c69fcef13d28b85cb6c01d35f09a8845f23 * pwalletMain -> vpwallets Signed-off-by: Pasta <pasta@dashboost.org> * add gArgs Signed-off-by: Pasta <pasta@dashboost.org> * continued pwalletsMain -> vpwallets Signed-off-by: Pasta <pasta@dashboost.org> * remove external pwalletMains and pwalletMain -> vpwallet Signed-off-by: Pasta <pasta@dashboost.org> * add external referance to vpwallets Signed-off-by: Pasta <pasta@dashboost.org> * more pWalletMain -> vpwallets[0] Signed-off-by: Pasta <pasta@dashboost.org> * code review Signed-off-by: Pasta <pasta@dashboost.org> * revert LOCK(cs_main) move Signed-off-by: Pasta <pasta@dashboost.org> * import wallet.h and remove extern Signed-off-by: Pasta <pasta@dashboost.org> * batch.* -> WriteIC and EraseIC Signed-off-by: Pasta <pasta@dashboost.org> * wrap wallet.h include inside of an ifdef Signed-off-by: Pasta <pasta@dashboost.org> * drop wallet.h Signed-off-by: Pasta <pasta@dashboost.org> * add dropped "!" Signed-off-by: Pasta <pasta@dashboost.org>
2019-07-11 09:50:52 +02:00
CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in) :
nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(env_in), strFile(strFile_in)
{
}
/** Rewrite the entire database on disk, with the exception of key pszSkip if non-zero
*/
bool Rewrite(const char* pszSkip=nullptr);
/** Back up the entire database to a file.
*/
bool Backup(const std::string& strDest);
/** Get a name for this database, for debugging etc.
*/
std::string GetName() const { return strFile; }
/** Make sure all changes are flushed to disk.
*/
void Flush(bool shutdown);
Backport #8694: Basic multiwallet support (#3022) * Merge #8694: Basic multiwallet support c237bd7 wallet: Update formatting (Luke Dashjr) 9cbe8c8 wallet: Forbid -salvagewallet, -zapwallettxes, and -upgradewallet with multiple wallets (Luke Dashjr) a2a5f3f wallet: Base backup filenames on original wallet filename (Luke Dashjr) b823a4c wallet: Include actual backup filename in recovery warning message (Luke Dashjr) 84dcb45 Bugfix: wallet: Fix warningStr, errorStr argument order (Luke Dashjr) 008c360 Wallet: Move multiwallet sanity checks to CWallet::Verify, and do other checks on all wallets (Luke Dashjr) 0f08575 Wallet: Support loading multiple wallets if -wallet used more than once (Luke Dashjr) b124cf0 Wallet: Replace pwalletMain with a vector of wallet pointers (Luke Dashjr) 19b3648 CWalletDB: Store the update counter per wallet (Luke Dashjr) 74e8738 Bugfix: ForceSetArg should replace entr(ies) in mapMultiArgs, not append (Luke Dashjr) 23fb9ad wallet: Move nAccountingEntryNumber from static/global to CWallet (Luke Dashjr) 9d15d55 Bugfix: wallet: Increment "update counter" when modifying account stuff (Luke Dashjr) f28eb80 Bugfix: wallet: Increment "update counter" only after actually making the applicable db changes to avoid potential races (Luke Dashjr) Tree-SHA512: 23f5dda58477307bc07997010740f1dc729164cdddefd2f9a2c9c7a877111eb1516d3e2ad4f9b104621f0b7f17369c69fcef13d28b85cb6c01d35f09a8845f23 * pwalletMain -> vpwallets Signed-off-by: Pasta <pasta@dashboost.org> * add gArgs Signed-off-by: Pasta <pasta@dashboost.org> * continued pwalletsMain -> vpwallets Signed-off-by: Pasta <pasta@dashboost.org> * remove external pwalletMains and pwalletMain -> vpwallet Signed-off-by: Pasta <pasta@dashboost.org> * add external referance to vpwallets Signed-off-by: Pasta <pasta@dashboost.org> * more pWalletMain -> vpwallets[0] Signed-off-by: Pasta <pasta@dashboost.org> * code review Signed-off-by: Pasta <pasta@dashboost.org> * revert LOCK(cs_main) move Signed-off-by: Pasta <pasta@dashboost.org> * import wallet.h and remove extern Signed-off-by: Pasta <pasta@dashboost.org> * batch.* -> WriteIC and EraseIC Signed-off-by: Pasta <pasta@dashboost.org> * wrap wallet.h include inside of an ifdef Signed-off-by: Pasta <pasta@dashboost.org> * drop wallet.h Signed-off-by: Pasta <pasta@dashboost.org> * add dropped "!" Signed-off-by: Pasta <pasta@dashboost.org>
2019-07-11 09:50:52 +02:00
void IncrementUpdateCounter();
std::atomic<unsigned int> nUpdateCounter;
unsigned int nLastSeen;
unsigned int nLastFlushed;
int64_t nLastWalletUpdate;
private:
/** BerkeleyDB specific */
CDBEnv *env;
std::string strFile;
/** Return whether this database handle is a dummy for testing.
* Only to be used at a low level, application should ideally not care
* about this.
*/
bool IsDummy() { return env == nullptr; }
};
2012-03-26 16:48:23 +02:00
/** RAII class that provides access to a Berkeley database */
class CDB
{
protected:
Db* pdb;
std::string strFile;
DbTxn* activeTxn;
bool fReadOnly;
bool fFlushOnClose;
CDBEnv *env;
public:
explicit CDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool fFlushOnCloseIn=true);
~CDB() { Close(); }
CDB(const CDB&) = delete;
CDB& operator=(const CDB&) = delete;
void Flush();
void Close();
Backport #8694: Basic multiwallet support (#3022) * Merge #8694: Basic multiwallet support c237bd7 wallet: Update formatting (Luke Dashjr) 9cbe8c8 wallet: Forbid -salvagewallet, -zapwallettxes, and -upgradewallet with multiple wallets (Luke Dashjr) a2a5f3f wallet: Base backup filenames on original wallet filename (Luke Dashjr) b823a4c wallet: Include actual backup filename in recovery warning message (Luke Dashjr) 84dcb45 Bugfix: wallet: Fix warningStr, errorStr argument order (Luke Dashjr) 008c360 Wallet: Move multiwallet sanity checks to CWallet::Verify, and do other checks on all wallets (Luke Dashjr) 0f08575 Wallet: Support loading multiple wallets if -wallet used more than once (Luke Dashjr) b124cf0 Wallet: Replace pwalletMain with a vector of wallet pointers (Luke Dashjr) 19b3648 CWalletDB: Store the update counter per wallet (Luke Dashjr) 74e8738 Bugfix: ForceSetArg should replace entr(ies) in mapMultiArgs, not append (Luke Dashjr) 23fb9ad wallet: Move nAccountingEntryNumber from static/global to CWallet (Luke Dashjr) 9d15d55 Bugfix: wallet: Increment "update counter" when modifying account stuff (Luke Dashjr) f28eb80 Bugfix: wallet: Increment "update counter" only after actually making the applicable db changes to avoid potential races (Luke Dashjr) Tree-SHA512: 23f5dda58477307bc07997010740f1dc729164cdddefd2f9a2c9c7a877111eb1516d3e2ad4f9b104621f0b7f17369c69fcef13d28b85cb6c01d35f09a8845f23 * pwalletMain -> vpwallets Signed-off-by: Pasta <pasta@dashboost.org> * add gArgs Signed-off-by: Pasta <pasta@dashboost.org> * continued pwalletsMain -> vpwallets Signed-off-by: Pasta <pasta@dashboost.org> * remove external pwalletMains and pwalletMain -> vpwallet Signed-off-by: Pasta <pasta@dashboost.org> * add external referance to vpwallets Signed-off-by: Pasta <pasta@dashboost.org> * more pWalletMain -> vpwallets[0] Signed-off-by: Pasta <pasta@dashboost.org> * code review Signed-off-by: Pasta <pasta@dashboost.org> * revert LOCK(cs_main) move Signed-off-by: Pasta <pasta@dashboost.org> * import wallet.h and remove extern Signed-off-by: Pasta <pasta@dashboost.org> * batch.* -> WriteIC and EraseIC Signed-off-by: Pasta <pasta@dashboost.org> * wrap wallet.h include inside of an ifdef Signed-off-by: Pasta <pasta@dashboost.org> * drop wallet.h Signed-off-by: Pasta <pasta@dashboost.org> * add dropped "!" Signed-off-by: Pasta <pasta@dashboost.org>
2019-07-11 09:50:52 +02:00
static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename);
/* flush the wallet passively (TRY_LOCK)
ideal to be called periodically */
static bool PeriodicFlush(CWalletDBWrapper& dbw);
/* verifies the database environment */
Merge #11466: Specify custom wallet directory with -walletdir param c1e5d40 Make debugging test crash easier (MeshCollider) 8263f6a Create walletdir if datadir doesn't exist and fix tests (MeshCollider) 9587a9c Default walletdir is wallets/ if it exists (MeshCollider) d987889 Add release notes for -walletdir and wallets/ dir (MeshCollider) 80c5cbc Add test for -walletdir (MeshCollider) 0530ba0 Add -walletdir parameter to specify custom wallet dir (MeshCollider) Pull request description: Closes #11348 Adds a `-walletdir` parameter which specifies a directory to use for wallets, allowing them to be stored separately from the 'main' data directory. Creates a new `wallets/` directory in datadir if this is the first time running, and defaults to using it if it exists. Includes tests and release notes. Things which might need to be considered more: - there is no 'lock' on the wallets directory, which might be needed? - because this uses a new wallets/ directory by default, downgrading to an earlier version won't see the wallets in that directory (not a big deal though, users can just copy them up to the main dir) - jnewbery suggested putting each wallet in its own directory, which is a good idea, but out of scope for this PR IMO. EDIT: this is being done in https://github.com/bitcoin/bitcoin/pull/11687 - doc/files.md needs updating (will do soon) I also considered including a cleanup by removing caching of data directory paths and instead just initialise them once on startup (c.f. #3073), but decided it wasn't super relevant here will just complicate review. Tree-SHA512: c8ac04bfe9a810c32055f2c8b8fa0d535e56125ceb8d96f12447dd3538bf3e5ee992b60b1cd2173bf5f3fa023a9feab12c9963593bf27ed419df929bb413398d
2017-11-18 14:32:50 +01:00
static bool VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr);
/* verifies the database file */
Merge #11466: Specify custom wallet directory with -walletdir param c1e5d40 Make debugging test crash easier (MeshCollider) 8263f6a Create walletdir if datadir doesn't exist and fix tests (MeshCollider) 9587a9c Default walletdir is wallets/ if it exists (MeshCollider) d987889 Add release notes for -walletdir and wallets/ dir (MeshCollider) 80c5cbc Add test for -walletdir (MeshCollider) 0530ba0 Add -walletdir parameter to specify custom wallet dir (MeshCollider) Pull request description: Closes #11348 Adds a `-walletdir` parameter which specifies a directory to use for wallets, allowing them to be stored separately from the 'main' data directory. Creates a new `wallets/` directory in datadir if this is the first time running, and defaults to using it if it exists. Includes tests and release notes. Things which might need to be considered more: - there is no 'lock' on the wallets directory, which might be needed? - because this uses a new wallets/ directory by default, downgrading to an earlier version won't see the wallets in that directory (not a big deal though, users can just copy them up to the main dir) - jnewbery suggested putting each wallet in its own directory, which is a good idea, but out of scope for this PR IMO. EDIT: this is being done in https://github.com/bitcoin/bitcoin/pull/11687 - doc/files.md needs updating (will do soon) I also considered including a cleanup by removing caching of data directory paths and instead just initialise them once on startup (c.f. #3073), but decided it wasn't super relevant here will just complicate review. Tree-SHA512: c8ac04bfe9a810c32055f2c8b8fa0d535e56125ceb8d96f12447dd3538bf3e5ee992b60b1cd2173bf5f3fa023a9feab12c9963593bf27ed419df929bb413398d
2017-11-18 14:32:50 +01:00
static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc);
public:
template <typename K, typename T>
bool Read(const K& key, T& value)
{
if (!pdb)
return false;
// Key
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
Dbt datKey(ssKey.data(), ssKey.size());
// Read
Dbt datValue;
datValue.set_flags(DB_DBT_MALLOC);
int ret = pdb->get(activeTxn, &datKey, &datValue, 0);
memory_cleanse(datKey.get_data(), datKey.get_size());
bool success = false;
if (datValue.get_data() != nullptr) {
// Unserialize value
try {
CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
ssValue >> value;
success = true;
} catch (const std::exception&) {
// In this case success remains 'false'
}
// Clear and free memory
memory_cleanse(datValue.get_data(), datValue.get_size());
free(datValue.get_data());
}
return ret == 0 && success;
}
template <typename K, typename T>
bool Write(const K& key, const T& value, bool fOverwrite = true)
{
if (!pdb)
return true;
if (fReadOnly)
assert(!"Write called on database in read-only mode");
// Key
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
Dbt datKey(ssKey.data(), ssKey.size());
// Value
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
ssValue.reserve(10000);
ssValue << value;
Dbt datValue(ssValue.data(), ssValue.size());
// Write
int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
// Clear memory in case it was a private key
memory_cleanse(datKey.get_data(), datKey.get_size());
memory_cleanse(datValue.get_data(), datValue.get_size());
return (ret == 0);
}
template <typename K>
bool Erase(const K& key)
{
if (!pdb)
return false;
if (fReadOnly)
assert(!"Erase called on database in read-only mode");
// Key
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
Dbt datKey(ssKey.data(), ssKey.size());
// Erase
int ret = pdb->del(activeTxn, &datKey, 0);
// Clear memory
memory_cleanse(datKey.get_data(), datKey.get_size());
return (ret == 0 || ret == DB_NOTFOUND);
}
template <typename K>
bool Exists(const K& key)
{
if (!pdb)
return false;
// Key
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
Dbt datKey(ssKey.data(), ssKey.size());
// Exists
int ret = pdb->exists(activeTxn, &datKey, 0);
// Clear memory
memory_cleanse(datKey.get_data(), datKey.get_size());
return (ret == 0);
}
Dbc* GetCursor()
{
if (!pdb)
return nullptr;
Dbc* pcursor = nullptr;
int ret = pdb->cursor(nullptr, &pcursor, 0);
if (ret != 0)
return nullptr;
return pcursor;
}
int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, bool setRange = false)
{
// Read at cursor
Dbt datKey;
unsigned int fFlags = DB_NEXT;
if (setRange) {
datKey.set_data(ssKey.data());
datKey.set_size(ssKey.size());
fFlags = DB_SET_RANGE;
}
Dbt datValue;
datKey.set_flags(DB_DBT_MALLOC);
datValue.set_flags(DB_DBT_MALLOC);
int ret = pcursor->get(&datKey, &datValue, fFlags);
if (ret != 0)
return ret;
else if (datKey.get_data() == nullptr || datValue.get_data() == nullptr)
return 99999;
// Convert to streams
ssKey.SetType(SER_DISK);
ssKey.clear();
ssKey.write((char*)datKey.get_data(), datKey.get_size());
ssValue.SetType(SER_DISK);
ssValue.clear();
ssValue.write((char*)datValue.get_data(), datValue.get_size());
// Clear and free memory
memory_cleanse(datKey.get_data(), datKey.get_size());
memory_cleanse(datValue.get_data(), datValue.get_size());
free(datKey.get_data());
free(datValue.get_data());
return 0;
}
public:
bool TxnBegin()
{
if (!pdb || activeTxn)
return false;
DbTxn* ptxn = bitdb.TxnBegin();
if (!ptxn)
return false;
activeTxn = ptxn;
return true;
}
bool TxnCommit()
{
if (!pdb || !activeTxn)
return false;
int ret = activeTxn->commit(0);
activeTxn = nullptr;
return (ret == 0);
}
bool TxnAbort()
{
if (!pdb || !activeTxn)
return false;
int ret = activeTxn->abort();
activeTxn = nullptr;
return (ret == 0);
}
bool ReadVersion(int& nVersion)
{
nVersion = 0;
return Read(std::string("version"), nVersion);
}
bool WriteVersion(int nVersion)
{
return Write(std::string("version"), nVersion);
}
2011-11-10 21:29:23 +01:00
bool static Rewrite(CWalletDBWrapper& dbw, const char* pszSkip = nullptr);
};
#endif // BITCOIN_WALLET_DB_H