mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
validation: Add chainstate member to MemPoolAccept
This commit is contained in:
parent
4c15942b79
commit
d8a816329c
@ -458,11 +458,13 @@ namespace {
|
||||
class MemPoolAccept
|
||||
{
|
||||
public:
|
||||
explicit MemPoolAccept(CTxMemPool& mempool) : m_pool(mempool), m_view(&m_dummy), m_viewmempool(&::ChainstateActive().CoinsTip(), m_pool),
|
||||
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),
|
||||
m_limit_ancestors(gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT)),
|
||||
m_limit_ancestor_size(gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000),
|
||||
m_limit_descendants(gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT)),
|
||||
m_limit_descendant_size(gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000) {}
|
||||
m_limit_descendant_size(gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000) {
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(m_active_chainstate));
|
||||
}
|
||||
|
||||
// We put the arguments we're handed into a struct, so we can pass them
|
||||
// around easier.
|
||||
@ -547,6 +549,8 @@ private:
|
||||
CCoinsViewMemPool m_viewmempool;
|
||||
CCoinsView m_dummy;
|
||||
|
||||
CChainState& m_active_chainstate;
|
||||
|
||||
// The package limits in effect at the time of invocation.
|
||||
const size_t m_limit_ancestors;
|
||||
const size_t m_limit_ancestor_size;
|
||||
@ -601,7 +605,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
// Only accept nLockTime-using transactions that can be mined in the next
|
||||
// block; we don't want our mempool filled up with transactions that can't
|
||||
// be mined yet.
|
||||
if (!CheckFinalTx(::ChainActive().Tip(), tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
|
||||
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
|
||||
if (!CheckFinalTx(m_active_chainstate.m_chain.Tip(), tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
|
||||
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
|
||||
|
||||
// is it already in the memory pool?
|
||||
@ -649,7 +654,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
LockPoints lp;
|
||||
m_view.SetBackend(m_viewmempool);
|
||||
|
||||
const CCoinsViewCache& coins_cache = ::ChainstateActive().CoinsTip();
|
||||
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(m_active_chainstate.CoinsTip()));
|
||||
const CCoinsViewCache& coins_cache = m_active_chainstate.CoinsTip();
|
||||
// do all inputs exist?
|
||||
for (const CTxIn& txin : tx.vin) {
|
||||
if (!coins_cache.HaveCoinInCache(txin.prevout)) {
|
||||
@ -685,16 +691,19 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
// be mined yet.
|
||||
// Must keep pool.cs for this unless we change CheckSequenceLocks to take a
|
||||
// CoinsViewCache instead of create its own
|
||||
if (!CheckSequenceLocks(::ChainstateActive(), m_pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(m_active_chainstate));
|
||||
if (!CheckSequenceLocks(m_active_chainstate, m_pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
|
||||
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final");
|
||||
|
||||
if (!Consensus::CheckTxInputs(tx, state, m_view, g_chainman.m_blockman.GetSpendHeight(m_view), ws.m_base_fees)) {
|
||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(m_active_chainstate.m_blockman));
|
||||
if (!Consensus::CheckTxInputs(tx, state, m_view, m_active_chainstate.m_blockman.GetSpendHeight(m_view), ws.m_base_fees)) {
|
||||
return false; // state filled in by CheckTxInputs
|
||||
}
|
||||
|
||||
// Check for non-standard pay-to-script-hash in inputs
|
||||
const auto& params = args.m_chainparams.GetConsensus();
|
||||
auto taproot_state = VersionBitsState(::ChainActive().Tip(), params, Consensus::DEPLOYMENT_TAPROOT, versionbitscache);
|
||||
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
|
||||
auto taproot_state = VersionBitsState(m_active_chainstate.m_chain.Tip(), params, Consensus::DEPLOYMENT_TAPROOT, versionbitscache);
|
||||
if (fRequireStandard && !AreInputsStandard(tx, m_view, taproot_state == ThresholdState::ACTIVE)) {
|
||||
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs");
|
||||
}
|
||||
@ -720,7 +729,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
}
|
||||
}
|
||||
|
||||
entry.reset(new CTxMemPoolEntry(ptx, ws.m_base_fees, nAcceptTime, ::ChainActive().Height(),
|
||||
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
|
||||
entry.reset(new CTxMemPoolEntry(ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(),
|
||||
fSpendsCoinbase, nSigOpsCost, lp));
|
||||
unsigned int nSize = entry->GetTxSize();
|
||||
|
||||
@ -972,8 +982,10 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws, P
|
||||
// There is a similar check in CreateNewBlock() to prevent creating
|
||||
// invalid blocks (using TestBlockValidity), however allowing such
|
||||
// transactions into the mempool can be exploited as a DoS attack.
|
||||
unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(::ChainActive().Tip(), chainparams.GetConsensus());
|
||||
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, txdata, ::ChainstateActive().CoinsTip())) {
|
||||
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
|
||||
unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(m_active_chainstate.m_chain.Tip(), chainparams.GetConsensus());
|
||||
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(m_active_chainstate.CoinsTip()));
|
||||
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, txdata, m_active_chainstate.CoinsTip())) {
|
||||
return error("%s: BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s",
|
||||
__func__, hash.ToString(), state.ToString());
|
||||
}
|
||||
@ -1013,14 +1025,16 @@ bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws)
|
||||
// - it's not being re-added during a reorg which bypasses typical mempool fee limits
|
||||
// - the node is not behind
|
||||
// - the transaction is not dependent on any other transactions in the mempool
|
||||
bool validForFeeEstimation = !fReplacementTransaction && !bypass_limits && IsCurrentForFeeEstimation(::ChainstateActive()) && m_pool.HasNoInputsOf(tx);
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(m_active_chainstate));
|
||||
bool validForFeeEstimation = !fReplacementTransaction && !bypass_limits && IsCurrentForFeeEstimation(m_active_chainstate) && m_pool.HasNoInputsOf(tx);
|
||||
|
||||
// Store transaction in memory
|
||||
m_pool.addUnchecked(*entry, setAncestors, validForFeeEstimation);
|
||||
|
||||
// trim mempool and check if tx was trimmed
|
||||
if (!bypass_limits) {
|
||||
LimitMempoolSize(m_pool, ::ChainstateActive().CoinsTip(), gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
|
||||
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(m_active_chainstate.CoinsTip()));
|
||||
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip(), gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
|
||||
if (!m_pool.exists(hash))
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool full");
|
||||
}
|
||||
@ -1069,7 +1083,7 @@ static MempoolAcceptResult AcceptToMemoryPoolWithTime(const CChainParams& chainp
|
||||
std::vector<COutPoint> coins_to_uncache;
|
||||
MemPoolAccept::ATMPArgs args { chainparams, nAcceptTime, bypass_limits, coins_to_uncache, test_accept };
|
||||
|
||||
const MempoolAcceptResult result = MemPoolAccept(pool).AcceptSingleTransaction(tx, args);
|
||||
const MempoolAcceptResult result = MemPoolAccept(pool, ::ChainstateActive()).AcceptSingleTransaction(tx, args);
|
||||
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
|
||||
// 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
|
||||
|
Loading…
Reference in New Issue
Block a user