mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
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
This commit is contained in:
commit
177433ad22
12 changed files with 197 additions and 166 deletions
21
src/init.cpp
21
src/init.cpp
|
@ -197,8 +197,9 @@ void Shutdown()
|
||||||
StopRPC();
|
StopRPC();
|
||||||
StopHTTPServer();
|
StopHTTPServer();
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
if (pwalletMain)
|
for (CWalletRef pwallet : vpwallets) {
|
||||||
pwalletMain->Flush(false);
|
pwallet->Flush(false);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
MapPort(false);
|
MapPort(false);
|
||||||
UnregisterValidationInterface(peerLogic.get());
|
UnregisterValidationInterface(peerLogic.get());
|
||||||
|
@ -238,8 +239,9 @@ void Shutdown()
|
||||||
pblocktree = NULL;
|
pblocktree = NULL;
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
if (pwalletMain)
|
for (CWalletRef pwallet : vpwallets) {
|
||||||
pwalletMain->Flush(true);
|
pwallet->Flush(true);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLE_ZMQ
|
#if ENABLE_ZMQ
|
||||||
|
@ -259,8 +261,10 @@ void Shutdown()
|
||||||
#endif
|
#endif
|
||||||
UnregisterAllValidationInterfaces();
|
UnregisterAllValidationInterfaces();
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
delete pwalletMain;
|
for (CWalletRef pwallet : vpwallets) {
|
||||||
pwalletMain = NULL;
|
delete pwallet;
|
||||||
|
}
|
||||||
|
vpwallets.clear();
|
||||||
#endif
|
#endif
|
||||||
globalVerifyHandle.reset();
|
globalVerifyHandle.reset();
|
||||||
ECC_Stop();
|
ECC_Stop();
|
||||||
|
@ -1672,8 +1676,9 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
uiInterface.InitMessage(_("Done loading"));
|
uiInterface.InitMessage(_("Done loading"));
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
if (pwalletMain)
|
for (CWalletRef pwallet : vpwallets) {
|
||||||
pwalletMain->postInitProcess(scheduler);
|
pwallet->postInitProcess(scheduler);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return !fRequestShutdown;
|
return !fRequestShutdown;
|
||||||
|
|
|
@ -474,9 +474,10 @@ void BitcoinApplication::initializeResult(bool success)
|
||||||
window->setClientModel(clientModel);
|
window->setClientModel(clientModel);
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
if(pwalletMain)
|
// TODO: Expose secondary wallets
|
||||||
|
if (!vpwallets.empty())
|
||||||
{
|
{
|
||||||
walletModel = new WalletModel(platformStyle, pwalletMain, optionsModel);
|
walletModel = new WalletModel(platformStyle, vpwallets[0], optionsModel);
|
||||||
|
|
||||||
window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel);
|
window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel);
|
||||||
window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET);
|
window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET);
|
||||||
|
|
|
@ -474,6 +474,7 @@ void ArgsManager::ForceSetArg(const std::string& strArg, const std::string& strV
|
||||||
{
|
{
|
||||||
LOCK(cs_args);
|
LOCK(cs_args);
|
||||||
mapArgs[strArg] = strValue;
|
mapArgs[strArg] = strValue;
|
||||||
|
mapMultiArgs[strArg].clear();
|
||||||
mapMultiArgs[strArg].push_back(strValue);
|
mapMultiArgs[strArg].push_back(strValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,7 @@ void CDBEnv::MakeMock()
|
||||||
fMockDb = true;
|
fMockDb = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, bool (*recoverFunc)(const std::string& strFile))
|
CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, recoverFunc_type recoverFunc, std::string& out_backup_filename)
|
||||||
{
|
{
|
||||||
LOCK(cs_db);
|
LOCK(cs_db);
|
||||||
assert(mapFileUseCount.count(strFile) == 0);
|
assert(mapFileUseCount.count(strFile) == 0);
|
||||||
|
@ -155,21 +155,21 @@ CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, bool (*recoverFu
|
||||||
return RECOVER_FAIL;
|
return RECOVER_FAIL;
|
||||||
|
|
||||||
// Try to recover:
|
// Try to recover:
|
||||||
bool fRecovered = (*recoverFunc)(strFile);
|
bool fRecovered = (*recoverFunc)(strFile, out_backup_filename);
|
||||||
return (fRecovered ? RECOVER_OK : RECOVER_FAIL);
|
return (fRecovered ? RECOVER_OK : RECOVER_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue))
|
bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& newFilename)
|
||||||
{
|
{
|
||||||
// Recovery procedure:
|
// Recovery procedure:
|
||||||
// move wallet file to wallet.timestamp.bak
|
// move wallet file to walletfilename.timestamp.bak
|
||||||
// Call Salvage with fAggressive=true to
|
// Call Salvage with fAggressive=true to
|
||||||
// get as much data as possible.
|
// get as much data as possible.
|
||||||
// Rewrite salvaged data to fresh wallet file
|
// Rewrite salvaged data to fresh wallet file
|
||||||
// Set -rescan so any missing transactions will be
|
// Set -rescan so any missing transactions will be
|
||||||
// found.
|
// found.
|
||||||
int64_t now = GetTime();
|
int64_t now = GetTime();
|
||||||
std::string newFilename = strprintf("wallet.%d.bak", now);
|
newFilename = strprintf("%s.%d.bak", filename, now);
|
||||||
|
|
||||||
int result = bitdb.dbenv->dbrename(NULL, filename.c_str(), NULL,
|
int result = bitdb.dbenv->dbrename(NULL, filename.c_str(), NULL,
|
||||||
newFilename.c_str(), DB_AUTO_COMMIT);
|
newFilename.c_str(), DB_AUTO_COMMIT);
|
||||||
|
@ -259,18 +259,19 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataD
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile))
|
bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc)
|
||||||
{
|
{
|
||||||
if (fs::exists(dataDir / walletFile))
|
if (fs::exists(dataDir / walletFile))
|
||||||
{
|
{
|
||||||
CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc);
|
std::string backup_filename;
|
||||||
|
CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc, backup_filename);
|
||||||
if (r == CDBEnv::RECOVER_OK)
|
if (r == CDBEnv::RECOVER_OK)
|
||||||
{
|
{
|
||||||
warningStr = strprintf(_("Warning: Wallet file corrupt, data salvaged!"
|
warningStr = strprintf(_("Warning: Wallet file corrupt, data salvaged!"
|
||||||
" Original %s saved as %s in %s; if"
|
" Original %s saved as %s in %s; if"
|
||||||
" your balance or transactions are incorrect you should"
|
" your balance or transactions are incorrect you should"
|
||||||
" restore from a backup."),
|
" restore from a backup."),
|
||||||
walletFile, "wallet.{timestamp}.bak", dataDir);
|
walletFile, backup_filename, dataDir);
|
||||||
}
|
}
|
||||||
if (r == CDBEnv::RECOVER_FAIL)
|
if (r == CDBEnv::RECOVER_FAIL)
|
||||||
{
|
{
|
||||||
|
@ -432,6 +433,11 @@ void CDB::Flush()
|
||||||
env->dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0, nMinutes, 0);
|
env->dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0, nMinutes, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWalletDBWrapper::IncrementUpdateCounter()
|
||||||
|
{
|
||||||
|
++nUpdateCounter;
|
||||||
|
}
|
||||||
|
|
||||||
void CDB::Close()
|
void CDB::Close()
|
||||||
{
|
{
|
||||||
if (!pdb)
|
if (!pdb)
|
||||||
|
|
|
@ -55,7 +55,8 @@ public:
|
||||||
enum VerifyResult { VERIFY_OK,
|
enum VerifyResult { VERIFY_OK,
|
||||||
RECOVER_OK,
|
RECOVER_OK,
|
||||||
RECOVER_FAIL };
|
RECOVER_FAIL };
|
||||||
VerifyResult Verify(const std::string& strFile, bool (*recoverFunc)(const std::string& strFile));
|
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.
|
* Salvage data from a file that Verify says is bad.
|
||||||
* fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation).
|
* fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation).
|
||||||
|
@ -93,13 +94,13 @@ class CWalletDBWrapper
|
||||||
friend class CDB;
|
friend class CDB;
|
||||||
public:
|
public:
|
||||||
/** Create dummy DB handle */
|
/** Create dummy DB handle */
|
||||||
CWalletDBWrapper(): env(nullptr)
|
CWalletDBWrapper() : nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create DB handle to real database */
|
/** Create DB handle to real database */
|
||||||
CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in) :
|
CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in) :
|
||||||
env(env_in), strFile(strFile_in)
|
nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(env_in), strFile(strFile_in)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +120,13 @@ public:
|
||||||
*/
|
*/
|
||||||
void Flush(bool shutdown);
|
void Flush(bool shutdown);
|
||||||
|
|
||||||
|
void IncrementUpdateCounter();
|
||||||
|
|
||||||
|
std::atomic<unsigned int> nUpdateCounter;
|
||||||
|
unsigned int nLastSeen;
|
||||||
|
unsigned int nLastFlushed;
|
||||||
|
int64_t nLastWalletUpdate;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** BerkeleyDB specific */
|
/** BerkeleyDB specific */
|
||||||
CDBEnv *env;
|
CDBEnv *env;
|
||||||
|
@ -149,7 +157,7 @@ public:
|
||||||
|
|
||||||
void Flush();
|
void Flush();
|
||||||
void Close();
|
void Close();
|
||||||
static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue));
|
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)
|
/* flush the wallet passively (TRY_LOCK)
|
||||||
ideal to be called periodically */
|
ideal to be called periodically */
|
||||||
|
@ -157,7 +165,7 @@ public:
|
||||||
/* verifies the database environment */
|
/* verifies the database environment */
|
||||||
static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr);
|
static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr);
|
||||||
/* verifies the database file */
|
/* verifies the database file */
|
||||||
static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile));
|
static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CDB(const CDB&);
|
CDB(const CDB&);
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
|
|
||||||
CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
|
CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
return pwalletMain;
|
// TODO: Some way to access secondary wallets
|
||||||
|
return vpwallets.empty() ? nullptr : vpwallets[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string HelpRequiringPassphrase(CWallet * const pwallet)
|
std::string HelpRequiringPassphrase(CWallet * const pwallet)
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include "wallet/db.h"
|
#include "wallet/db.h"
|
||||||
#include "wallet/wallet.h"
|
#include "wallet/wallet.h"
|
||||||
|
|
||||||
|
CWallet *pwalletMain;
|
||||||
|
|
||||||
WalletTestingSetup::WalletTestingSetup(const std::string& chainName):
|
WalletTestingSetup::WalletTestingSetup(const std::string& chainName):
|
||||||
TestingSetup(chainName)
|
TestingSetup(chainName)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|
||||||
|
extern CWallet* pwalletMain;
|
||||||
|
|
||||||
extern UniValue importmulti(const JSONRPCRequest& request);
|
extern UniValue importmulti(const JSONRPCRequest& request);
|
||||||
extern UniValue dumpwallet(const JSONRPCRequest& request);
|
extern UniValue dumpwallet(const JSONRPCRequest& request);
|
||||||
extern UniValue importwallet(const JSONRPCRequest& request);
|
extern UniValue importwallet(const JSONRPCRequest& request);
|
||||||
|
@ -401,8 +403,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
|
||||||
// after.
|
// after.
|
||||||
{
|
{
|
||||||
CWallet wallet;
|
CWallet wallet;
|
||||||
CWallet *backup = ::pwalletMain;
|
vpwallets.insert(vpwallets.begin(), &wallet);
|
||||||
::pwalletMain = &wallet;
|
|
||||||
UniValue keys;
|
UniValue keys;
|
||||||
keys.setArray();
|
keys.setArray();
|
||||||
UniValue key;
|
UniValue key;
|
||||||
|
@ -433,7 +434,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
|
||||||
"downloading and rescanning the relevant blocks (see -reindex and -rescan "
|
"downloading and rescanning the relevant blocks (see -reindex and -rescan "
|
||||||
"options).\"}},{\"success\":true}]",
|
"options).\"}},{\"success\":true}]",
|
||||||
0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW));
|
0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW));
|
||||||
::pwalletMain = backup;
|
vpwallets.erase(vpwallets.begin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,7 +444,6 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
|
||||||
// than or equal to key birthday.
|
// than or equal to key birthday.
|
||||||
BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||||
{
|
{
|
||||||
CWallet *pwalletMainBackup = ::pwalletMain;
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
// Create two blocks with same timestamp to verify that importwallet rescan
|
// Create two blocks with same timestamp to verify that importwallet rescan
|
||||||
|
@ -469,7 +469,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||||
JSONRPCRequest request;
|
JSONRPCRequest request;
|
||||||
request.params.setArray();
|
request.params.setArray();
|
||||||
request.params.push_back("wallet.backup");
|
request.params.push_back("wallet.backup");
|
||||||
::pwalletMain = &wallet;
|
vpwallets.insert(vpwallets.begin(), &wallet);
|
||||||
::dumpwallet(request);
|
::dumpwallet(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,7 +481,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||||
JSONRPCRequest request;
|
JSONRPCRequest request;
|
||||||
request.params.setArray();
|
request.params.setArray();
|
||||||
request.params.push_back("wallet.backup");
|
request.params.push_back("wallet.backup");
|
||||||
::pwalletMain = &wallet;
|
vpwallets[0] = &wallet;
|
||||||
::importwallet(request);
|
::importwallet(request);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3);
|
BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3);
|
||||||
|
@ -494,7 +494,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||||
}
|
}
|
||||||
|
|
||||||
SetMockTime(0);
|
SetMockTime(0);
|
||||||
::pwalletMain = pwalletMainBackup;
|
vpwallets.erase(vpwallets.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that GetImmatureCredit() returns a newly calculated value instead of
|
// Check that GetImmatureCredit() returns a newly calculated value instead of
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
CWallet* pwalletMain = NULL;
|
std::vector<CWalletRef> vpwallets;
|
||||||
/** Transaction fee set by the user */
|
/** Transaction fee set by the user */
|
||||||
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
|
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
|
||||||
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
|
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
|
||||||
|
@ -440,30 +440,40 @@ bool CWallet::Verify()
|
||||||
if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET))
|
if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
uiInterface.InitMessage(_("Verifying wallet..."));
|
uiInterface.InitMessage(_("Verifying wallet(s)..."));
|
||||||
std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
|
|
||||||
|
for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
|
||||||
|
if (boost::filesystem::path(walletFile).filename() != walletFile) {
|
||||||
|
return InitError(_("-wallet parameter must only specify a filename (not a path)"));
|
||||||
|
} else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) {
|
||||||
|
return InitError(_("Invalid characters in -wallet filename"));
|
||||||
|
}
|
||||||
|
|
||||||
std::string strError;
|
std::string strError;
|
||||||
if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError))
|
if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) {
|
||||||
return InitError(strError);
|
return InitError(strError);
|
||||||
|
}
|
||||||
|
|
||||||
if (GetBoolArg("-salvagewallet", false))
|
if (GetBoolArg("-salvagewallet", false)) {
|
||||||
{
|
|
||||||
// Recover readable keypairs:
|
// Recover readable keypairs:
|
||||||
CWallet dummyWallet;
|
CWallet dummyWallet;
|
||||||
if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter))
|
std::string backup_filename;
|
||||||
|
if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter, backup_filename)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string strWarning;
|
std::string strWarning;
|
||||||
bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError);
|
bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError);
|
||||||
if (!strWarning.empty())
|
if (!strWarning.empty()) {
|
||||||
InitWarning(strWarning);
|
InitWarning(strWarning);
|
||||||
if (!dbV)
|
}
|
||||||
{
|
if (!dbV) {
|
||||||
InitError(strError);
|
InitError(strError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2867,8 +2877,9 @@ bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry)
|
||||||
|
|
||||||
bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB *pwalletdb)
|
bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB *pwalletdb)
|
||||||
{
|
{
|
||||||
if (!pwalletdb->WriteAccountingEntry_Backend(acentry))
|
if (!pwalletdb->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
laccentries.push_back(acentry);
|
laccentries.push_back(acentry);
|
||||||
CAccountingEntry & entry = laccentries.back();
|
CAccountingEntry & entry = laccentries.back();
|
||||||
|
@ -3880,7 +3891,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
|
||||||
walletInstance->ScanForWalletTransactions(pindexRescan, true);
|
walletInstance->ScanForWalletTransactions(pindexRescan, true);
|
||||||
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
|
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
|
||||||
walletInstance->SetBestChain(chainActive.GetLocator());
|
walletInstance->SetBestChain(chainActive.GetLocator());
|
||||||
CWalletDB::IncrementUpdateCounter();
|
walletInstance->dbw->IncrementUpdateCounter();
|
||||||
|
|
||||||
// Restore wallet transaction metadata after -zapwallettxes=1
|
// Restore wallet transaction metadata after -zapwallettxes=1
|
||||||
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
|
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
|
||||||
|
@ -3922,24 +3933,17 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
|
||||||
bool CWallet::InitLoadWallet()
|
bool CWallet::InitLoadWallet()
|
||||||
{
|
{
|
||||||
if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
|
if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
|
||||||
pwalletMain = NULL;
|
|
||||||
LogPrintf("Wallet disabled!\n");
|
LogPrintf("Wallet disabled!\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
|
for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
|
||||||
|
|
||||||
if (boost::filesystem::path(walletFile).filename() != walletFile) {
|
|
||||||
return InitError(_("-wallet parameter must only specify a filename (not a path)"));
|
|
||||||
} else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) {
|
|
||||||
return InitError(_("Invalid characters in -wallet filename"));
|
|
||||||
}
|
|
||||||
|
|
||||||
CWallet * const pwallet = CreateWalletFromFile(walletFile);
|
CWallet * const pwallet = CreateWalletFromFile(walletFile);
|
||||||
if (!pwallet) {
|
if (!pwallet) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pwalletMain = pwallet;
|
vpwallets.push_back(pwallet);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3960,6 +3964,9 @@ void CWallet::postInitProcess(CScheduler& scheduler)
|
||||||
|
|
||||||
bool CWallet::ParameterInteraction()
|
bool CWallet::ParameterInteraction()
|
||||||
{
|
{
|
||||||
|
SoftSetArg("-wallet", DEFAULT_WALLET_DAT);
|
||||||
|
const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;
|
||||||
|
|
||||||
if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET))
|
if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -3968,15 +3975,27 @@ bool CWallet::ParameterInteraction()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetBoolArg("-salvagewallet", false) && SoftSetBoolArg("-rescan", true)) {
|
if (GetBoolArg("-salvagewallet", false) && SoftSetBoolArg("-rescan", true)) {
|
||||||
|
if (is_multiwallet) {
|
||||||
|
return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet"));
|
||||||
|
}
|
||||||
// Rewrite just private keys: rescan to find transactions
|
// Rewrite just private keys: rescan to find transactions
|
||||||
LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__);
|
LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -zapwallettx implies a rescan
|
// -zapwallettx implies a rescan
|
||||||
if (GetBoolArg("-zapwallettxes", false) && SoftSetBoolArg("-rescan", true)) {
|
if (GetBoolArg("-zapwallettxes", false) && SoftSetBoolArg("-rescan", true)) {
|
||||||
|
if (is_multiwallet) {
|
||||||
|
return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes"));
|
||||||
|
}
|
||||||
LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n", __func__);
|
LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_multiwallet) {
|
||||||
|
if (GetBoolArg("-upgradewallet", false)) {
|
||||||
|
return InitError(strprintf("%s is only allowed with a single wallet file", "-upgradewallet"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (GetBoolArg("-sysperms", false))
|
if (GetBoolArg("-sysperms", false))
|
||||||
return InitError("-sysperms is not allowed in combination with enabled wallet functionality");
|
return InitError("-sysperms is not allowed in combination with enabled wallet functionality");
|
||||||
if (GetArg("-prune", 0) && GetBoolArg("-rescan", false))
|
if (GetArg("-prune", 0) && GetBoolArg("-rescan", false))
|
||||||
|
|
|
@ -29,7 +29,8 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
extern CWallet* pwalletMain;
|
typedef CWallet* CWalletRef;
|
||||||
|
extern std::vector<CWalletRef> vpwallets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings
|
* Settings
|
||||||
|
@ -782,6 +783,7 @@ public:
|
||||||
nMasterKeyMaxID = 0;
|
nMasterKeyMaxID = 0;
|
||||||
pwalletdbEncryption = NULL;
|
pwalletdbEncryption = NULL;
|
||||||
nOrderPosNext = 0;
|
nOrderPosNext = 0;
|
||||||
|
nAccountingEntryNumber = 0;
|
||||||
nNextResend = 0;
|
nNextResend = 0;
|
||||||
nLastResend = 0;
|
nLastResend = 0;
|
||||||
nTimeFirstKey = 0;
|
nTimeFirstKey = 0;
|
||||||
|
@ -799,6 +801,7 @@ public:
|
||||||
TxItems wtxOrdered;
|
TxItems wtxOrdered;
|
||||||
|
|
||||||
int64_t nOrderPosNext;
|
int64_t nOrderPosNext;
|
||||||
|
uint64_t nAccountingEntryNumber;
|
||||||
std::map<uint256, int> mapRequestCount;
|
std::map<uint256, int> mapRequestCount;
|
||||||
|
|
||||||
std::map<CTxDestination, CAddressBookData> mapAddressBook;
|
std::map<CTxDestination, CAddressBookData> mapAddressBook;
|
||||||
|
|
|
@ -21,59 +21,47 @@
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
static uint64_t nAccountingEntryNumber = 0;
|
|
||||||
|
|
||||||
static std::atomic<unsigned int> nWalletDBUpdateCounter;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// CWalletDB
|
// CWalletDB
|
||||||
//
|
//
|
||||||
|
|
||||||
bool CWalletDB::WriteName(const std::string& strAddress, const std::string& strName)
|
bool CWalletDB::WriteName(const std::string& strAddress, const std::string& strName)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return WriteIC(std::make_pair(std::string("name"), strAddress), strName);
|
||||||
return batch.Write(std::make_pair(std::string("name"), strAddress), strName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::EraseName(const std::string& strAddress)
|
bool CWalletDB::EraseName(const std::string& strAddress)
|
||||||
{
|
{
|
||||||
// This should only be used for sending addresses, never for receiving addresses,
|
// 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.
|
// receiving addresses must always have an address book entry if they're not change return.
|
||||||
nWalletDBUpdateCounter++;
|
return EraseIC(std::make_pair(std::string("name"), strAddress));
|
||||||
return batch.Erase(std::make_pair(std::string("name"), strAddress));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WritePurpose(const std::string& strAddress, const std::string& strPurpose)
|
bool CWalletDB::WritePurpose(const std::string& strAddress, const std::string& strPurpose)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return WriteIC(std::make_pair(std::string("purpose"), strAddress), strPurpose);
|
||||||
return batch.Write(std::make_pair(std::string("purpose"), strAddress), strPurpose);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::ErasePurpose(const std::string& strPurpose)
|
bool CWalletDB::ErasePurpose(const std::string& strPurpose)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return EraseIC(std::make_pair(std::string("purpose"), strPurpose));
|
||||||
return batch.Erase(std::make_pair(std::string("purpose"), strPurpose));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteTx(const CWalletTx& wtx)
|
bool CWalletDB::WriteTx(const CWalletTx& wtx)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return WriteIC(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
|
||||||
return batch.Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::EraseTx(uint256 hash)
|
bool CWalletDB::EraseTx(uint256 hash)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return EraseIC(std::make_pair(std::string("tx"), hash));
|
||||||
return batch.Erase(std::make_pair(std::string("tx"), hash));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
|
bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) {
|
||||||
|
|
||||||
if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey),
|
|
||||||
keyMeta, false))
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// hash pubkey/privkey to accelerate wallet load
|
// hash pubkey/privkey to accelerate wallet load
|
||||||
std::vector<unsigned char> vchKey;
|
std::vector<unsigned char> vchKey;
|
||||||
|
@ -81,7 +69,7 @@ bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, c
|
||||||
vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
|
vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
|
||||||
vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
|
vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
|
||||||
|
|
||||||
return batch.Write(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
|
return WriteIC(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
|
bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
|
||||||
|
@ -89,55 +77,53 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
|
||||||
const CKeyMetadata &keyMeta)
|
const CKeyMetadata &keyMeta)
|
||||||
{
|
{
|
||||||
const bool fEraseUnencryptedKey = true;
|
const bool fEraseUnencryptedKey = true;
|
||||||
nWalletDBUpdateCounter++;
|
|
||||||
|
|
||||||
if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey),
|
if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) {
|
||||||
keyMeta))
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!batch.Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false))
|
if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (fEraseUnencryptedKey)
|
if (fEraseUnencryptedKey)
|
||||||
{
|
{
|
||||||
batch.Erase(std::make_pair(std::string("key"), vchPubKey));
|
EraseIC(std::make_pair(std::string("key"), vchPubKey));
|
||||||
batch.Erase(std::make_pair(std::string("wkey"), vchPubKey));
|
EraseIC(std::make_pair(std::string("wkey"), vchPubKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
|
bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return WriteIC(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
|
||||||
return batch.Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
|
bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return WriteIC(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
|
||||||
return batch.Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta)
|
bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
if (!WriteIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) {
|
||||||
if (!batch.Write(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta))
|
|
||||||
return false;
|
return false;
|
||||||
return batch.Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1');
|
}
|
||||||
|
return WriteIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::EraseWatchOnly(const CScript &dest)
|
bool CWalletDB::EraseWatchOnly(const CScript &dest)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
if (!EraseIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) {
|
||||||
if (!batch.Erase(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest))))
|
|
||||||
return false;
|
return false;
|
||||||
return batch.Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)));
|
}
|
||||||
|
return EraseIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
|
bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
WriteIC(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
|
||||||
batch.Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
|
return WriteIC(std::string("bestblock_nomerkle"), locator);
|
||||||
return batch.Write(std::string("bestblock_nomerkle"), locator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
|
bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
|
||||||
|
@ -148,14 +134,12 @@ bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
|
||||||
|
|
||||||
bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
|
bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return WriteIC(std::string("orderposnext"), nOrderPosNext);
|
||||||
return batch.Write(std::string("orderposnext"), nOrderPosNext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey)
|
bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return WriteIC(std::string("defaultkey"), vchPubKey);
|
||||||
return batch.Write(std::string("defaultkey"), vchPubKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)
|
bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)
|
||||||
|
@ -165,19 +149,17 @@ bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)
|
||||||
|
|
||||||
bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
|
bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return WriteIC(std::make_pair(std::string("pool"), nPool), keypool);
|
||||||
return batch.Write(std::make_pair(std::string("pool"), nPool), keypool);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::ErasePool(int64_t nPool)
|
bool CWalletDB::ErasePool(int64_t nPool)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return EraseIC(std::make_pair(std::string("pool"), nPool));
|
||||||
return batch.Erase(std::make_pair(std::string("pool"), nPool));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteMinVersion(int nVersion)
|
bool CWalletDB::WriteMinVersion(int nVersion)
|
||||||
{
|
{
|
||||||
return batch.Write(std::string("minversion"), nVersion);
|
return WriteIC(std::string("minversion"), nVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account)
|
bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account)
|
||||||
|
@ -188,17 +170,12 @@ bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account)
|
||||||
|
|
||||||
bool CWalletDB::WriteAccount(const std::string& strAccount, const CAccount& account)
|
bool CWalletDB::WriteAccount(const std::string& strAccount, const CAccount& account)
|
||||||
{
|
{
|
||||||
return batch.Write(std::make_pair(std::string("acc"), strAccount), account);
|
return WriteIC(std::make_pair(std::string("acc"), strAccount), account);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry)
|
bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry)
|
||||||
{
|
{
|
||||||
return batch.Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
|
return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
|
||||||
}
|
|
||||||
|
|
||||||
bool CWalletDB::WriteAccountingEntry_Backend(const CAccountingEntry& acentry)
|
|
||||||
{
|
|
||||||
return WriteAccountingEntry(++nAccountingEntryNumber, acentry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CAmount CWalletDB::GetAccountCreditDebit(const std::string& strAccount)
|
CAmount CWalletDB::GetAccountCreditDebit(const std::string& strAccount)
|
||||||
|
@ -337,8 +314,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||||
ssKey >> strAccount;
|
ssKey >> strAccount;
|
||||||
uint64_t nNumber;
|
uint64_t nNumber;
|
||||||
ssKey >> nNumber;
|
ssKey >> nNumber;
|
||||||
if (nNumber > nAccountingEntryNumber)
|
if (nNumber > pwallet->nAccountingEntryNumber) {
|
||||||
nAccountingEntryNumber = nNumber;
|
pwallet->nAccountingEntryNumber = nNumber;
|
||||||
|
}
|
||||||
|
|
||||||
if (!wss.fAnyUnordered)
|
if (!wss.fAnyUnordered)
|
||||||
{
|
{
|
||||||
|
@ -784,38 +762,39 @@ void MaybeCompactWalletDB()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int nLastSeen = CWalletDB::GetUpdateCounter();
|
for (CWalletRef pwallet : vpwallets) {
|
||||||
static unsigned int nLastFlushed = CWalletDB::GetUpdateCounter();
|
CWalletDBWrapper& dbh = pwallet->GetDBHandle();
|
||||||
static int64_t nLastWalletUpdate = GetTime();
|
|
||||||
|
|
||||||
if (nLastSeen != CWalletDB::GetUpdateCounter())
|
unsigned int nUpdateCounter = dbh.nUpdateCounter;
|
||||||
{
|
|
||||||
nLastSeen = CWalletDB::GetUpdateCounter();
|
if (dbh.nLastSeen != nUpdateCounter) {
|
||||||
nLastWalletUpdate = GetTime();
|
dbh.nLastSeen = nUpdateCounter;
|
||||||
|
dbh.nLastWalletUpdate = GetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nLastFlushed != CWalletDB::GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2)
|
if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) {
|
||||||
{
|
if (CDB::PeriodicFlush(dbh)) {
|
||||||
if (CDB::PeriodicFlush(pwalletMain->GetDBHandle())) {
|
dbh.nLastFlushed = nUpdateCounter;
|
||||||
nLastFlushed = CWalletDB::GetUpdateCounter();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fOneThread = false;
|
fOneThread = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Try to (very carefully!) recover wallet file if there is a problem.
|
// Try to (very carefully!) recover wallet file if there is a problem.
|
||||||
//
|
//
|
||||||
bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue))
|
bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename)
|
||||||
{
|
{
|
||||||
return CDB::Recover(filename, callbackDataIn, recoverKVcallback);
|
return CDB::Recover(filename, callbackDataIn, recoverKVcallback, out_backup_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::Recover(const std::string& filename)
|
bool CWalletDB::Recover(const std::string& filename, std::string& out_backup_filename)
|
||||||
{
|
{
|
||||||
// recover without a key filter callback
|
// recover without a key filter callback
|
||||||
// results in recovering all record types
|
// results in recovering all record types
|
||||||
return CWalletDB::Recover(filename, NULL, NULL);
|
return CWalletDB::Recover(filename, NULL, NULL, out_backup_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue)
|
bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue)
|
||||||
|
@ -848,36 +827,23 @@ bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path&
|
||||||
|
|
||||||
bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr)
|
bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr)
|
||||||
{
|
{
|
||||||
return CDB::VerifyDatabaseFile(walletFile, dataDir, errorStr, warningStr, CWalletDB::Recover);
|
return CDB::VerifyDatabaseFile(walletFile, dataDir, warningStr, errorStr, CWalletDB::Recover);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
|
bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
|
||||||
return batch.Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
|
bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
|
||||||
return batch.Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CWalletDB::WriteHDChain(const CHDChain& chain)
|
bool CWalletDB::WriteHDChain(const CHDChain& chain)
|
||||||
{
|
{
|
||||||
nWalletDBUpdateCounter++;
|
return WriteIC(std::string("hdchain"), chain);
|
||||||
return batch.Write(std::string("hdchain"), chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWalletDB::IncrementUpdateCounter()
|
|
||||||
{
|
|
||||||
nWalletDBUpdateCounter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CWalletDB::GetUpdateCounter()
|
|
||||||
{
|
|
||||||
return nWalletDBUpdateCounter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::TxnBegin()
|
bool CWalletDB::TxnBegin()
|
||||||
|
|
|
@ -140,9 +140,31 @@ public:
|
||||||
*/
|
*/
|
||||||
class CWalletDB
|
class CWalletDB
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
template <typename K, typename T>
|
||||||
|
bool WriteIC(const K& key, const T& value, bool fOverwrite = true)
|
||||||
|
{
|
||||||
|
if (!batch.Write(key, value, fOverwrite)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_dbw.IncrementUpdateCounter();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K>
|
||||||
|
bool EraseIC(const K& key)
|
||||||
|
{
|
||||||
|
if (!batch.Erase(key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_dbw.IncrementUpdateCounter();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CWalletDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool _fFlushOnClose = true) :
|
CWalletDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool _fFlushOnClose = true) :
|
||||||
batch(dbw, pszMode, _fFlushOnClose)
|
batch(dbw, pszMode, _fFlushOnClose),
|
||||||
|
m_dbw(dbw)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +202,6 @@ public:
|
||||||
/// This writes directly to the database, and will not update the CWallet's cached accounting entries!
|
/// This writes directly to the database, and will not update the CWallet's cached accounting entries!
|
||||||
/// Use wallet.AddAccountingEntry instead, to write *and* update its caches.
|
/// Use wallet.AddAccountingEntry instead, to write *and* update its caches.
|
||||||
bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry);
|
bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry);
|
||||||
bool WriteAccountingEntry_Backend(const CAccountingEntry& acentry);
|
|
||||||
bool ReadAccount(const std::string& strAccount, CAccount& account);
|
bool ReadAccount(const std::string& strAccount, CAccount& account);
|
||||||
bool WriteAccount(const std::string& strAccount, const CAccount& account);
|
bool WriteAccount(const std::string& strAccount, const CAccount& account);
|
||||||
|
|
||||||
|
@ -197,9 +218,9 @@ public:
|
||||||
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
|
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
|
||||||
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
|
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
|
||||||
/* Try to (very carefully!) recover wallet database (with a possible key type filter) */
|
/* Try to (very carefully!) recover wallet database (with a possible key type filter) */
|
||||||
static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue));
|
static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename);
|
||||||
/* Recover convenience-function to bypass the key filter callback, called when verify fails, recovers everything */
|
/* Recover convenience-function to bypass the key filter callback, called when verify fails, recovers everything */
|
||||||
static bool Recover(const std::string& filename);
|
static bool Recover(const std::string& filename, std::string& out_backup_filename);
|
||||||
/* Recover filter (used as callback), will only let keys (cryptographical keys) as KV/key-type pass through */
|
/* Recover filter (used as callback), will only let keys (cryptographical keys) as KV/key-type pass through */
|
||||||
static bool RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue);
|
static bool RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue);
|
||||||
/* Function to determine if a certain KV/key-type is a key (cryptographical key) type */
|
/* Function to determine if a certain KV/key-type is a key (cryptographical key) type */
|
||||||
|
@ -212,9 +233,6 @@ public:
|
||||||
//! write the hdchain model (external chain child index counter)
|
//! write the hdchain model (external chain child index counter)
|
||||||
bool WriteHDChain(const CHDChain& chain);
|
bool WriteHDChain(const CHDChain& chain);
|
||||||
|
|
||||||
static void IncrementUpdateCounter();
|
|
||||||
static unsigned int GetUpdateCounter();
|
|
||||||
|
|
||||||
//! Begin a new transaction
|
//! Begin a new transaction
|
||||||
bool TxnBegin();
|
bool TxnBegin();
|
||||||
//! Commit current transaction
|
//! Commit current transaction
|
||||||
|
@ -227,6 +245,7 @@ public:
|
||||||
bool WriteVersion(int nVersion);
|
bool WriteVersion(int nVersion);
|
||||||
private:
|
private:
|
||||||
CDB batch;
|
CDB batch;
|
||||||
|
CWalletDBWrapper& m_dbw;
|
||||||
|
|
||||||
CWalletDB(const CWalletDB&);
|
CWalletDB(const CWalletDB&);
|
||||||
void operator=(const CWalletDB&);
|
void operator=(const CWalletDB&);
|
||||||
|
|
Loading…
Add table
Reference in a new issue