Merge #17889: wallet: Improve CWallet:MarkDestinationsDirty

2b1641492f wallet: Improve CWallet:MarkDestinationsDirty (João Barbosa)

Pull request description:

  Improve `CWallet:MarkDestinationsDirty` by skipping transactions that already have the cache invalidated. Skipping a transaction avoids at worst case extracting all output destinations.

ACKs for top commit:
  meshcollider:
    re-utACK 2b1641492f

Tree-SHA512: 479dc2dde4b653b856e3d6a0c59a34fe33e963eb131a2d88552a8b30471b8725a087888fe5d7db6e4ee19b74072fe64441497f033be7d1931637f756e0d8fef5
pull/764/head
Samuel Dobson 5 years ago
commit 7fb94c0ed4
No known key found for this signature in database
GPG Key ID: D300116E1C875A3D

@ -78,6 +78,7 @@ static void add_coin(CWallet& wallet, const CAmount& nValue, int nAge = 6*24, bo
if (fIsFromMe) if (fIsFromMe)
{ {
wtx->m_amounts[CWalletTx::DEBIT].Set(ISMINE_SPENDABLE, 1); wtx->m_amounts[CWalletTx::DEBIT].Set(ISMINE_SPENDABLE, 1);
wtx->m_is_cache_empty = false;
} }
COutput output(wtx.get(), nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */); COutput output(wtx.get(), nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
vCoins.push_back(output); vCoins.push_back(output);

@ -1795,6 +1795,7 @@ CAmount CWalletTx::GetCachableAmount(AmountType type, const isminefilter& filter
auto& amount = m_amounts[type]; auto& amount = m_amounts[type];
if (recalculate || !amount.m_cached[filter]) { if (recalculate || !amount.m_cached[filter]) {
amount.Set(filter, type == DEBIT ? pwallet->GetDebit(*tx, filter) : pwallet->GetCredit(*tx, filter)); amount.Set(filter, type == DEBIT ? pwallet->GetDebit(*tx, filter) : pwallet->GetCredit(*tx, filter));
m_is_cache_empty = false;
} }
return amount.m_value[filter]; return amount.m_value[filter];
} }
@ -1871,6 +1872,7 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter
if (allow_cache) { if (allow_cache) {
m_amounts[AVAILABLE_CREDIT].Set(filter, nCredit); m_amounts[AVAILABLE_CREDIT].Set(filter, nCredit);
m_is_cache_empty = false;
} }
return nCredit; return nCredit;
@ -3171,10 +3173,9 @@ int64_t CWallet::GetOldestKeyPoolTime()
void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations) { void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations) {
for (auto& entry : mapWallet) { for (auto& entry : mapWallet) {
CWalletTx& wtx = entry.second; CWalletTx& wtx = entry.second;
if (wtx.m_is_cache_empty) continue;
for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) { for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
CTxDestination dst; CTxDestination dst;
if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, dst) && destinations.count(dst)) { if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, dst) && destinations.count(dst)) {
wtx.MarkDirty(); wtx.MarkDirty();
break; break;

@ -313,6 +313,13 @@ public:
enum AmountType { DEBIT, CREDIT, IMMATURE_CREDIT, AVAILABLE_CREDIT, AMOUNTTYPE_ENUM_ELEMENTS }; enum AmountType { DEBIT, CREDIT, IMMATURE_CREDIT, AVAILABLE_CREDIT, AMOUNTTYPE_ENUM_ELEMENTS };
CAmount GetCachableAmount(AmountType type, const isminefilter& filter, bool recalculate = false) const; CAmount GetCachableAmount(AmountType type, const isminefilter& filter, bool recalculate = false) const;
mutable CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS]; mutable CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS];
/**
* This flag is true if all m_amounts caches are empty. This is particularly
* useful in places where MarkDirty is conditionally called and the
* condition can be expensive and thus can be skipped if the flag is true.
* See MarkDestinationsDirty.
*/
mutable bool m_is_cache_empty{true};
mutable bool fChangeCached; mutable bool fChangeCached;
mutable bool fInMempool; mutable bool fInMempool;
mutable CAmount nChangeCached; mutable CAmount nChangeCached;
@ -439,6 +446,7 @@ public:
m_amounts[IMMATURE_CREDIT].Reset(); m_amounts[IMMATURE_CREDIT].Reset();
m_amounts[AVAILABLE_CREDIT].Reset(); m_amounts[AVAILABLE_CREDIT].Reset();
fChangeCached = false; fChangeCached = false;
m_is_cache_empty = true;
} }
void BindWallet(CWallet *pwalletIn) void BindWallet(CWallet *pwalletIn)

Loading…
Cancel
Save