Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show First 20 Lines • Show All 2,109 Lines • ▼ Show 20 Lines | if (pwallet != nullptr) { | ||||
const TxId &txid = GetId(); | const TxId &txid = GetId(); | ||||
result = pwallet->GetConflicts(txid); | result = pwallet->GetConflicts(txid); | ||||
result.erase(txid); | result.erase(txid); | ||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
Amount CWalletTx::GetCachableAmount(AmountType type, const isminefilter &filter, | |||||
bool recalculate) const { | |||||
auto &amount = m_amounts[type]; | |||||
if (recalculate || !amount.m_cached[filter]) { | |||||
amount.Set(filter, type == DEBIT ? pwallet->GetDebit(*tx, filter) | |||||
: pwallet->GetCredit(*tx, filter)); | |||||
} | |||||
return amount.m_value[filter]; | |||||
} | |||||
Amount CWalletTx::GetDebit(const isminefilter &filter) const { | Amount CWalletTx::GetDebit(const isminefilter &filter) const { | ||||
if (tx->vin.empty()) { | if (tx->vin.empty()) { | ||||
return Amount::zero(); | return Amount::zero(); | ||||
} | } | ||||
Amount debit = Amount::zero(); | Amount debit = Amount::zero(); | ||||
if (filter & ISMINE_SPENDABLE) { | if (filter & ISMINE_SPENDABLE) { | ||||
if (fDebitCached) { | debit += GetCachableAmount(DEBIT, ISMINE_SPENDABLE); | ||||
debit += nDebitCached; | |||||
} else { | |||||
nDebitCached = pwallet->GetDebit(*tx, ISMINE_SPENDABLE); | |||||
fDebitCached = true; | |||||
debit += nDebitCached; | |||||
} | |||||
} | } | ||||
if (filter & ISMINE_WATCH_ONLY) { | if (filter & ISMINE_WATCH_ONLY) { | ||||
if (fWatchDebitCached) { | debit += GetCachableAmount(DEBIT, ISMINE_WATCH_ONLY); | ||||
debit += nWatchDebitCached; | |||||
} else { | |||||
nWatchDebitCached = pwallet->GetDebit(*tx, ISMINE_WATCH_ONLY); | |||||
fWatchDebitCached = true; | |||||
debit += Amount(nWatchDebitCached); | |||||
} | |||||
} | } | ||||
return debit; | return debit; | ||||
} | } | ||||
Amount CWalletTx::GetCredit(interfaces::Chain::Lock &locked_chain, | Amount CWalletTx::GetCredit(interfaces::Chain::Lock &locked_chain, | ||||
const isminefilter &filter) const { | const isminefilter &filter) const { | ||||
// Must wait until coinbase is safely deep enough in the chain before | // Must wait until coinbase is safely deep enough in the chain before | ||||
// valuing it. | // valuing it. | ||||
if (IsImmatureCoinBase(locked_chain)) { | if (IsImmatureCoinBase(locked_chain)) { | ||||
return Amount::zero(); | return Amount::zero(); | ||||
} | } | ||||
Amount credit = Amount::zero(); | Amount credit = Amount::zero(); | ||||
if (filter & ISMINE_SPENDABLE) { | if (filter & ISMINE_SPENDABLE) { | ||||
// GetBalance can assume transactions in mapWallet won't change. | // GetBalance can assume transactions in mapWallet won't change. | ||||
if (fCreditCached) { | credit += GetCachableAmount(CREDIT, ISMINE_SPENDABLE); | ||||
credit += nCreditCached; | |||||
} else { | |||||
nCreditCached = pwallet->GetCredit(*tx, ISMINE_SPENDABLE); | |||||
fCreditCached = true; | |||||
credit += nCreditCached; | |||||
} | |||||
} | } | ||||
if (filter & ISMINE_WATCH_ONLY) { | if (filter & ISMINE_WATCH_ONLY) { | ||||
if (fWatchCreditCached) { | credit += GetCachableAmount(CREDIT, ISMINE_WATCH_ONLY); | ||||
credit += nWatchCreditCached; | |||||
} else { | |||||
nWatchCreditCached = pwallet->GetCredit(*tx, ISMINE_WATCH_ONLY); | |||||
fWatchCreditCached = true; | |||||
credit += nWatchCreditCached; | |||||
} | |||||
} | } | ||||
return credit; | return credit; | ||||
} | } | ||||
Amount CWalletTx::GetImmatureCredit(interfaces::Chain::Lock &locked_chain, | Amount CWalletTx::GetImmatureCredit(interfaces::Chain::Lock &locked_chain, | ||||
bool fUseCache) const { | bool fUseCache) const { | ||||
if (IsImmatureCoinBase(locked_chain) && IsInMainChain(locked_chain)) { | if (IsImmatureCoinBase(locked_chain) && IsInMainChain(locked_chain)) { | ||||
if (fUseCache && fImmatureCreditCached) { | return GetCachableAmount(IMMATURE_CREDIT, ISMINE_SPENDABLE, !fUseCache); | ||||
return nImmatureCreditCached; | |||||
} | |||||
nImmatureCreditCached = pwallet->GetCredit(*tx, ISMINE_SPENDABLE); | |||||
fImmatureCreditCached = true; | |||||
return nImmatureCreditCached; | |||||
} | } | ||||
return Amount::zero(); | return Amount::zero(); | ||||
} | } | ||||
Amount CWalletTx::GetAvailableCredit(interfaces::Chain::Lock &locked_chain, | Amount CWalletTx::GetAvailableCredit(interfaces::Chain::Lock &locked_chain, | ||||
bool fUseCache, | bool fUseCache, | ||||
const isminefilter &filter) const { | const isminefilter &filter) const { | ||||
if (pwallet == nullptr) { | if (pwallet == nullptr) { | ||||
return Amount::zero(); | return Amount::zero(); | ||||
} | } | ||||
// Avoid caching ismine for NO or ALL cases (could remove this check and | |||||
// simplify in the future). | |||||
bool allow_cache = | |||||
filter == ISMINE_SPENDABLE || filter == ISMINE_WATCH_ONLY; | |||||
// Must wait until coinbase is safely deep enough in the chain before | // Must wait until coinbase is safely deep enough in the chain before | ||||
// valuing it. | // valuing it. | ||||
if (IsImmatureCoinBase(locked_chain)) { | if (IsImmatureCoinBase(locked_chain)) { | ||||
return Amount::zero(); | return Amount::zero(); | ||||
} | } | ||||
Amount *cache = nullptr; | if (fUseCache && allow_cache && | ||||
bool *cache_used = nullptr; | m_amounts[AVAILABLE_CREDIT].m_cached[filter]) { | ||||
return m_amounts[AVAILABLE_CREDIT].m_value[filter]; | |||||
if (filter == ISMINE_SPENDABLE) { | |||||
cache = &nAvailableCreditCached; | |||||
cache_used = &fAvailableCreditCached; | |||||
} else if (filter == ISMINE_WATCH_ONLY) { | |||||
cache = &nAvailableWatchCreditCached; | |||||
cache_used = &fAvailableWatchCreditCached; | |||||
} | |||||
if (fUseCache && cache_used && *cache_used) { | |||||
return *cache; | |||||
} | } | ||||
Amount nCredit = Amount::zero(); | Amount nCredit = Amount::zero(); | ||||
const TxId &txid = GetId(); | const TxId &txid = GetId(); | ||||
for (uint32_t i = 0; i < tx->vout.size(); i++) { | for (uint32_t i = 0; i < tx->vout.size(); i++) { | ||||
if (!pwallet->IsSpent(locked_chain, COutPoint(txid, i))) { | if (!pwallet->IsSpent(locked_chain, COutPoint(txid, i))) { | ||||
const CTxOut &txout = tx->vout[i]; | const CTxOut &txout = tx->vout[i]; | ||||
nCredit += pwallet->GetCredit(txout, filter); | nCredit += pwallet->GetCredit(txout, filter); | ||||
if (!MoneyRange(nCredit)) { | if (!MoneyRange(nCredit)) { | ||||
throw std::runtime_error(std::string(__func__) + | throw std::runtime_error(std::string(__func__) + | ||||
" : value out of range"); | " : value out of range"); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (cache) { | if (allow_cache) { | ||||
*cache = nCredit; | m_amounts[AVAILABLE_CREDIT].Set(filter, nCredit); | ||||
*cache_used = true; | |||||
} | } | ||||
return nCredit; | return nCredit; | ||||
} | } | ||||
Amount | Amount | ||||
CWalletTx::GetImmatureWatchOnlyCredit(interfaces::Chain::Lock &locked_chain, | CWalletTx::GetImmatureWatchOnlyCredit(interfaces::Chain::Lock &locked_chain, | ||||
const bool fUseCache) const { | const bool fUseCache) const { | ||||
if (IsImmatureCoinBase(locked_chain) && IsInMainChain(locked_chain)) { | if (IsImmatureCoinBase(locked_chain) && IsInMainChain(locked_chain)) { | ||||
if (fUseCache && fImmatureWatchCreditCached) { | return GetCachableAmount(IMMATURE_CREDIT, ISMINE_WATCH_ONLY, | ||||
return nImmatureWatchCreditCached; | !fUseCache); | ||||
} | |||||
nImmatureWatchCreditCached = pwallet->GetCredit(*tx, ISMINE_WATCH_ONLY); | |||||
fImmatureWatchCreditCached = true; | |||||
return nImmatureWatchCreditCached; | |||||
} | } | ||||
return Amount::zero(); | return Amount::zero(); | ||||
} | } | ||||
Amount CWalletTx::GetChange() const { | Amount CWalletTx::GetChange() const { | ||||
if (fChangeCached) { | if (fChangeCached) { | ||||
return nChangeCached; | return nChangeCached; | ||||
▲ Show 20 Lines • Show All 2,758 Lines • Show Last 20 Lines |