Use wallet UTXOs whenever possible to avoid looping through all wallet txes (#3156)

* Use setWalletUTXO whenever possible to avoid looping through all wallet txes

* Apply review suggestion - GetSpendableTXs()
This commit is contained in:
UdjinM6 2019-10-17 13:28:34 +03:00 committed by Alexander Block
parent 21d33dd56d
commit 3c6b5f98e0
2 changed files with 47 additions and 41 deletions

View File

@ -2446,14 +2446,33 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman
*/
std::unordered_set<const CWalletTx*, WalletTxHasher> CWallet::GetSpendableTXs() const
{
AssertLockHeld(cs_wallet);
std::unordered_set<const CWalletTx*, WalletTxHasher> ret;
for (auto it = setWalletUTXO.begin(); it != setWalletUTXO.end(); ) {
const auto& outpoint = *it;
const auto jt = mapWallet.find(outpoint.hash);
if (jt != mapWallet.end()) {
ret.emplace(&jt->second);
}
// setWalletUTXO is sorted by COutPoint, which means that all UTXOs for the same TX are neighbors
// skip entries until we encounter a new TX
while (it != setWalletUTXO.end() && it->hash == outpoint.hash) {
++it;
}
}
return ret;
}
CAmount CWallet::GetBalance() const
{
CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
for (auto pcoin : GetSpendableTXs()) {
if (pcoin->IsTrusted())
nTotal += pcoin->GetAvailableCredit();
}
@ -2492,15 +2511,8 @@ CAmount CWallet::GetAnonymizedBalance() const
LOCK2(cs_main, cs_wallet);
std::set<uint256> setWalletTxesCounted;
for (const auto& outpoint : setWalletUTXO) {
if (!setWalletTxesCounted.emplace(outpoint.hash).second) continue;
const auto it = mapWallet.find(outpoint.hash);
if (it == mapWallet.end() || !it->second.IsTrusted()) continue;
nTotal += it->second.GetAnonymizedCredit();
for (auto pcoin : GetSpendableTXs()) {
nTotal += pcoin->GetAnonymizedCredit();
}
return nTotal;
@ -2560,14 +2572,8 @@ CAmount CWallet::GetDenominatedBalance(bool unconfirmed) const
LOCK2(cs_main, cs_wallet);
std::set<uint256> setWalletTxesCounted;
for (const auto& outpoint : setWalletUTXO) {
if (!setWalletTxesCounted.emplace(outpoint.hash).second) continue;
const auto it = mapWallet.find(outpoint.hash);
if (it == mapWallet.end()) continue;
nTotal += it->second.GetDenominatedCredit(unconfirmed);
for (auto pcoin : GetSpendableTXs()) {
nTotal += pcoin->GetDenominatedCredit(unconfirmed);
}
return nTotal;
@ -2578,9 +2584,7 @@ CAmount CWallet::GetUnconfirmedBalance() const
CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
for (auto pcoin : GetSpendableTXs()) {
if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && !pcoin->IsLockedByInstantSend() && pcoin->InMempool())
nTotal += pcoin->GetAvailableCredit();
}
@ -2593,9 +2597,7 @@ CAmount CWallet::GetImmatureBalance() const
CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
for (auto pcoin : GetSpendableTXs()) {
nTotal += pcoin->GetImmatureCredit();
}
}
@ -2607,9 +2609,7 @@ CAmount CWallet::GetWatchOnlyBalance() const
CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
for (auto pcoin : GetSpendableTXs()) {
if (pcoin->IsTrusted())
nTotal += pcoin->GetAvailableWatchOnlyCredit();
}
@ -2623,9 +2623,7 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
for (auto pcoin : GetSpendableTXs()) {
if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && !pcoin->IsLockedByInstantSend() && pcoin->InMempool())
nTotal += pcoin->GetAvailableWatchOnlyCredit();
}
@ -2638,9 +2636,7 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const
CAmount nTotal = 0;
{
LOCK2(cs_main, cs_wallet);
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
for (auto pcoin : GetSpendableTXs()) {
nTotal += pcoin->GetImmatureWatchOnlyCredit();
}
}
@ -2714,10 +2710,8 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
CAmount nTotal = 0;
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const uint256& wtxid = it->first;
const CWalletTx* pcoin = &(*it).second;
for (auto pcoin : GetSpendableTXs()) {
const uint256& wtxid = pcoin->GetHash();
if (!CheckFinalTx(*pcoin))
continue;
@ -2760,10 +2754,10 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
if (pcoin->tx->vout[i].nValue < nMinimumAmount || pcoin->tx->vout[i].nValue > nMaximumAmount)
continue;
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint((*it).first, i)))
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint(wtxid, i)))
continue;
if (IsLockedCoin((*it).first, i) && nCoinType != ONLY_1000)
if (IsLockedCoin(wtxid, i) && nCoinType != ONLY_1000)
continue;
if (IsSpent(wtxid, i))

View File

@ -10,6 +10,7 @@
#include "amount.h"
#include "base58.h"
#include "policy/feerate.h"
#include "saltedhasher.h"
#include "streams.h"
#include "tinyformat.h"
#include "ui_interface.h"
@ -518,6 +519,14 @@ public:
std::set<uint256> GetConflicts() const;
};
struct WalletTxHasher
{
StaticSaltedHasher h;
size_t operator()(const CWalletTx* a) const
{
return h(a->GetHash());
}
};
class CInputCoin {
public:
@ -775,6 +784,9 @@ private:
// the next block comes in
uint256 hashPrevBestCoinbase;
// A helper function which loops through wallet UTXOs
std::unordered_set<const CWalletTx*, WalletTxHasher> GetSpendableTXs() const;
public:
/*
* Main wallet lock.