Skip to content

Commit

Permalink
Merge bitcoin#9227: Make nWalletDBUpdated atomic to avoid a potential…
Browse files Browse the repository at this point in the history
… race.

d63ff62 Make nWalletDBUpdated atomic to avoid a potential race. (Patrick Strateman)
  • Loading branch information
laanwj committed Feb 6, 2017
2 parents 870cd2b + d63ff62 commit 02464da
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 33 deletions.
3 changes: 0 additions & 3 deletions src/wallet/db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@
using namespace std;


unsigned int nWalletDBUpdated;


//
// CDB
//
Expand Down
2 changes: 0 additions & 2 deletions src/wallet/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
static const bool DEFAULT_WALLET_PRIVDB = true;

extern unsigned int nWalletDBUpdated;

class CDBEnv
{
private:
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3691,7 +3691,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
walletInstance->ScanForWalletTransactions(pindexRescan, true);
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
walletInstance->SetBestChain(chainActive.GetLocator());
nWalletDBUpdated++;
CWalletDB::IncrementUpdateCounter();

// Restore wallet transaction metadata after -zapwallettxes=1
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
Expand Down
66 changes: 40 additions & 26 deletions src/wallet/walletdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "utiltime.h"
#include "wallet/wallet.h"

#include <atomic>

#include <boost/version.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
Expand All @@ -24,51 +26,53 @@ using namespace std;

static uint64_t nAccountingEntryNumber = 0;

static std::atomic<unsigned int> nWalletDBUpdateCounter;

//
// CWalletDB
//

bool CWalletDB::WriteName(const string& strAddress, const string& strName)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Write(make_pair(string("name"), strAddress), strName);
}

bool CWalletDB::EraseName(const 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.
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Erase(make_pair(string("name"), strAddress));
}

bool CWalletDB::WritePurpose(const string& strAddress, const string& strPurpose)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Write(make_pair(string("purpose"), strAddress), strPurpose);
}

bool CWalletDB::ErasePurpose(const string& strPurpose)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Erase(make_pair(string("purpose"), strPurpose));
}

bool CWalletDB::WriteTx(const CWalletTx& wtx)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
}

bool CWalletDB::EraseTx(uint256 hash)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Erase(std::make_pair(std::string("tx"), hash));
}

bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;

if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
keyMeta, false))
Expand All @@ -88,7 +92,7 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
const CKeyMetadata &keyMeta)
{
const bool fEraseUnencryptedKey = true;
nWalletDBUpdated++;
nWalletDBUpdateCounter++;

if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
keyMeta))
Expand All @@ -106,31 +110,31 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,

bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
}

bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
}

bool CWalletDB::WriteWatchOnly(const CScript &dest)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1');
}

bool CWalletDB::EraseWatchOnly(const CScript &dest)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)));
}

bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
return Write(std::string("bestblock_nomerkle"), locator);
}
Expand All @@ -143,13 +147,13 @@ bool CWalletDB::ReadBestBlock(CBlockLocator& locator)

bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Write(std::string("orderposnext"), nOrderPosNext);
}

bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Write(std::string("defaultkey"), vchPubKey);
}

Expand All @@ -160,13 +164,13 @@ bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)

bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Write(std::make_pair(std::string("pool"), nPool), keypool);
}

bool CWalletDB::ErasePool(int64_t nPool)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Erase(std::make_pair(std::string("pool"), nPool));
}

Expand Down Expand Up @@ -780,20 +784,20 @@ void ThreadFlushWalletDB()
if (!GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET))
return;

unsigned int nLastSeen = nWalletDBUpdated;
unsigned int nLastFlushed = nWalletDBUpdated;
unsigned int nLastSeen = CWalletDB::GetUpdateCounter();
unsigned int nLastFlushed = CWalletDB::GetUpdateCounter();
int64_t nLastWalletUpdate = GetTime();
while (true)
{
MilliSleep(500);

if (nLastSeen != nWalletDBUpdated)
if (nLastSeen != CWalletDB::GetUpdateCounter())
{
nLastSeen = nWalletDBUpdated;
nLastSeen = CWalletDB::GetUpdateCounter();
nLastWalletUpdate = GetTime();
}

if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2)
if (nLastFlushed != CWalletDB::GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2)
{
TRY_LOCK(bitdb.cs_db,lockDb);
if (lockDb)
Expand All @@ -815,7 +819,7 @@ void ThreadFlushWalletDB()
if (_mi != bitdb.mapFileUseCount.end())
{
LogPrint("db", "Flushing %s\n", strFile);
nLastFlushed = nWalletDBUpdated;
nLastFlushed = CWalletDB::GetUpdateCounter();
int64_t nStart = GetTimeMillis();

// Flush wallet file so it's self contained
Expand Down Expand Up @@ -922,19 +926,29 @@ bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename)

bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
}

bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
}


bool CWalletDB::WriteHDChain(const CHDChain& chain)
{
nWalletDBUpdated++;
nWalletDBUpdateCounter++;
return Write(std::string("hdchain"), chain);
}

void CWalletDB::IncrementUpdateCounter()
{
nWalletDBUpdateCounter++;
}

unsigned int CWalletDB::GetUpdateCounter()
{
return nWalletDBUpdateCounter;
}
3 changes: 2 additions & 1 deletion src/wallet/walletdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,11 @@ class CWalletDB : public CDB
//! write the hdchain model (external chain child index counter)
bool WriteHDChain(const CHDChain& chain);

static void IncrementUpdateCounter();
static unsigned int GetUpdateCounter();
private:
CWalletDB(const CWalletDB&);
void operator=(const CWalletDB&);

};

void ThreadFlushWalletDB();
Expand Down

0 comments on commit 02464da

Please sign in to comment.