mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-12-09 12:12:41 +01:00
Merge #8694: Basic multiwallet support
c237bd7wallet: Update formatting (Luke Dashjr)9cbe8c8wallet: Forbid -salvagewallet, -zapwallettxes, and -upgradewallet with multiple wallets (Luke Dashjr)a2a5f3fwallet: Base backup filenames on original wallet filename (Luke Dashjr)b823a4cwallet: Include actual backup filename in recovery warning message (Luke Dashjr)84dcb45Bugfix: wallet: Fix warningStr, errorStr argument order (Luke Dashjr)008c360Wallet: Move multiwallet sanity checks to CWallet::Verify, and do other checks on all wallets (Luke Dashjr)0f08575Wallet: Support loading multiple wallets if -wallet used more than once (Luke Dashjr)b124cf0Wallet: Replace pwalletMain with a vector of wallet pointers (Luke Dashjr)19b3648CWalletDB: Store the update counter per wallet (Luke Dashjr)74e8738Bugfix: ForceSetArg should replace entr(ies) in mapMultiArgs, not append (Luke Dashjr)23fb9adwallet: Move nAccountingEntryNumber from static/global to CWallet (Luke Dashjr)9d15d55Bugfix: wallet: Increment "update counter" when modifying account stuff (Luke Dashjr)f28eb80Bugfix: 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:
@@ -21,59 +21,47 @@
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
static uint64_t nAccountingEntryNumber = 0;
|
||||
|
||||
static std::atomic<unsigned int> nWalletDBUpdateCounter;
|
||||
|
||||
//
|
||||
// CWalletDB
|
||||
//
|
||||
|
||||
bool CWalletDB::WriteName(const std::string& strAddress, const std::string& strName)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Write(std::make_pair(std::string("name"), strAddress), strName);
|
||||
return WriteIC(std::make_pair(std::string("name"), strAddress), strName);
|
||||
}
|
||||
|
||||
bool CWalletDB::EraseName(const std::string& strAddress)
|
||||
{
|
||||
// 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.
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Erase(std::make_pair(std::string("name"), strAddress));
|
||||
return EraseIC(std::make_pair(std::string("name"), strAddress));
|
||||
}
|
||||
|
||||
bool CWalletDB::WritePurpose(const std::string& strAddress, const std::string& strPurpose)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Write(std::make_pair(std::string("purpose"), strAddress), strPurpose);
|
||||
return WriteIC(std::make_pair(std::string("purpose"), strAddress), strPurpose);
|
||||
}
|
||||
|
||||
bool CWalletDB::ErasePurpose(const std::string& strPurpose)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Erase(std::make_pair(std::string("purpose"), strPurpose));
|
||||
return EraseIC(std::make_pair(std::string("purpose"), strPurpose));
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteTx(const CWalletTx& wtx)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
|
||||
return WriteIC(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
|
||||
}
|
||||
|
||||
bool CWalletDB::EraseTx(uint256 hash)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Erase(std::make_pair(std::string("tx"), hash));
|
||||
return EraseIC(std::make_pair(std::string("tx"), hash));
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
|
||||
if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey),
|
||||
keyMeta, false))
|
||||
if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// hash pubkey/privkey to accelerate wallet load
|
||||
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(), 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,
|
||||
@@ -89,55 +77,53 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
|
||||
const CKeyMetadata &keyMeta)
|
||||
{
|
||||
const bool fEraseUnencryptedKey = true;
|
||||
nWalletDBUpdateCounter++;
|
||||
|
||||
if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey),
|
||||
keyMeta))
|
||||
if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) {
|
||||
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;
|
||||
}
|
||||
if (fEraseUnencryptedKey)
|
||||
{
|
||||
batch.Erase(std::make_pair(std::string("key"), vchPubKey));
|
||||
batch.Erase(std::make_pair(std::string("wkey"), vchPubKey));
|
||||
EraseIC(std::make_pair(std::string("key"), vchPubKey));
|
||||
EraseIC(std::make_pair(std::string("wkey"), vchPubKey));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
|
||||
return WriteIC(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
|
||||
return WriteIC(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
if (!batch.Write(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta))
|
||||
if (!WriteIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) {
|
||||
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)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
if (!batch.Erase(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest))))
|
||||
if (!EraseIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) {
|
||||
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)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
batch.Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
|
||||
return batch.Write(std::string("bestblock_nomerkle"), locator);
|
||||
WriteIC(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
|
||||
return WriteIC(std::string("bestblock_nomerkle"), locator);
|
||||
}
|
||||
|
||||
bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
|
||||
@@ -148,14 +134,12 @@ bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
|
||||
|
||||
bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Write(std::string("orderposnext"), nOrderPosNext);
|
||||
return WriteIC(std::string("orderposnext"), nOrderPosNext);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Write(std::string("defaultkey"), vchPubKey);
|
||||
return WriteIC(std::string("defaultkey"), vchPubKey);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Write(std::make_pair(std::string("pool"), nPool), keypool);
|
||||
return WriteIC(std::make_pair(std::string("pool"), nPool), keypool);
|
||||
}
|
||||
|
||||
bool CWalletDB::ErasePool(int64_t nPool)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Erase(std::make_pair(std::string("pool"), nPool));
|
||||
return EraseIC(std::make_pair(std::string("pool"), nPool));
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -188,17 +170,12 @@ bool CWalletDB::ReadAccount(const std::string& strAccount, 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)
|
||||
{
|
||||
return batch.Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteAccountingEntry_Backend(const CAccountingEntry& acentry)
|
||||
{
|
||||
return WriteAccountingEntry(++nAccountingEntryNumber, acentry);
|
||||
return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
|
||||
}
|
||||
|
||||
CAmount CWalletDB::GetAccountCreditDebit(const std::string& strAccount)
|
||||
@@ -337,8 +314,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||
ssKey >> strAccount;
|
||||
uint64_t nNumber;
|
||||
ssKey >> nNumber;
|
||||
if (nNumber > nAccountingEntryNumber)
|
||||
nAccountingEntryNumber = nNumber;
|
||||
if (nNumber > pwallet->nAccountingEntryNumber) {
|
||||
pwallet->nAccountingEntryNumber = nNumber;
|
||||
}
|
||||
|
||||
if (!wss.fAnyUnordered)
|
||||
{
|
||||
@@ -784,38 +762,39 @@ void MaybeCompactWalletDB()
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned int nLastSeen = CWalletDB::GetUpdateCounter();
|
||||
static unsigned int nLastFlushed = CWalletDB::GetUpdateCounter();
|
||||
static int64_t nLastWalletUpdate = GetTime();
|
||||
for (CWalletRef pwallet : vpwallets) {
|
||||
CWalletDBWrapper& dbh = pwallet->GetDBHandle();
|
||||
|
||||
if (nLastSeen != CWalletDB::GetUpdateCounter())
|
||||
{
|
||||
nLastSeen = CWalletDB::GetUpdateCounter();
|
||||
nLastWalletUpdate = GetTime();
|
||||
}
|
||||
unsigned int nUpdateCounter = dbh.nUpdateCounter;
|
||||
|
||||
if (nLastFlushed != CWalletDB::GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2)
|
||||
{
|
||||
if (CDB::PeriodicFlush(pwalletMain->GetDBHandle())) {
|
||||
nLastFlushed = CWalletDB::GetUpdateCounter();
|
||||
if (dbh.nLastSeen != nUpdateCounter) {
|
||||
dbh.nLastSeen = nUpdateCounter;
|
||||
dbh.nLastWalletUpdate = GetTime();
|
||||
}
|
||||
|
||||
if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) {
|
||||
if (CDB::PeriodicFlush(dbh)) {
|
||||
dbh.nLastFlushed = nUpdateCounter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fOneThread = false;
|
||||
}
|
||||
|
||||
//
|
||||
// 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
|
||||
// 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)
|
||||
@@ -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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
|
||||
return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
|
||||
}
|
||||
|
||||
bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
|
||||
return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
|
||||
}
|
||||
|
||||
|
||||
bool CWalletDB::WriteHDChain(const CHDChain& chain)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return batch.Write(std::string("hdchain"), chain);
|
||||
}
|
||||
|
||||
void CWalletDB::IncrementUpdateCounter()
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
}
|
||||
|
||||
unsigned int CWalletDB::GetUpdateCounter()
|
||||
{
|
||||
return nWalletDBUpdateCounter;
|
||||
return WriteIC(std::string("hdchain"), chain);
|
||||
}
|
||||
|
||||
bool CWalletDB::TxnBegin()
|
||||
|
||||
Reference in New Issue
Block a user