Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 558 Lines • ▼ Show 20 Lines | for (const auto &txin : tx.vin) { | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
void LimitMempoolSize(CTxMemPool &pool, size_t limit, unsigned long age) { | void LimitMempoolSize(CTxMemPool &pool, size_t limit, unsigned long age) { | ||||
int expired = pool.Expire(GetTime() - age); | int expired = pool.Expire(GetTime() - age); | ||||
if (expired != 0) | if (expired != 0) { | ||||
LogPrint("mempool", "Expired %i transactions from the memory pool\n", | LogPrint("mempool", "Expired %i transactions from the memory pool\n", | ||||
expired); | expired); | ||||
} | |||||
std::vector<uint256> vNoSpendsRemaining; | std::vector<COutPoint> vNoSpendsRemaining; | ||||
pool.TrimToSize(limit, &vNoSpendsRemaining); | pool.TrimToSize(limit, &vNoSpendsRemaining); | ||||
for (const uint256 &removed : vNoSpendsRemaining) { | for (const COutPoint &removed : vNoSpendsRemaining) { | ||||
pcoinsTip->Uncache(removed); | pcoinsTip->Uncache(removed); | ||||
} | } | ||||
} | } | ||||
/** Convert CValidationState to a human-readable message for logging */ | /** Convert CValidationState to a human-readable message for logging */ | ||||
std::string FormatStateMessage(const CValidationState &state) { | std::string FormatStateMessage(const CValidationState &state) { | ||||
return strprintf( | return strprintf( | ||||
"%s%s (code %i)", state.GetRejectReason(), | "%s%s (code %i)", state.GetRejectReason(), | ||||
Show All 28 Lines | bool IsUAHFenabledForCurrentBlock(const Config &config) { | ||||
return IsUAHFenabled(config, chainActive.Tip()); | return IsUAHFenabled(config, chainActive.Tip()); | ||||
} | } | ||||
static bool AcceptToMemoryPoolWorker( | static bool AcceptToMemoryPoolWorker( | ||||
const Config &config, CTxMemPool &pool, CValidationState &state, | const Config &config, CTxMemPool &pool, CValidationState &state, | ||||
const CTransactionRef &ptx, bool fLimitFree, bool *pfMissingInputs, | const CTransactionRef &ptx, bool fLimitFree, bool *pfMissingInputs, | ||||
int64_t nAcceptTime, std::list<CTransactionRef> *plTxnReplaced, | int64_t nAcceptTime, std::list<CTransactionRef> *plTxnReplaced, | ||||
bool fOverrideMempoolLimit, const CAmount &nAbsurdFee, | bool fOverrideMempoolLimit, const CAmount &nAbsurdFee, | ||||
std::vector<uint256> &vHashTxnToUncache) { | std::vector<COutPoint> &coins_to_uncache) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
const CTransaction &tx = *ptx; | const CTransaction &tx = *ptx; | ||||
const uint256 txid = tx.GetId(); | const uint256 txid = tx.GetId(); | ||||
if (pfMissingInputs) { | if (pfMissingInputs) { | ||||
*pfMissingInputs = false; | *pfMissingInputs = false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | // Check for conflicts with in-memory transactions | ||||
{ | { | ||||
LOCK(pool.cs); | LOCK(pool.cs); | ||||
CCoinsViewMemPool viewMemPool(pcoinsTip, pool); | CCoinsViewMemPool viewMemPool(pcoinsTip, pool); | ||||
view.SetBackend(viewMemPool); | view.SetBackend(viewMemPool); | ||||
// Do we already have it? | // Do we already have it? | ||||
for (size_t out = 0; out < tx.vout.size(); out++) { | for (size_t out = 0; out < tx.vout.size(); out++) { | ||||
COutPoint outpoint(txid, out); | COutPoint outpoint(txid, out); | ||||
bool fHadTxInCache = pcoinsTip->HaveCoinInCache(outpoint); | bool had_coin_in_cache = pcoinsTip->HaveCoinInCache(outpoint); | ||||
if (view.HaveCoin(outpoint)) { | if (view.HaveCoin(outpoint)) { | ||||
if (!fHadTxInCache) { | if (!had_coin_in_cache) { | ||||
vHashTxnToUncache.push_back(txid); | coins_to_uncache.push_back(outpoint); | ||||
} | } | ||||
return state.Invalid(false, REJECT_ALREADY_KNOWN, | return state.Invalid(false, REJECT_ALREADY_KNOWN, | ||||
"txn-already-known"); | "txn-already-known"); | ||||
} | } | ||||
} | } | ||||
// Do all inputs exist? Note that this does not check for the | // Do all inputs exist? | ||||
// presence of actual outputs (see the next check for that), and | |||||
// only helps with filling in pfMissingInputs (to determine missing | |||||
// vs spent). | |||||
for (const CTxIn txin : tx.vin) { | for (const CTxIn txin : tx.vin) { | ||||
if (!pcoinsTip->HaveCoinInCache(txin.prevout)) { | if (!pcoinsTip->HaveCoinInCache(txin.prevout)) { | ||||
vHashTxnToUncache.push_back(txin.prevout.hash); | coins_to_uncache.push_back(txin.prevout); | ||||
} | } | ||||
if (!view.HaveCoin(txin.prevout)) { | if (!view.HaveCoin(txin.prevout)) { | ||||
if (pfMissingInputs) { | if (pfMissingInputs) { | ||||
*pfMissingInputs = true; | *pfMissingInputs = true; | ||||
} | } | ||||
// fMissingInputs and !state.IsInvalid() is used to detect | // fMissingInputs and !state.IsInvalid() is used to detect | ||||
▲ Show 20 Lines • Show All 205 Lines • ▼ Show 20 Lines | static bool AcceptToMemoryPoolWorker( | ||||
} | } | ||||
GetMainSignals().SyncTransaction( | GetMainSignals().SyncTransaction( | ||||
tx, nullptr, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK); | tx, nullptr, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK); | ||||
return true; | return true; | ||||
} | } | ||||
bool AcceptToMemoryPoolWithTime(const Config &config, CTxMemPool &pool, | static bool AcceptToMemoryPoolWithTime( | ||||
CValidationState &state, | const Config &config, CTxMemPool &pool, CValidationState &state, | ||||
const CTransactionRef &tx, bool fLimitFree, | const CTransactionRef &tx, bool fLimitFree, bool *pfMissingInputs, | ||||
bool *pfMissingInputs, int64_t nAcceptTime, | int64_t nAcceptTime, std::list<CTransactionRef> *plTxnReplaced = nullptr, | ||||
std::list<CTransactionRef> *plTxnReplaced, | bool fOverrideMempoolLimit = false, const CAmount nAbsurdFee = 0) { | ||||
bool fOverrideMempoolLimit, | std::vector<COutPoint> coins_to_uncache; | ||||
const CAmount nAbsurdFee) { | |||||
std::vector<uint256> vHashTxToUncache; | |||||
bool res = AcceptToMemoryPoolWorker( | bool res = AcceptToMemoryPoolWorker( | ||||
config, pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, | config, pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, | ||||
plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee, vHashTxToUncache); | plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache); | ||||
if (!res) { | if (!res) { | ||||
for (const uint256 &txid : vHashTxToUncache) { | for (const COutPoint &outpoint : coins_to_uncache) { | ||||
pcoinsTip->Uncache(txid); | 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; | ||||
FlushStateToDisk(stateDummy, FLUSH_STATE_PERIODIC); | FlushStateToDisk(stateDummy, FLUSH_STATE_PERIODIC); | ||||
return res; | return res; | ||||
} | } | ||||
bool AcceptToMemoryPool(const Config &config, CTxMemPool &pool, | bool AcceptToMemoryPool(const Config &config, CTxMemPool &pool, | ||||
▲ Show 20 Lines • Show All 3,863 Lines • Show Last 20 Lines |