@@ -404,36 +404,41 @@ static void UpdateMempoolForReorg(CTxMemPool& mempool, DisconnectedBlockTransact
404
404
LimitMempoolSize (mempool, gArgs .GetArg (" -maxmempool" , DEFAULT_MAX_MEMPOOL_SIZE) * 1000000 , std::chrono::hours{gArgs .GetArg (" -mempoolexpiry" , DEFAULT_MEMPOOL_EXPIRY)});
405
405
}
406
406
407
- // Used to avoid mempool polluting consensus critical paths if CCoinsViewMempool
408
- // were somehow broken and returning the wrong scriptPubKeys
409
- static bool CheckInputsFromMempoolAndCache (const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& view, const CTxMemPool& pool,
410
- unsigned int flags, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
407
+ /* *
408
+ * Checks to avoid mempool polluting consensus critical paths since cached
409
+ * signature and script validity results will be reused if we validate this
410
+ * transaction again during block validation.
411
+ * */
412
+ static bool CheckInputsFromMempoolAndCache (const CTransaction& tx, TxValidationState& state,
413
+ const CCoinsViewCache& view, const CTxMemPool& pool,
414
+ unsigned int flags, PrecomputedTransactionData& txdata)
415
+ EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
416
+ {
411
417
AssertLockHeld (cs_main);
412
-
413
- // pool.cs should be locked already, but go ahead and re-take the lock here
414
- // to enforce that mempool doesn't change between when we check the view
415
- // and when we actually call through to CheckInputScripts
416
- LOCK (pool.cs );
418
+ AssertLockHeld (pool.cs );
417
419
418
420
assert (!tx.IsCoinBase ());
419
421
for (const CTxIn& txin : tx.vin ) {
420
422
const Coin& coin = view.AccessCoin (txin.prevout );
421
423
422
- // AcceptToMemoryPoolWorker has already checked that the coins are
423
- // available, so this shouldn't fail. If the inputs are not available
424
- // here then return false.
424
+ // This coin was checked in PreChecks and MemPoolAccept
425
+ // has been holding cs_main since then.
426
+ Assume (!coin. IsSpent ());
425
427
if (coin.IsSpent ()) return false ;
426
428
427
- // Check equivalence for available inputs.
429
+ // If the Coin is available, there are 2 possibilities:
430
+ // it is available in our current ChainstateActive UTXO set,
431
+ // or it's a UTXO provided by a transaction in our mempool.
432
+ // Ensure the scriptPubKeys in Coins from CoinsView are correct.
428
433
const CTransactionRef& txFrom = pool.get (txin.prevout .hash );
429
434
if (txFrom) {
430
435
assert (txFrom->GetHash () == txin.prevout .hash );
431
436
assert (txFrom->vout .size () > txin.prevout .n );
432
437
assert (txFrom->vout [txin.prevout .n ] == coin.out );
433
438
} else {
434
- const Coin& coinFromDisk = ::ChainstateActive ().CoinsTip ().AccessCoin (txin.prevout );
435
- assert (!coinFromDisk .IsSpent ());
436
- assert (coinFromDisk .out == coin.out );
439
+ const Coin& coinFromUTXOSet = ::ChainstateActive ().CoinsTip ().AccessCoin (txin.prevout );
440
+ assert (!coinFromUTXOSet .IsSpent ());
441
+ assert (coinFromUTXOSet .out == coin.out );
437
442
}
438
443
}
439
444
@@ -502,21 +507,21 @@ class MemPoolAccept
502
507
503
508
// Run the script checks using our policy flags. As this can be slow, we should
504
509
// only invoke this on transactions that have otherwise passed policy checks.
505
- bool PolicyScriptChecks (ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
510
+ bool PolicyScriptChecks (ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs );
506
511
507
512
// Re-run the script checks, using consensus flags, and try to cache the
508
513
// result in the scriptcache. This should be done after
509
514
// PolicyScriptChecks(). This requires that all inputs either be in our
510
515
// utxo set or in the mempool.
511
- bool ConsensusScriptChecks (ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData &txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
516
+ bool ConsensusScriptChecks (ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData &txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs );
512
517
513
518
// Try to add the transaction to the mempool, removing any conflicts first.
514
519
// Returns true if the transaction is in the mempool after any size
515
520
// limiting is performed, false otherwise.
516
521
bool Finalize (ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
517
522
518
523
// Compare a package's feerate against minimum allowed.
519
- bool CheckFeeRate (size_t package_size, CAmount package_fee, TxValidationState& state)
524
+ bool CheckFeeRate (size_t package_size, CAmount package_fee, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs)
520
525
{
521
526
CAmount mempoolRejectFee = m_pool.GetMinFee (gArgs .GetArg (" -maxmempool" , DEFAULT_MAX_MEMPOOL_SIZE) * 1000000 ).GetFee (package_size);
522
527
if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) {
0 commit comments