Skip to content

Commit d8a8163

Browse files
committed
validation: Add chainstate member to MemPoolAccept
1 parent 4c15942 commit d8a8163

File tree

1 file changed

+27
-13
lines changed

1 file changed

+27
-13
lines changed

src/validation.cpp

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -458,11 +458,13 @@ namespace {
458458
class MemPoolAccept
459459
{
460460
public:
461-
explicit MemPoolAccept(CTxMemPool& mempool) : m_pool(mempool), m_view(&m_dummy), m_viewmempool(&::ChainstateActive().CoinsTip(), m_pool),
461+
explicit MemPoolAccept(CTxMemPool& mempool, CChainState& active_chainstate) : m_pool(mempool), m_view(&m_dummy), m_viewmempool(&active_chainstate.CoinsTip(), m_pool), m_active_chainstate(active_chainstate),
462462
m_limit_ancestors(gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT)),
463463
m_limit_ancestor_size(gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000),
464464
m_limit_descendants(gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT)),
465-
m_limit_descendant_size(gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000) {}
465+
m_limit_descendant_size(gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000) {
466+
assert(std::addressof(::ChainstateActive()) == std::addressof(m_active_chainstate));
467+
}
466468

467469
// We put the arguments we're handed into a struct, so we can pass them
468470
// around easier.
@@ -547,6 +549,8 @@ class MemPoolAccept
547549
CCoinsViewMemPool m_viewmempool;
548550
CCoinsView m_dummy;
549551

552+
CChainState& m_active_chainstate;
553+
550554
// The package limits in effect at the time of invocation.
551555
const size_t m_limit_ancestors;
552556
const size_t m_limit_ancestor_size;
@@ -601,7 +605,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
601605
// Only accept nLockTime-using transactions that can be mined in the next
602606
// block; we don't want our mempool filled up with transactions that can't
603607
// be mined yet.
604-
if (!CheckFinalTx(::ChainActive().Tip(), tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
608+
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
609+
if (!CheckFinalTx(m_active_chainstate.m_chain.Tip(), tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
605610
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
606611

607612
// is it already in the memory pool?
@@ -649,7 +654,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
649654
LockPoints lp;
650655
m_view.SetBackend(m_viewmempool);
651656

652-
const CCoinsViewCache& coins_cache = ::ChainstateActive().CoinsTip();
657+
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(m_active_chainstate.CoinsTip()));
658+
const CCoinsViewCache& coins_cache = m_active_chainstate.CoinsTip();
653659
// do all inputs exist?
654660
for (const CTxIn& txin : tx.vin) {
655661
if (!coins_cache.HaveCoinInCache(txin.prevout)) {
@@ -685,16 +691,19 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
685691
// be mined yet.
686692
// Must keep pool.cs for this unless we change CheckSequenceLocks to take a
687693
// CoinsViewCache instead of create its own
688-
if (!CheckSequenceLocks(::ChainstateActive(), m_pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
694+
assert(std::addressof(::ChainstateActive()) == std::addressof(m_active_chainstate));
695+
if (!CheckSequenceLocks(m_active_chainstate, m_pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
689696
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final");
690697

691-
if (!Consensus::CheckTxInputs(tx, state, m_view, g_chainman.m_blockman.GetSpendHeight(m_view), ws.m_base_fees)) {
698+
assert(std::addressof(g_chainman.m_blockman) == std::addressof(m_active_chainstate.m_blockman));
699+
if (!Consensus::CheckTxInputs(tx, state, m_view, m_active_chainstate.m_blockman.GetSpendHeight(m_view), ws.m_base_fees)) {
692700
return false; // state filled in by CheckTxInputs
693701
}
694702

695703
// Check for non-standard pay-to-script-hash in inputs
696704
const auto& params = args.m_chainparams.GetConsensus();
697-
auto taproot_state = VersionBitsState(::ChainActive().Tip(), params, Consensus::DEPLOYMENT_TAPROOT, versionbitscache);
705+
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
706+
auto taproot_state = VersionBitsState(m_active_chainstate.m_chain.Tip(), params, Consensus::DEPLOYMENT_TAPROOT, versionbitscache);
698707
if (fRequireStandard && !AreInputsStandard(tx, m_view, taproot_state == ThresholdState::ACTIVE)) {
699708
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs");
700709
}
@@ -720,7 +729,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
720729
}
721730
}
722731

723-
entry.reset(new CTxMemPoolEntry(ptx, ws.m_base_fees, nAcceptTime, ::ChainActive().Height(),
732+
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
733+
entry.reset(new CTxMemPoolEntry(ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(),
724734
fSpendsCoinbase, nSigOpsCost, lp));
725735
unsigned int nSize = entry->GetTxSize();
726736

@@ -972,8 +982,10 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws, P
972982
// There is a similar check in CreateNewBlock() to prevent creating
973983
// invalid blocks (using TestBlockValidity), however allowing such
974984
// transactions into the mempool can be exploited as a DoS attack.
975-
unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(::ChainActive().Tip(), chainparams.GetConsensus());
976-
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, txdata, ::ChainstateActive().CoinsTip())) {
985+
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
986+
unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(m_active_chainstate.m_chain.Tip(), chainparams.GetConsensus());
987+
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(m_active_chainstate.CoinsTip()));
988+
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, txdata, m_active_chainstate.CoinsTip())) {
977989
return error("%s: BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s",
978990
__func__, hash.ToString(), state.ToString());
979991
}
@@ -1013,14 +1025,16 @@ bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws)
10131025
// - it's not being re-added during a reorg which bypasses typical mempool fee limits
10141026
// - the node is not behind
10151027
// - the transaction is not dependent on any other transactions in the mempool
1016-
bool validForFeeEstimation = !fReplacementTransaction && !bypass_limits && IsCurrentForFeeEstimation(::ChainstateActive()) && m_pool.HasNoInputsOf(tx);
1028+
assert(std::addressof(::ChainstateActive()) == std::addressof(m_active_chainstate));
1029+
bool validForFeeEstimation = !fReplacementTransaction && !bypass_limits && IsCurrentForFeeEstimation(m_active_chainstate) && m_pool.HasNoInputsOf(tx);
10171030

10181031
// Store transaction in memory
10191032
m_pool.addUnchecked(*entry, setAncestors, validForFeeEstimation);
10201033

10211034
// trim mempool and check if tx was trimmed
10221035
if (!bypass_limits) {
1023-
LimitMempoolSize(m_pool, ::ChainstateActive().CoinsTip(), gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
1036+
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(m_active_chainstate.CoinsTip()));
1037+
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip(), gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
10241038
if (!m_pool.exists(hash))
10251039
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool full");
10261040
}
@@ -1069,7 +1083,7 @@ static MempoolAcceptResult AcceptToMemoryPoolWithTime(const CChainParams& chainp
10691083
std::vector<COutPoint> coins_to_uncache;
10701084
MemPoolAccept::ATMPArgs args { chainparams, nAcceptTime, bypass_limits, coins_to_uncache, test_accept };
10711085

1072-
const MempoolAcceptResult result = MemPoolAccept(pool).AcceptSingleTransaction(tx, args);
1086+
const MempoolAcceptResult result = MemPoolAccept(pool, ::ChainstateActive()).AcceptSingleTransaction(tx, args);
10731087
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
10741088
// Remove coins that were not present in the coins cache before calling ATMPW;
10751089
// this is to prevent memory DoS in case we receive a large number of

0 commit comments

Comments
 (0)