Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 362 Lines • ▼ Show 20 Lines | struct ATMPArgs { | ||||
* Return any outpoints which were not previously present in the coins | * Return any outpoints which were not previously present in the coins | ||||
* cache, but were added as a result of validating the tx for mempool | * cache, but were added as a result of validating the tx for mempool | ||||
* acceptance. This allows the caller to optionally remove the cache | * acceptance. This allows the caller to optionally remove the cache | ||||
* additions if the associated transaction ends up being rejected by | * additions if the associated transaction ends up being rejected by | ||||
* the mempool. | * the mempool. | ||||
*/ | */ | ||||
std::vector<COutPoint> &m_coins_to_uncache; | std::vector<COutPoint> &m_coins_to_uncache; | ||||
const bool m_test_accept; | const bool m_test_accept; | ||||
Amount *m_fee_out; | |||||
}; | }; | ||||
// Single transaction acceptance | // Single transaction acceptance | ||||
bool AcceptSingleTransaction(const CTransactionRef &ptx, ATMPArgs &args) | bool AcceptSingleTransaction(const CTransactionRef &ptx, ATMPArgs &args) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
private: | private: | ||||
// All the intermediate state that gets passed between the various levels | // All the intermediate state that gets passed between the various levels | ||||
▲ Show 20 Lines • Show All 171 Lines • ▼ Show 20 Lines | bool MemPoolAccept::PreChecks(ATMPArgs &args, Workspace &ws) { | ||||
Amount nFees = Amount::zero(); | Amount nFees = Amount::zero(); | ||||
if (!Consensus::CheckTxInputs(tx, state, m_view, GetSpendHeight(m_view), | if (!Consensus::CheckTxInputs(tx, state, m_view, GetSpendHeight(m_view), | ||||
nFees)) { | nFees)) { | ||||
// state filled in by CheckTxInputs | // state filled in by CheckTxInputs | ||||
return false; | return false; | ||||
} | } | ||||
// If fee_out is passed, return the fee to the caller | |||||
if (args.m_fee_out) { | |||||
*args.m_fee_out = nFees; | |||||
} | |||||
// Check for non-standard pay-to-script-hash in inputs | // Check for non-standard pay-to-script-hash in inputs | ||||
if (fRequireStandard && | if (fRequireStandard && | ||||
!AreInputsStandard(tx, m_view, ws.m_next_block_script_verify_flags)) { | !AreInputsStandard(tx, m_view, ws.m_next_block_script_verify_flags)) { | ||||
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, | return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, | ||||
"bad-txns-nonstandard-inputs"); | "bad-txns-nonstandard-inputs"); | ||||
} | } | ||||
// nModifiedFees includes any fee deltas from PrioritiseTransaction | // nModifiedFees includes any fee deltas from PrioritiseTransaction | ||||
▲ Show 20 Lines • Show All 173 Lines • ▼ Show 20 Lines | bool MemPoolAccept::AcceptSingleTransaction(const CTransactionRef &ptx, | ||||
return true; | return true; | ||||
} | } | ||||
} // namespace | } // namespace | ||||
/** | /** | ||||
* (try to) add transaction to memory pool with a specified acceptance time. | * (try to) add transaction to memory pool with a specified acceptance time. | ||||
*/ | */ | ||||
static bool | static bool AcceptToMemoryPoolWithTime( | ||||
AcceptToMemoryPoolWithTime(const Config &config, CTxMemPool &pool, | const Config &config, CTxMemPool &pool, TxValidationState &state, | ||||
TxValidationState &state, const CTransactionRef &tx, | const CTransactionRef &tx, int64_t nAcceptTime, bool bypass_limits, | ||||
int64_t nAcceptTime, bool bypass_limits, | const Amount nAbsurdFee, bool test_accept, Amount *fee_out = nullptr) | ||||
const Amount nAbsurdFee, bool test_accept) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
std::vector<COutPoint> coins_to_uncache; | std::vector<COutPoint> coins_to_uncache; | ||||
MemPoolAccept::ATMPArgs args{config, state, nAcceptTime, | MemPoolAccept::ATMPArgs args{config, state, nAcceptTime, | ||||
bypass_limits, nAbsurdFee, coins_to_uncache, | bypass_limits, nAbsurdFee, coins_to_uncache, | ||||
test_accept}; | test_accept, fee_out}; | ||||
bool res = MemPoolAccept(pool).AcceptSingleTransaction(tx, args); | bool res = MemPoolAccept(pool).AcceptSingleTransaction(tx, args); | ||||
if (!res) { | if (!res) { | ||||
// Remove coins that were not present in the coins cache before calling | // 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 | // ATMPW; this is to prevent memory DoS in case we receive a large | ||||
// number of invalid transactions that attempt to overrun the in-memory | // number of invalid transactions that attempt to overrun the in-memory | ||||
// coins cache | // coins cache | ||||
// (`CCoinsViewCache::cacheCoins`). | // (`CCoinsViewCache::cacheCoins`). | ||||
for (const COutPoint &outpoint : coins_to_uncache) { | for (const COutPoint &outpoint : coins_to_uncache) { | ||||
::ChainstateActive().CoinsTip().Uncache(outpoint); | ::ChainstateActive().CoinsTip().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 | ||||
BlockValidationState stateDummy; | BlockValidationState stateDummy; | ||||
::ChainstateActive().FlushStateToDisk(config.GetChainParams(), stateDummy, | ::ChainstateActive().FlushStateToDisk(config.GetChainParams(), stateDummy, | ||||
FlushStateMode::PERIODIC); | FlushStateMode::PERIODIC); | ||||
return res; | return res; | ||||
} | } | ||||
bool AcceptToMemoryPool(const Config &config, CTxMemPool &pool, | bool AcceptToMemoryPool(const Config &config, CTxMemPool &pool, | ||||
TxValidationState &state, const CTransactionRef &tx, | TxValidationState &state, const CTransactionRef &tx, | ||||
bool bypass_limits, const Amount nAbsurdFee, | bool bypass_limits, const Amount nAbsurdFee, | ||||
bool test_accept) { | bool test_accept, Amount *fee_out) { | ||||
return AcceptToMemoryPoolWithTime(config, pool, state, tx, GetTime(), | return AcceptToMemoryPoolWithTime(config, pool, state, tx, GetTime(), | ||||
bypass_limits, nAbsurdFee, test_accept); | bypass_limits, nAbsurdFee, test_accept, | ||||
fee_out); | |||||
} | } | ||||
CTransactionRef GetTransaction(const CBlockIndex *const block_index, | CTransactionRef GetTransaction(const CBlockIndex *const block_index, | ||||
const CTxMemPool *const mempool, | const CTxMemPool *const mempool, | ||||
const TxId &txid, | const TxId &txid, | ||||
const Consensus::Params &consensusParams, | const Consensus::Params &consensusParams, | ||||
BlockHash &hashBlock) { | BlockHash &hashBlock) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
▲ Show 20 Lines • Show All 5,328 Lines • Show Last 20 Lines |