Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 326 Lines • ▼ Show 20 Lines | for (const CTxIn &txin : tx.vin) { | ||||
assert(coinFromDisk.GetTxOut() == coin.GetTxOut()); | assert(coinFromDisk.GetTxOut() == coin.GetTxOut()); | ||||
} | } | ||||
} | } | ||||
return CheckInputs(tx, state, view, true, flags, cacheSigStore, true, | return CheckInputs(tx, state, view, true, flags, cacheSigStore, true, | ||||
txdata, nSigChecksOut); | txdata, nSigChecksOut); | ||||
} | } | ||||
/** | |||||
* @param[out] coins_to_uncache Return any outpoints which were not previously | |||||
* present in the coins cache, but were added as a result of validating the tx | |||||
* for mempool acceptance. This allows the caller | |||||
* to optionally remove the cache additions if the associated transaction ends | |||||
* up being rejected by the mempool. | |||||
*/ | |||||
static bool | static bool | ||||
AcceptToMemoryPoolWorker(const Config &config, CTxMemPool &pool, | AcceptToMemoryPoolWorker(const Config &config, CTxMemPool &pool, | ||||
CValidationState &state, const CTransactionRef &ptx, | CValidationState &state, const CTransactionRef &ptx, | ||||
bool *pfMissingInputs, int64_t nAcceptTime, | bool *pfMissingInputs, int64_t nAcceptTime, | ||||
bool bypass_limits, const Amount nAbsurdFee, | bool bypass_limits, const Amount nAbsurdFee, | ||||
std::vector<COutPoint> &coins_to_uncache, | std::vector<COutPoint> &coins_to_uncache, | ||||
bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | for (const CTxIn &txin : tx.vin) { | ||||
view.SetBackend(viewMemPool); | view.SetBackend(viewMemPool); | ||||
// Do all inputs exist? | // Do all inputs exist? | ||||
for (const CTxIn &txin : tx.vin) { | for (const CTxIn &txin : tx.vin) { | ||||
if (!pcoinsTip->HaveCoinInCache(txin.prevout)) { | if (!pcoinsTip->HaveCoinInCache(txin.prevout)) { | ||||
coins_to_uncache.push_back(txin.prevout); | coins_to_uncache.push_back(txin.prevout); | ||||
} | } | ||||
// Note: this call may add txin.prevout to the coins cache | |||||
// (pcoinsTip.cacheCoins) by way of FetchCoin(). It should be | |||||
// removed later (via coins_to_uncache) if this tx turns out to be | |||||
// invalid. | |||||
if (!view.HaveCoin(txin.prevout)) { | if (!view.HaveCoin(txin.prevout)) { | ||||
// Are inputs missing because we already have the tx? | // Are inputs missing because we already have the tx? | ||||
for (size_t out = 0; out < tx.vout.size(); out++) { | for (size_t out = 0; out < tx.vout.size(); out++) { | ||||
// Optimistically just do efficient check of cache for | // Optimistically just do efficient check of cache for | ||||
// outputs. | // outputs. | ||||
if (pcoinsTip->HaveCoinInCache(COutPoint(txid, out))) { | if (pcoinsTip->HaveCoinInCache(COutPoint(txid, out))) { | ||||
return state.Invalid( | return state.Invalid( | ||||
ValidationInvalidReason::TX_CONFLICT, false, | ValidationInvalidReason::TX_CONFLICT, false, | ||||
▲ Show 20 Lines • Show All 210 Lines • ▼ Show 20 Lines | AcceptToMemoryPoolWithTime(const Config &config, CTxMemPool &pool, | ||||
bool bypass_limits, const Amount nAbsurdFee, | bool bypass_limits, const Amount nAbsurdFee, | ||||
bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
std::vector<COutPoint> coins_to_uncache; | std::vector<COutPoint> coins_to_uncache; | ||||
bool res = AcceptToMemoryPoolWorker( | bool res = AcceptToMemoryPoolWorker( | ||||
config, pool, state, tx, pfMissingInputs, nAcceptTime, bypass_limits, | config, pool, state, tx, pfMissingInputs, nAcceptTime, bypass_limits, | ||||
nAbsurdFee, coins_to_uncache, test_accept); | nAbsurdFee, coins_to_uncache, test_accept); | ||||
if (!res) { | if (!res) { | ||||
// Remove coins that were not present in the coins cache before calling | |||||
// ATMPW; this is to prevent memory DoS in case we receive a large | |||||
// number of invalid transactions that attempt to overrun the in-memory | |||||
// coins cache | |||||
// (`CCoinsViewCache::cacheCoins`). | |||||
for (const COutPoint &outpoint : coins_to_uncache) { | for (const COutPoint &outpoint : coins_to_uncache) { | ||||
pcoinsTip->Uncache(outpoint); | pcoinsTip->Uncache(outpoint); | ||||
} | } | ||||
} | } | ||||
// After we've (potentially) uncached entries, ensure our coins cache is | // After we've (potentially) uncached entries, ensure our coins cache is | ||||
// still within its size limits | // still within its size limits | ||||
CValidationState stateDummy; | CValidationState stateDummy; | ||||
▲ Show 20 Lines • Show All 5,008 Lines • Show Last 20 Lines |