Navigation Menu

Skip to content

Commit

Permalink
Add atomic cache for balances
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasschnelli committed Jun 14, 2017
1 parent 1ad3d4e commit 8688671
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 13 deletions.
76 changes: 63 additions & 13 deletions src/wallet/wallet.cpp
Expand Up @@ -723,6 +723,7 @@ DBErrors CWallet::ReorderTransactions()
}
walletdb.WriteOrderPosNext(nOrderPosNext);

MarkBalancesDirty();
return DB_LOAD_OK;
}

Expand Down Expand Up @@ -812,11 +813,10 @@ bool CWallet::GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bFo

void CWallet::MarkDirty()
{
{
LOCK(cs_wallet);
for (std::pair<const uint256, CWalletTx>& item : mapWallet)
item.second.MarkDirty();
}
LOCK(cs_wallet);
MarkBalancesDirty();
for (std::pair<const uint256, CWalletTx>& item : mapWallet)
item.second.MarkDirty();
}

bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
Expand All @@ -843,6 +843,7 @@ bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
success = false;
}

MarkBalancesDirty();
NotifyTransactionChanged(this, originalHash, CT_UPDATED);

return success;
Expand Down Expand Up @@ -907,6 +908,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)

// Break debit/credit balance caches:
wtx.MarkDirty();
MarkBalancesDirty();

// Notify UI of new or updated transaction
NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
Expand Down Expand Up @@ -1053,6 +1055,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
}
}

MarkBalancesDirty();
return true;
}

Expand Down Expand Up @@ -1113,6 +1116,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
}
}
}
MarkBalancesDirty();
}

void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pindex, int posInBlock) {
Expand Down Expand Up @@ -1152,6 +1156,7 @@ void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const
for (size_t i = 0; i < pblock->vtx.size(); i++) {
SyncTransaction(pblock->vtx[i], pindex, i);
}
MarkBalancesDirty();
}

void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) {
Expand All @@ -1160,6 +1165,7 @@ void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) {
for (const CTransactionRef& ptx : pblock->vtx) {
SyncTransaction(ptx);
}
MarkBalancesDirty();
}


Expand Down Expand Up @@ -1856,9 +1862,23 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman
* @{
*/

void CWallet::MarkBalancesDirty()
{
fBalanceDirty = true;
fUnconfirmedBalanceDirty = true;
fImmatureBalanceDirty = true;
fWatchOnlyBalanceDirty = true;
fUnconfirmedWatchOnlyBalanceDirty = true;
fImmatureWatchOnlyBalanceDirty = true;
BalancesChanged(); //emit signal
}

CAmount CWallet::GetBalance() const
{
if (!fBalanceDirty) {
return nBalanceCache;
}

CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
Expand All @@ -1868,13 +1888,18 @@ CAmount CWallet::GetBalance() const
if (pcoin->IsTrusted())
nTotal += pcoin->GetAvailableCredit();
}
nBalanceCache = nTotal;
fBalanceDirty = false;
}

return nTotal;
return nBalanceCache;
}

CAmount CWallet::GetUnconfirmedBalance() const
{
if (!fUnconfirmedBalanceDirty) {
return nUnconfirmedBalanceCache;
}

CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
Expand All @@ -1884,12 +1909,18 @@ CAmount CWallet::GetUnconfirmedBalance() const
if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool())
nTotal += pcoin->GetAvailableCredit();
}
nUnconfirmedBalanceCache = nTotal;
fUnconfirmedBalanceDirty = false;
}
return nTotal;
return nUnconfirmedBalanceCache;
}

CAmount CWallet::GetImmatureBalance() const
{
if (!fImmatureBalanceDirty) {
return nImmatureBalanceCache;
}

CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
Expand All @@ -1898,12 +1929,18 @@ CAmount CWallet::GetImmatureBalance() const
const CWalletTx* pcoin = &(*it).second;
nTotal += pcoin->GetImmatureCredit();
}
nImmatureBalanceCache = nTotal;
fImmatureBalanceDirty = false;
}
return nTotal;
return nImmatureBalanceCache;
}

CAmount CWallet::GetWatchOnlyBalance() const
{
if (!fWatchOnlyBalanceDirty) {
return nWatchOnlyBalanceCache;
}

CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
Expand All @@ -1913,13 +1950,18 @@ CAmount CWallet::GetWatchOnlyBalance() const
if (pcoin->IsTrusted())
nTotal += pcoin->GetAvailableWatchOnlyCredit();
}
nWatchOnlyBalanceCache = nTotal;
fWatchOnlyBalanceDirty = false;
}

return nTotal;
return nWatchOnlyBalanceCache;
}

CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
{
if (!fUnconfirmedWatchOnlyBalanceDirty) {
return nUnconfirmedWatchOnlyBalanceCache;
}

CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
Expand All @@ -1929,12 +1971,18 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool())
nTotal += pcoin->GetAvailableWatchOnlyCredit();
}
nUnconfirmedWatchOnlyBalanceCache = nTotal;
fUnconfirmedWatchOnlyBalanceDirty = false;
}
return nTotal;
return nUnconfirmedWatchOnlyBalanceCache;
}

CAmount CWallet::GetImmatureWatchOnlyBalance() const
{
if (!fImmatureWatchOnlyBalanceDirty) {
return nImmatureWatchOnlyBalanceCache;
}

CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
Expand All @@ -1943,8 +1991,10 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const
const CWalletTx* pcoin = &(*it).second;
nTotal += pcoin->GetImmatureWatchOnlyCredit();
}
nImmatureWatchOnlyBalanceCache = nTotal;
fImmatureWatchOnlyBalanceDirty = false;
}
return nTotal;
return nImmatureWatchOnlyBalanceCache;
}

// Calculate total balance in a different way from GetBalance. The biggest
Expand Down
24 changes: 24 additions & 0 deletions src/wallet/wallet.h
Expand Up @@ -791,6 +791,12 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
nRelockTime = 0;
fAbortRescan = false;
fScanningWallet = false;
fBalanceDirty = true;
fUnconfirmedBalanceDirty = true;
fImmatureBalanceDirty = true;
fWatchOnlyBalanceDirty = true;
fUnconfirmedWatchOnlyBalanceDirty = true;
fImmatureWatchOnlyBalanceDirty = true;
}

std::map<uint256, CWalletTx> mapWallet;
Expand Down Expand Up @@ -922,6 +928,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
void ReacceptWalletTransactions();
void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override;
std::vector<uint256> ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman);

void MarkBalancesDirty();
CAmount GetBalance() const;
CAmount GetUnconfirmedBalance() const;
CAmount GetImmatureBalance() const;
Expand All @@ -931,6 +939,22 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
CAmount GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account) const;
CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const;

mutable std::atomic<CAmount> nBalanceCache;
mutable std::atomic<CAmount> nUnconfirmedBalanceCache;
mutable std::atomic<CAmount> nImmatureBalanceCache;
mutable std::atomic<CAmount> nWatchOnlyBalanceCache;
mutable std::atomic<CAmount> nUnconfirmedWatchOnlyBalanceCache;
mutable std::atomic<CAmount> nImmatureWatchOnlyBalanceCache;
mutable std::atomic<bool> fBalanceDirty;
mutable std::atomic<bool> fUnconfirmedBalanceDirty;
mutable std::atomic<bool> fImmatureBalanceDirty;
mutable std::atomic<bool> fWatchOnlyBalanceDirty;
mutable std::atomic<bool> fUnconfirmedWatchOnlyBalanceDirty;
mutable std::atomic<bool> fImmatureWatchOnlyBalanceDirty;

/** Notification for balance changes */
boost::signals2::signal<void ()> BalancesChanged;

/**
* Insert additional inputs into the transaction by
* calling CreateTransaction();
Expand Down

0 comments on commit 8688671

Please sign in to comment.