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:
parent
21d33dd56d
commit
3c6b5f98e0
@ -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))
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user