Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show First 20 Lines • Show All 2,168 Lines • ▼ Show 20 Lines | Amount CWalletTx::GetChange() const { | ||||
return nChangeCached; | return nChangeCached; | ||||
} | } | ||||
bool CWalletTx::InMempool() const { | bool CWalletTx::InMempool() const { | ||||
return fInMempool; | return fInMempool; | ||||
} | } | ||||
bool CWalletTx::IsTrusted() const { | bool CWalletTx::IsTrusted() const { | ||||
std::set<TxId> s; | std::set<TxId> trusted_parents; | ||||
return IsTrusted(s); | LOCK(pwallet->cs_wallet); | ||||
return pwallet->IsTrusted(*this, trusted_parents); | |||||
} | } | ||||
bool CWalletTx::IsTrusted(std::set<TxId> &trusted_parents) const { | bool CWallet::IsTrusted(const CWalletTx &wtx, | ||||
std::set<TxId> &trusted_parents) const { | |||||
AssertLockHeld(cs_wallet); | |||||
// Quick answer in most cases | // Quick answer in most cases | ||||
TxValidationState state; | TxValidationState state; | ||||
if (!pwallet->chain().contextualCheckTransactionForCurrentBlock(*tx, | if (!chain().contextualCheckTransactionForCurrentBlock(*wtx.tx, state)) { | ||||
state)) { | |||||
return false; | return false; | ||||
} | } | ||||
int nDepth = GetDepthInMainChain(); | int nDepth = wtx.GetDepthInMainChain(); | ||||
if (nDepth >= 1) { | if (nDepth >= 1) { | ||||
return true; | return true; | ||||
} | } | ||||
if (nDepth < 0) { | if (nDepth < 0) { | ||||
return false; | return false; | ||||
} | } | ||||
// using wtx's cached debit | // using wtx's cached debit | ||||
if (!pwallet->m_spend_zero_conf_change || !IsFromMe(ISMINE_ALL)) { | if (!m_spend_zero_conf_change || !wtx.IsFromMe(ISMINE_ALL)) { | ||||
return false; | return false; | ||||
} | } | ||||
// Don't trust unconfirmed transactions from us unless they are in the | // Don't trust unconfirmed transactions from us unless they are in the | ||||
// mempool. | // mempool. | ||||
if (!InMempool()) { | if (!wtx.InMempool()) { | ||||
return false; | return false; | ||||
} | } | ||||
// Trusted if all inputs are from us and are in the mempool: | // Trusted if all inputs are from us and are in the mempool: | ||||
LOCK(pwallet->cs_wallet); | for (const CTxIn &txin : wtx.tx->vin) { | ||||
for (const CTxIn &txin : tx->vin) { | |||||
// Transactions not sent by us: not trusted | // Transactions not sent by us: not trusted | ||||
const CWalletTx *parent = pwallet->GetWalletTx(txin.prevout.GetTxId()); | const CWalletTx *parent = GetWalletTx(txin.prevout.GetTxId()); | ||||
if (parent == nullptr) { | if (parent == nullptr) { | ||||
return false; | return false; | ||||
} | } | ||||
const CTxOut &parentOut = parent->tx->vout[txin.prevout.GetN()]; | const CTxOut &parentOut = parent->tx->vout[txin.prevout.GetN()]; | ||||
// Check that this specific input being spent is trusted | // Check that this specific input being spent is trusted | ||||
if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) { | if (IsMine(parentOut) != ISMINE_SPENDABLE) { | ||||
return false; | return false; | ||||
} | } | ||||
// If we've already trusted this parent, continue | // If we've already trusted this parent, continue | ||||
if (trusted_parents.count(parent->GetId())) { | if (trusted_parents.count(parent->GetId())) { | ||||
continue; | continue; | ||||
} | } | ||||
// Recurse to check that the parent is also trusted | // Recurse to check that the parent is also trusted | ||||
if (!parent->IsTrusted(trusted_parents)) { | if (!IsTrusted(*parent, trusted_parents)) { | ||||
return false; | return false; | ||||
} | } | ||||
trusted_parents.insert(parent->GetId()); | trusted_parents.insert(parent->GetId()); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
CWallet::Balance CWallet::GetBalance(const int min_depth, | CWallet::Balance CWallet::GetBalance(const int min_depth, | ||||
bool avoid_reuse) const { | bool avoid_reuse) const { | ||||
Balance ret; | Balance ret; | ||||
isminefilter reuse_filter = avoid_reuse ? ISMINE_NO : ISMINE_USED; | isminefilter reuse_filter = avoid_reuse ? ISMINE_NO : ISMINE_USED; | ||||
LOCK(cs_wallet); | LOCK(cs_wallet); | ||||
std::set<TxId> trusted_parents; | std::set<TxId> trusted_parents; | ||||
for (const auto &entry : mapWallet) { | for (const auto &entry : mapWallet) { | ||||
const CWalletTx &wtx = entry.second; | const CWalletTx &wtx = entry.second; | ||||
const bool is_trusted{wtx.IsTrusted(trusted_parents)}; | const bool is_trusted{IsTrusted(wtx, trusted_parents)}; | ||||
const int tx_depth{wtx.GetDepthInMainChain()}; | const int tx_depth{wtx.GetDepthInMainChain()}; | ||||
const Amount tx_credit_mine{wtx.GetAvailableCredit( | const Amount tx_credit_mine{wtx.GetAvailableCredit( | ||||
/* fUseCache */ true, ISMINE_SPENDABLE | reuse_filter)}; | /* fUseCache */ true, ISMINE_SPENDABLE | reuse_filter)}; | ||||
const Amount tx_credit_watchonly{wtx.GetAvailableCredit( | const Amount tx_credit_watchonly{wtx.GetAvailableCredit( | ||||
/* fUseCache */ true, ISMINE_WATCH_ONLY | reuse_filter)}; | /* fUseCache */ true, ISMINE_WATCH_ONLY | reuse_filter)}; | ||||
if (is_trusted && tx_depth >= min_depth) { | if (is_trusted && tx_depth >= min_depth) { | ||||
ret.m_mine_trusted += tx_credit_mine; | ret.m_mine_trusted += tx_credit_mine; | ||||
ret.m_watchonly_trusted += tx_credit_watchonly; | ret.m_watchonly_trusted += tx_credit_watchonly; | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | for (const auto &entry : mapWallet) { | ||||
// We should not consider coins which aren't at least in our mempool. | // We should not consider coins which aren't at least in our mempool. | ||||
// It's possible for these to be conflicted via ancestors which we may | // It's possible for these to be conflicted via ancestors which we may | ||||
// never be able to detect. | // never be able to detect. | ||||
if (nDepth == 0 && !wtx.InMempool()) { | if (nDepth == 0 && !wtx.InMempool()) { | ||||
continue; | continue; | ||||
} | } | ||||
bool safeTx = wtx.IsTrusted(trusted_parents); | bool safeTx = IsTrusted(wtx, trusted_parents); | ||||
// Bitcoin-ABC: Removed check that prevents consideration of coins from | // Bitcoin-ABC: Removed check that prevents consideration of coins from | ||||
// transactions that are replacing other transactions. This check based | // transactions that are replacing other transactions. This check based | ||||
// on wtx.mapValue.count("replaces_txid") which was not being set | // on wtx.mapValue.count("replaces_txid") which was not being set | ||||
// anywhere. | // anywhere. | ||||
// Similarly, we should not consider coins from transactions that have | // Similarly, we should not consider coins from transactions that have | ||||
// been replaced. In the example above, we would want to prevent | // been replaced. In the example above, we would want to prevent | ||||
▲ Show 20 Lines • Show All 1,313 Lines • ▼ Show 20 Lines | |||||
std::map<CTxDestination, Amount> CWallet::GetAddressBalances() const { | std::map<CTxDestination, Amount> CWallet::GetAddressBalances() const { | ||||
std::map<CTxDestination, Amount> balances; | std::map<CTxDestination, Amount> balances; | ||||
LOCK(cs_wallet); | LOCK(cs_wallet); | ||||
std::set<TxId> trusted_parents; | std::set<TxId> trusted_parents; | ||||
for (const auto &walletEntry : mapWallet) { | for (const auto &walletEntry : mapWallet) { | ||||
const CWalletTx &wtx = walletEntry.second; | const CWalletTx &wtx = walletEntry.second; | ||||
if (!wtx.IsTrusted(trusted_parents)) { | if (!IsTrusted(wtx, trusted_parents)) { | ||||
continue; | continue; | ||||
} | } | ||||
if (wtx.IsImmatureCoinBase()) { | if (wtx.IsImmatureCoinBase()) { | ||||
continue; | continue; | ||||
} | } | ||||
int nDepth = wtx.GetDepthInMainChain(); | int nDepth = wtx.GetDepthInMainChain(); | ||||
▲ Show 20 Lines • Show All 1,336 Lines • Show Last 20 Lines |