mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
merge bitcoin#20750: Prune g_chainman usage in mempool-related validation functions
This commit is contained in:
parent
228a7fb4a1
commit
30191be0b1
@ -41,7 +41,7 @@ static void AssembleBlock(benchmark::Bench& bench)
|
||||
|
||||
for (const auto& txr : txs) {
|
||||
CValidationState state;
|
||||
bool ret{::AcceptToMemoryPool(*test_setup.m_node.mempool, state, txr, nullptr /* pfMissingInputs */, false /* bypass_limits */, /* nAbsurdFee */ 0)};
|
||||
bool ret{::AcceptToMemoryPool(::ChainstateActive(), *test_setup.m_node.mempool, state, txr, nullptr /* pfMissingInputs */, false /* bypass_limits */, /* nAbsurdFee */ 0)};
|
||||
assert(ret);
|
||||
}
|
||||
}
|
||||
|
@ -352,7 +352,7 @@ bool CCoinJoin::IsCollateralValid(CTxMemPool& mempool, const CTransaction& txCol
|
||||
{
|
||||
LOCK(cs_main);
|
||||
CValidationState validationState;
|
||||
if (!AcceptToMemoryPool(mempool, validationState, MakeTransactionRef(txCollateral), /*pfMissingInputs=*/nullptr, /*bypass_limits=*/false, /*nAbsurdFee=*/DEFAULT_MAX_RAW_TX_FEE, /*test_accept=*/true)) {
|
||||
if (!AcceptToMemoryPool(::ChainstateActive(), mempool, validationState, MakeTransactionRef(txCollateral), /*pfMissingInputs=*/nullptr, /*bypass_limits=*/false, /*nAbsurdFee=*/DEFAULT_MAX_RAW_TX_FEE, /*test_accept=*/true)) {
|
||||
LogPrint(BCLog::COINJOIN, "CCoinJoin::IsCollateralValid -- didn't pass AcceptToMemoryPool()\n");
|
||||
return false;
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ void CCoinJoinServer::CommitFinalTransaction()
|
||||
TRY_LOCK(cs_main, lockMain);
|
||||
CValidationState validationState;
|
||||
mempool.PrioritiseTransaction(hashTx, 0.1 * COIN);
|
||||
if (!lockMain || !AcceptToMemoryPool(mempool, validationState, finalTransaction, nullptr /* pfMissingInputs */, false /* bypass_limits */, DEFAULT_MAX_RAW_TX_FEE /* nAbsurdFee */)) {
|
||||
if (!lockMain || !AcceptToMemoryPool(::ChainstateActive(), mempool, validationState, finalTransaction, nullptr /* pfMissingInputs */, false /* bypass_limits */, DEFAULT_MAX_RAW_TX_FEE /* nAbsurdFee */)) {
|
||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CommitFinalTransaction -- AcceptToMemoryPool() error: Transaction not valid\n");
|
||||
WITH_LOCK(cs_coinjoin, SetNull());
|
||||
// not much we can do in this case, just notify clients
|
||||
@ -455,7 +455,7 @@ void CCoinJoinServer::ConsumeCollateral(const CTransactionRef& txref) const
|
||||
{
|
||||
LOCK(cs_main);
|
||||
CValidationState validationState;
|
||||
if (!AcceptToMemoryPool(mempool, validationState, txref, nullptr /* pfMissingInputs */, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
|
||||
if (!AcceptToMemoryPool(::ChainstateActive(), mempool, validationState, txref, nullptr /* pfMissingInputs */, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
|
||||
LogPrint(BCLog::COINJOIN, "%s -- AcceptToMemoryPool failed\n", __func__);
|
||||
} else {
|
||||
connman.RelayTransaction(*txref);
|
||||
|
@ -239,7 +239,7 @@ public:
|
||||
bool checkFinalTx(const CTransaction& tx) override
|
||||
{
|
||||
LOCK(cs_main);
|
||||
return CheckFinalTx(tx);
|
||||
return CheckFinalTx(::ChainActive().Tip(), tx);
|
||||
}
|
||||
bool findBlock(const uint256& hash, CBlock* block, int64_t* time, int64_t* time_max) override
|
||||
{
|
||||
|
@ -2272,7 +2272,7 @@ void static ProcessOrphanTx(CConnman& connman, CTxMemPool& mempool, std::set<uin
|
||||
CValidationState orphan_state;
|
||||
|
||||
if (setMisbehaving.count(fromPeer)) continue;
|
||||
if (AcceptToMemoryPool(mempool, orphan_state, porphanTx, &fMissingInputs2 /* pfMissingInputs */,
|
||||
if (AcceptToMemoryPool(::ChainstateActive(), mempool, orphan_state, porphanTx, &fMissingInputs2 /* pfMissingInputs */,
|
||||
false /* bypass_limits */, 0 /* nAbsurdFee */)) {
|
||||
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
|
||||
RelayTransaction(orphanTx.GetHash(), connman);
|
||||
@ -3368,7 +3368,7 @@ void PeerLogicValidation::ProcessMessage(
|
||||
bool fMissingInputs = false;
|
||||
CValidationState state;
|
||||
|
||||
if (!AlreadyHave(inv, m_mempool, *m_llmq_ctx) && AcceptToMemoryPool(m_mempool, state, ptx, &fMissingInputs /* pfMissingInputs */,
|
||||
if (!AlreadyHave(inv, m_mempool, *m_llmq_ctx) && AcceptToMemoryPool(::ChainstateActive(), m_mempool, state, ptx, &fMissingInputs /* pfMissingInputs */,
|
||||
false /* bypass_limits */, 0 /* nAbsurdFee */)) {
|
||||
// Process custom txes, this changes AlreadyHave to "true"
|
||||
if (nInvType == MSG_DSTX) {
|
||||
|
@ -38,7 +38,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
|
||||
// Transaction is not already in the mempool. Submit it.
|
||||
CValidationState state;
|
||||
bool fMissingInputs;
|
||||
if (!AcceptToMemoryPool(*node.mempool, state, std::move(tx), &fMissingInputs,
|
||||
if (!AcceptToMemoryPool(::ChainstateActive(), *node.mempool, state, std::move(tx), &fMissingInputs,
|
||||
bypass_limits, max_tx_fee)) {
|
||||
if (state.IsInvalid()) {
|
||||
err_string = FormatStateMessage(state);
|
||||
|
@ -926,7 +926,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
|
||||
bool test_accept_res;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
test_accept_res = AcceptToMemoryPool(mempool, state, std::move(tx), &missing_inputs,
|
||||
test_accept_res = AcceptToMemoryPool(::ChainstateActive(), mempool, state, std::move(tx), &missing_inputs,
|
||||
false /* bypass_limits */, max_raw_tx_fee, /* test_accept */ true);
|
||||
}
|
||||
result_0.pushKV("allowed", test_accept_res);
|
||||
|
@ -35,7 +35,7 @@ struct MinerTestingSetup : public TestingSetup {
|
||||
void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs);
|
||||
bool TestSequenceLocks(const CTransaction& tx, int flags) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs)
|
||||
{
|
||||
return CheckSequenceLocks(*m_node.mempool, tx, flags);
|
||||
return CheckSequenceLocks(::ChainstateActive(), *m_node.mempool, tx, flags);
|
||||
}
|
||||
BlockAssembler AssemblerForTest(const CChainParams& params);
|
||||
};
|
||||
@ -456,7 +456,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||
tx.nLockTime = 0;
|
||||
hash = tx.GetHash();
|
||||
m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||
BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes
|
||||
BOOST_CHECK(CheckFinalTx(::ChainActive().Tip(), CTransaction(tx), flags)); // Locktime passes
|
||||
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
|
||||
BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(::ChainActive().Tip()->nHeight + 2))); // Sequence locks pass on 2nd block
|
||||
|
||||
@ -466,7 +466,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||
prevheights[0] = baseheight + 2;
|
||||
hash = tx.GetHash();
|
||||
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
|
||||
BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes
|
||||
BOOST_CHECK(CheckFinalTx(::ChainActive().Tip(), CTransaction(tx), flags)); // Locktime passes
|
||||
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
|
||||
|
||||
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
|
||||
@ -482,7 +482,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||
tx.nLockTime = ::ChainActive().Tip()->nHeight + 1;
|
||||
hash = tx.GetHash();
|
||||
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
|
||||
BOOST_CHECK(!CheckFinalTx(CTransaction(tx), flags)); // Locktime fails
|
||||
BOOST_CHECK(!CheckFinalTx(::ChainActive().Tip(), CTransaction(tx), flags)); // Locktime fails
|
||||
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
|
||||
BOOST_CHECK(IsFinalTx(CTransaction(tx), ::ChainActive().Tip()->nHeight + 2, ::ChainActive().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
|
||||
|
||||
@ -493,7 +493,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||
prevheights[0] = baseheight + 4;
|
||||
hash = tx.GetHash();
|
||||
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
|
||||
BOOST_CHECK(!CheckFinalTx(CTransaction(tx), flags)); // Locktime fails
|
||||
BOOST_CHECK(!CheckFinalTx(::ChainActive().Tip(), CTransaction(tx), flags)); // Locktime fails
|
||||
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
|
||||
BOOST_CHECK(IsFinalTx(CTransaction(tx), ::ChainActive().Tip()->nHeight + 2, ::ChainActive().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
|
||||
|
||||
@ -502,7 +502,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||
prevheights[0] = ::ChainActive().Tip()->nHeight + 1;
|
||||
tx.nLockTime = 0;
|
||||
tx.vin[0].nSequence = 0;
|
||||
BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes
|
||||
BOOST_CHECK(CheckFinalTx(::ChainActive().Tip(), CTransaction(tx), flags)); // Locktime passes
|
||||
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
|
||||
tx.vin[0].nSequence = 1;
|
||||
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
|
||||
|
@ -38,7 +38,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
|
||||
|
||||
BOOST_CHECK_EQUAL(
|
||||
false,
|
||||
AcceptToMemoryPool(*m_node.mempool, state, MakeTransactionRef(coinbaseTx),
|
||||
AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool, state, MakeTransactionRef(coinbaseTx),
|
||||
nullptr /* pfMissingInputs */,
|
||||
true /* bypass_limits */,
|
||||
0 /* nAbsurdFee */));
|
||||
|
@ -28,7 +28,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
|
||||
LOCK(cs_main);
|
||||
|
||||
CValidationState state;
|
||||
return AcceptToMemoryPool(*m_node.mempool, state, MakeTransactionRef(tx), nullptr /* pfMissingInputs */,
|
||||
return AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool, state, MakeTransactionRef(tx), nullptr /* pfMissingInputs */,
|
||||
true /* bypass_limits */, 0 /* nAbsurdFee */);
|
||||
};
|
||||
|
||||
|
@ -299,6 +299,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
|
||||
CValidationState state;
|
||||
for (const auto& tx : txs) {
|
||||
BOOST_REQUIRE(AcceptToMemoryPool(
|
||||
::ChainstateActive(),
|
||||
*m_node.mempool,
|
||||
state,
|
||||
tx,
|
||||
|
@ -752,7 +752,7 @@ void CTxMemPool::removeRecursive(const CTransaction &origTx, MemPoolRemovalReaso
|
||||
RemoveStaged(setAllRemoves, false, reason);
|
||||
}
|
||||
|
||||
void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
void CTxMemPool::removeForReorg(CChainState& active_chainstate, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
// Remove transactions spending a coinbase which are now immature and no-longer-final transactions
|
||||
AssertLockHeld(cs);
|
||||
@ -760,8 +760,9 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
|
||||
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
||||
const CTransaction& tx = it->GetTx();
|
||||
LockPoints lp = it->GetLockPoints();
|
||||
bool validLP = TestLockPointValidity(&lp);
|
||||
if (!CheckFinalTx(tx, flags) || !CheckSequenceLocks(*this, tx, flags, &lp, validLP)) {
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
||||
bool validLP = TestLockPointValidity(active_chainstate.m_chain, &lp);
|
||||
if (!CheckFinalTx(active_chainstate.m_chain.Tip(), tx, flags) || !CheckSequenceLocks(active_chainstate, *this, tx, flags, &lp, validLP)) {
|
||||
// Note if CheckSequenceLocks fails the LockPoints may still be invalid
|
||||
// So it's critical that we remove the tx and not depend on the LockPoints.
|
||||
txToRemove.insert(it);
|
||||
@ -770,8 +771,9 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
|
||||
indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
|
||||
if (it2 != mapTx.end())
|
||||
continue;
|
||||
const Coin &coin = pcoins->AccessCoin(txin.prevout);
|
||||
const Coin &coin = active_chainstate.CoinsTip().AccessCoin(txin.prevout);
|
||||
if (m_check_ratio != 0) assert(!coin.IsSpent());
|
||||
unsigned int nMemPoolHeight = active_chainstate.m_chain.Tip()->nHeight + 1;
|
||||
if (coin.IsSpent() || (coin.IsCoinBase() && ((signed long)nMemPoolHeight) - coin.nHeight < COINBASE_MATURITY)) {
|
||||
txToRemove.insert(it);
|
||||
break;
|
||||
|
@ -36,6 +36,7 @@
|
||||
class CBLSPublicKey;
|
||||
|
||||
class CBlockIndex;
|
||||
class CChainState;
|
||||
extern CCriticalSection cs_main;
|
||||
|
||||
/** Fake height value used in Coin to signify they are only in the memory pool (since 0.8) */
|
||||
@ -618,7 +619,7 @@ public:
|
||||
bool removeSpentIndex(const uint256 txhash);
|
||||
|
||||
void removeRecursive(const CTransaction& tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
void removeForReorg(const CCoinsViewCache* pcoins, unsigned int nMemPoolHeight, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main);
|
||||
void removeForReorg(CChainState& active_chainstate, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main);
|
||||
void removeConflicts(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
void removeProTxPubKeyConflicts(const CTransaction &tx, const CKeyID &keyId) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
void removeProTxPubKeyConflicts(const CTransaction &tx, const CBLSPublicKey &pubKey) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
|
@ -205,9 +205,10 @@ static FILE* OpenUndoFile(const FlatFilePos &pos, bool fReadOnly = false);
|
||||
static FlatFileSeq BlockFileSeq();
|
||||
static FlatFileSeq UndoFileSeq();
|
||||
|
||||
bool CheckFinalTx(const CTransaction &tx, int flags)
|
||||
bool CheckFinalTx(const CBlockIndex* active_chain_tip, const CTransaction &tx, int flags)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
assert(std::addressof(*::ChainActive().Tip()) == std::addressof(*active_chain_tip));
|
||||
|
||||
// By convention a negative value for flags indicates that the
|
||||
// current network-enforced consensus rules should be used. In
|
||||
@ -223,7 +224,7 @@ bool CheckFinalTx(const CTransaction &tx, int flags)
|
||||
// evaluated is what is used. Thus if we want to know if a
|
||||
// transaction can be part of the *next* block, we need to call
|
||||
// IsFinalTx() with one more than ::ChainActive().Height().
|
||||
const int nBlockHeight = ::ChainActive().Height() + 1;
|
||||
const int nBlockHeight = active_chain_tip->nHeight + 1;
|
||||
|
||||
// BIP113 requires that time-locked transactions have nLockTime set to
|
||||
// less than the median time of the previous block they're contained in.
|
||||
@ -231,13 +232,13 @@ bool CheckFinalTx(const CTransaction &tx, int flags)
|
||||
// chain tip, so we use that to calculate the median time passed to
|
||||
// IsFinalTx() if LOCKTIME_MEDIAN_TIME_PAST is set.
|
||||
const int64_t nBlockTime = (flags & LOCKTIME_MEDIAN_TIME_PAST)
|
||||
? ::ChainActive().Tip()->GetMedianTimePast()
|
||||
? active_chain_tip->GetMedianTimePast()
|
||||
: GetAdjustedTime();
|
||||
|
||||
return IsFinalTx(tx, nBlockHeight, nBlockTime);
|
||||
}
|
||||
|
||||
bool TestLockPointValidity(const LockPoints* lp)
|
||||
bool TestLockPointValidity(CChain& active_chain, const LockPoints* lp)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
assert(lp);
|
||||
@ -246,7 +247,8 @@ bool TestLockPointValidity(const LockPoints* lp)
|
||||
if (lp->maxInputBlock) {
|
||||
// Check whether ::ChainActive() is an extension of the block at which the LockPoints
|
||||
// calculation was valid. If not LockPoints are no longer valid
|
||||
if (!::ChainActive().Contains(lp->maxInputBlock)) {
|
||||
assert(std::addressof(::ChainActive()) == std::addressof(active_chain));
|
||||
if (!active_chain.Contains(lp->maxInputBlock)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -255,22 +257,28 @@ bool TestLockPointValidity(const LockPoints* lp)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flags, LockPoints* lp, bool useExistingLockPoints)
|
||||
bool CheckSequenceLocks(CChainState& active_chainstate,
|
||||
const CTxMemPool& pool,
|
||||
const CTransaction& tx,
|
||||
int flags,
|
||||
LockPoints* lp,
|
||||
bool useExistingLockPoints)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
AssertLockHeld(pool.cs);
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
||||
|
||||
CBlockIndex* tip = ::ChainActive().Tip();
|
||||
CBlockIndex* tip = active_chainstate.m_chain.Tip();
|
||||
assert(tip != nullptr);
|
||||
|
||||
CBlockIndex index;
|
||||
index.pprev = tip;
|
||||
// CheckSequenceLocks() uses ::ChainActive().Height()+1 to evaluate
|
||||
// CheckSequenceLocks() uses active_chainstate.m_chain.Height()+1 to evaluate
|
||||
// height based locks because when SequenceLocks() is called within
|
||||
// ConnectBlock(), the height of the block *being*
|
||||
// evaluated is what is used.
|
||||
// Thus if we want to know if a transaction can be part of the
|
||||
// *next* block, we need to use one more than ::ChainActive().Height()
|
||||
// *next* block, we need to use one more than active_chainstate.m_chain.Height()
|
||||
index.nHeight = tip->nHeight + 1;
|
||||
|
||||
std::pair<int, int64_t> lockPair;
|
||||
@ -280,8 +288,8 @@ bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flag
|
||||
lockPair.second = lp->time;
|
||||
}
|
||||
else {
|
||||
// CoinsTip() contains the UTXO set for ::ChainActive().Tip()
|
||||
CCoinsViewMemPool viewMemPool(&::ChainstateActive().CoinsTip(), pool);
|
||||
// CoinsTip() contains the UTXO set for active_chainstate.m_chain.Tip()
|
||||
CCoinsViewMemPool viewMemPool(&active_chainstate.CoinsTip(), pool);
|
||||
std::vector<int> prevheights;
|
||||
prevheights.resize(tx.vin.size());
|
||||
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
|
||||
@ -389,7 +397,8 @@ bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state,
|
||||
// Returns the script flags which should be checked for a given block
|
||||
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& chainparams);
|
||||
|
||||
static void LimitMempoolSize(CTxMemPool& pool, size_t limit, std::chrono::seconds age) EXCLUSIVE_LOCKS_REQUIRED(pool.cs, ::cs_main)
|
||||
static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache, size_t limit, std::chrono::seconds age)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(pool.cs, ::cs_main)
|
||||
{
|
||||
int expired = pool.Expire(GetTime<std::chrono::seconds>() - age);
|
||||
if (expired != 0) {
|
||||
@ -398,18 +407,20 @@ static void LimitMempoolSize(CTxMemPool& pool, size_t limit, std::chrono::second
|
||||
|
||||
std::vector<COutPoint> vNoSpendsRemaining;
|
||||
pool.TrimToSize(limit, &vNoSpendsRemaining);
|
||||
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(coins_cache));
|
||||
for (const COutPoint& removed : vNoSpendsRemaining)
|
||||
::ChainstateActive().CoinsTip().Uncache(removed);
|
||||
coins_cache.Uncache(removed);
|
||||
}
|
||||
|
||||
static bool IsCurrentForFeeEstimation() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
static bool IsCurrentForFeeEstimation(CChainState& active_chainstate) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
if (::ChainstateActive().IsInitialBlockDownload())
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
||||
if (active_chainstate.IsInitialBlockDownload())
|
||||
return false;
|
||||
if (::ChainActive().Tip()->GetBlockTime() < count_seconds(GetTime<std::chrono::seconds>() - MAX_FEE_ESTIMATION_TIP_AGE))
|
||||
if (active_chainstate.m_chain.Tip()->GetBlockTime() < count_seconds(GetTime<std::chrono::seconds>() - MAX_FEE_ESTIMATION_TIP_AGE))
|
||||
return false;
|
||||
if (::ChainActive().Height() < pindexBestHeader->nHeight - 1)
|
||||
if (active_chainstate.m_chain.Height() < pindexBestHeader->nHeight - 1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -427,10 +438,11 @@ static bool IsCurrentForFeeEstimation() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
* and instead just erase from the mempool as needed.
|
||||
*/
|
||||
|
||||
static void UpdateMempoolForReorg(CTxMemPool& mempool, DisconnectedBlockTransactions& disconnectpool, bool fAddToMempool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, mempool.cs)
|
||||
static void UpdateMempoolForReorg(CChainState& active_chainstate, CTxMemPool& mempool, DisconnectedBlockTransactions& disconnectpool, bool fAddToMempool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, mempool.cs)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
AssertLockHeld(mempool.cs);
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
||||
std::vector<uint256> vHashUpdate;
|
||||
// disconnectpool's insertion_order index sorts the entries from
|
||||
// oldest to newest, but the oldest entry will be the last tx from the
|
||||
@ -443,7 +455,7 @@ static void UpdateMempoolForReorg(CTxMemPool& mempool, DisconnectedBlockTransact
|
||||
// ignore validation errors in resurrected transactions
|
||||
CValidationState stateDummy;
|
||||
if (!fAddToMempool || (*it)->IsCoinBase() ||
|
||||
!AcceptToMemoryPool(mempool, stateDummy, *it, nullptr /* pfMissingInputs */,
|
||||
!AcceptToMemoryPool(active_chainstate, mempool, stateDummy, *it, nullptr /* pfMissingInputs */,
|
||||
true /* bypass_limits */, 0 /* nAbsurdFee */)) {
|
||||
// If the transaction doesn't make it in to the mempool, remove any
|
||||
// transactions that depend on it (which would now be orphans).
|
||||
@ -462,16 +474,18 @@ static void UpdateMempoolForReorg(CTxMemPool& mempool, DisconnectedBlockTransact
|
||||
mempool.UpdateTransactionsFromBlock(vHashUpdate);
|
||||
|
||||
// We also need to remove any now-immature transactions
|
||||
mempool.removeForReorg(&::ChainstateActive().CoinsTip(), ::ChainActive().Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
|
||||
|
||||
mempool.removeForReorg(active_chainstate, STANDARD_LOCKTIME_VERIFY_FLAGS);
|
||||
// Re-limit mempool size, in case we added any transactions
|
||||
LimitMempoolSize(mempool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
|
||||
LimitMempoolSize(mempool, active_chainstate.CoinsTip(), gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
|
||||
}
|
||||
|
||||
// Used to avoid mempool polluting consensus critical paths if CCoinsViewMempool
|
||||
// were somehow broken and returning the wrong scriptPubKeys
|
||||
static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& view, const CTxMemPool& pool,
|
||||
unsigned int flags, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
|
||||
static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationState& state,
|
||||
const CCoinsViewCache& view, const CTxMemPool& pool,
|
||||
unsigned int flags, PrecomputedTransactionData& txdata, CCoinsViewCache& coins_tip)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
// pool.cs should be locked already, but go ahead and re-take the lock here
|
||||
@ -495,7 +509,8 @@ static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationSt
|
||||
assert(txFrom->vout.size() > txin.prevout.n);
|
||||
assert(txFrom->vout[txin.prevout.n] == coin.out);
|
||||
} else {
|
||||
const Coin& coinFromDisk = ::ChainstateActive().CoinsTip().AccessCoin(txin.prevout);
|
||||
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(coins_tip));
|
||||
const Coin& coinFromDisk = coins_tip.AccessCoin(txin.prevout);
|
||||
assert(!coinFromDisk.IsSpent());
|
||||
assert(coinFromDisk.out == coin.out);
|
||||
}
|
||||
@ -510,11 +525,13 @@ namespace {
|
||||
class MemPoolAccept
|
||||
{
|
||||
public:
|
||||
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.
|
||||
@ -593,6 +610,7 @@ private:
|
||||
CCoinsViewCache m_view;
|
||||
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;
|
||||
@ -630,7 +648,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
if (!CheckTransaction(tx, state))
|
||||
return false; // state filled in by CheckTransaction
|
||||
|
||||
if (!ContextualCheckTransaction(tx, state, chainparams.GetConsensus(), ::ChainActive().Tip()))
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(m_active_chainstate));
|
||||
if (!ContextualCheckTransaction(tx, state, chainparams.GetConsensus(), m_active_chainstate.m_chain.Tip()))
|
||||
return error("%s: ContextualCheckTransaction: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
|
||||
|
||||
if (tx.nVersion == 3 && tx.nType == TRANSACTION_QUORUM_COMMITMENT) {
|
||||
@ -657,7 +676,7 @@ 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(tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
|
||||
if (!CheckFinalTx(m_active_chainstate.m_chain.Tip(), tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
|
||||
return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_NONSTANDARD, "non-final");
|
||||
|
||||
// is it already in the memory pool?
|
||||
@ -695,7 +714,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
LockPoints lp;
|
||||
m_view.SetBackend(m_viewmempool);
|
||||
|
||||
CCoinsViewCache& coins_cache = ::ChainstateActive().CoinsTip();
|
||||
assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(m_active_chainstate.CoinsTip()));
|
||||
CCoinsViewCache& coins_cache = m_active_chainstate.CoinsTip();
|
||||
// do all inputs exist?
|
||||
for (const CTxIn& txin : tx.vin) {
|
||||
if (!coins_cache.HaveCoinInCache(txin.prevout)) {
|
||||
@ -734,11 +754,13 @@ 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(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(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_NONSTANDARD, "non-BIP68-final");
|
||||
|
||||
assert(std::addressof(g_chainman.m_blockman) == std::addressof(m_active_chainstate.m_blockman));
|
||||
CAmount nFees = 0;
|
||||
if (!Consensus::CheckTxInputs(tx, state, m_view, g_chainman.m_blockman.GetSpendHeight(m_view), nFees)) {
|
||||
if (!Consensus::CheckTxInputs(tx, state, m_view, m_active_chainstate.m_blockman.GetSpendHeight(m_view), nFees)) {
|
||||
return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));
|
||||
}
|
||||
|
||||
@ -763,7 +785,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
}
|
||||
}
|
||||
|
||||
entry.reset(new CTxMemPoolEntry(ptx, nFees, nAcceptTime, ::ChainActive().Height(),
|
||||
assert(std::addressof(::ChainActive()) == std::addressof(m_active_chainstate.m_chain));
|
||||
entry.reset(new CTxMemPoolEntry(ptx, nFees, nAcceptTime, m_active_chainstate.m_chain.Height(),
|
||||
fSpendsCoinbase, nSigOps, lp));
|
||||
unsigned int nSize = entry->GetTxSize();
|
||||
|
||||
@ -806,7 +829,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
// DoS scoring a node for non-critical errors, e.g. duplicate keys because a TX is received that was already
|
||||
// mined
|
||||
// NOTE: we use UTXO here and do NOT allow mempool txes as masternode collaterals
|
||||
if (!CheckSpecialTx(tx, ::ChainActive().Tip(), state, ::ChainstateActive().CoinsTip(), true))
|
||||
if (!CheckSpecialTx(tx, m_active_chainstate.m_chain.Tip(), state, m_active_chainstate.CoinsTip(), true))
|
||||
return false;
|
||||
|
||||
if (m_pool.existsProviderTxConflict(tx)) {
|
||||
@ -857,8 +880,10 @@ bool MemPoolAccept::ConsensusScriptChecks(ATMPArgs& args, Workspace& ws, Precomp
|
||||
// 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)) {
|
||||
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! CheckInputs failed against latest-block but not STANDARD flags %s, %s",
|
||||
__func__, hash.ToString(), FormatStateMessage(state));
|
||||
}
|
||||
@ -881,7 +906,8 @@ bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws)
|
||||
// - the node is not behind
|
||||
// - the transaction is not dependent on any other transactions in the mempool
|
||||
// - the transaction is not a zero fee transaction
|
||||
bool validForFeeEstimation = (nModifiedFees != 0) && !bypass_limits && IsCurrentForFeeEstimation() && m_pool.HasNoInputsOf(tx);
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(m_active_chainstate));
|
||||
bool validForFeeEstimation = (nModifiedFees != 0) && !bypass_limits && IsCurrentForFeeEstimation(m_active_chainstate) && m_pool.HasNoInputsOf(tx);
|
||||
|
||||
// Store transaction in memory
|
||||
m_pool.addUnchecked(*entry, setAncestors, validForFeeEstimation);
|
||||
@ -905,7 +931,8 @@ bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws)
|
||||
}
|
||||
|
||||
if (!bypass_limits) {
|
||||
LimitMempoolSize(m_pool, 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(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "mempool full");
|
||||
}
|
||||
@ -954,13 +981,15 @@ bool MemPoolAccept::AcceptSingleTransaction(const CTransactionRef& ptx, ATMPArgs
|
||||
} // anon namespace
|
||||
|
||||
/** (try to) add transaction to memory pool with a specified acceptance time **/
|
||||
static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
|
||||
static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPool& pool, CChainState& active_chainstate, CValidationState &state, const CTransactionRef &tx,
|
||||
bool* pfMissingInputs, int64_t nAcceptTime, bool bypass_limits,
|
||||
const CAmount nAbsurdFee, bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
std::vector<COutPoint> coins_to_uncache;
|
||||
MemPoolAccept::ATMPArgs args { chainparams, state, pfMissingInputs, nAcceptTime, bypass_limits, nAbsurdFee, coins_to_uncache, test_accept };
|
||||
bool res = MemPoolAccept(pool).AcceptSingleTransaction(tx, args);
|
||||
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
||||
bool res = MemPoolAccept(pool, active_chainstate).AcceptSingleTransaction(tx, args);
|
||||
if (!res || test_accept) {
|
||||
if (!res) LogPrint(BCLog::MEMPOOL, "%s: %s %s (%s)\n", __func__, tx->GetHash().ToString(), state.GetRejectReason(), state.GetDebugMessage());
|
||||
|
||||
@ -970,19 +999,20 @@ static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPo
|
||||
// (`CCoinsViewCache::cacheCoins`).
|
||||
|
||||
for (const COutPoint& hashTx : coins_to_uncache)
|
||||
::ChainstateActive().CoinsTip().Uncache(hashTx);
|
||||
active_chainstate.CoinsTip().Uncache(hashTx);
|
||||
}
|
||||
// After we've (potentially) uncached entries, ensure our coins cache is still within its size limits
|
||||
CValidationState stateDummy;
|
||||
::ChainstateActive().FlushStateToDisk(chainparams, stateDummy, FlushStateMode::PERIODIC);
|
||||
active_chainstate.FlushStateToDisk(chainparams, stateDummy, FlushStateMode::PERIODIC);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
|
||||
bool AcceptToMemoryPool(CChainState& active_chainstate, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
|
||||
bool* pfMissingInputs, bool bypass_limits, const CAmount nAbsurdFee, bool test_accept)
|
||||
{
|
||||
const CChainParams& chainparams = Params();
|
||||
return AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, pfMissingInputs, GetTime(), bypass_limits, nAbsurdFee, test_accept);
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
||||
return AcceptToMemoryPoolWithTime(chainparams, pool, active_chainstate, state, tx, pfMissingInputs, GetTime(), bypass_limits, nAbsurdFee, test_accept);
|
||||
}
|
||||
|
||||
bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, std::vector<uint256> &hashes)
|
||||
@ -3038,7 +3068,7 @@ bool CChainState::ActivateBestChainStep(CValidationState& state, const CChainPar
|
||||
if (!DisconnectTip(state, chainparams, &disconnectpool)) {
|
||||
// This is likely a fatal error, but keep the mempool consistent,
|
||||
// just in case. Only remove from the mempool in this case.
|
||||
UpdateMempoolForReorg(m_mempool, disconnectpool, false);
|
||||
UpdateMempoolForReorg(::ChainstateActive(), m_mempool, disconnectpool, false);
|
||||
|
||||
// If we're unable to disconnect a block during normal operation,
|
||||
// then that is a failure of our local system -- we should abort
|
||||
@ -3082,7 +3112,7 @@ bool CChainState::ActivateBestChainStep(CValidationState& state, const CChainPar
|
||||
// A system error occurred (disk space, database error, ...).
|
||||
// Make the mempool consistent with the current tip, just in case
|
||||
// any observers try to use it before shutdown.
|
||||
UpdateMempoolForReorg(m_mempool, disconnectpool, false);
|
||||
UpdateMempoolForReorg(::ChainstateActive(), m_mempool, disconnectpool, false);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@ -3099,7 +3129,7 @@ bool CChainState::ActivateBestChainStep(CValidationState& state, const CChainPar
|
||||
if (fBlocksDisconnected) {
|
||||
// If any blocks were disconnected, disconnectpool may be non empty. Add
|
||||
// any disconnected transactions back to the mempool.
|
||||
UpdateMempoolForReorg(m_mempool, disconnectpool, true);
|
||||
UpdateMempoolForReorg(::ChainstateActive(), m_mempool, disconnectpool, true);
|
||||
}
|
||||
m_mempool.check(&CoinsTip());
|
||||
|
||||
@ -3347,7 +3377,7 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
|
||||
// transactions back to the mempool if disconnecting was successful,
|
||||
// and we're not doing a very deep invalidation (in which case
|
||||
// keeping the mempool up to date is probably futile anyway).
|
||||
UpdateMempoolForReorg(m_mempool, disconnectpool, /* fAddToMempool = */ (++disconnected <= 10) && ret);
|
||||
UpdateMempoolForReorg(::ChainstateActive(), m_mempool, disconnectpool, /* fAddToMempool = */ (++disconnected <= 10) && ret);
|
||||
if (!ret) return false;
|
||||
assert(invalid_walk_tip->pprev == m_chain.Tip());
|
||||
|
||||
@ -3493,7 +3523,7 @@ bool CChainState::MarkConflictingBlock(CValidationState& state, const CChainPara
|
||||
if (!DisconnectTip(state, chainparams, &disconnectpool)) {
|
||||
// It's probably hopeless to try to make the mempool consistent
|
||||
// here if DisconnectTip failed, but we can try.
|
||||
UpdateMempoolForReorg(m_mempool, disconnectpool, false);
|
||||
UpdateMempoolForReorg(::ChainstateActive(), m_mempool, disconnectpool, false);
|
||||
return false;
|
||||
}
|
||||
if (pindexOldTip == pindexBestHeader) {
|
||||
@ -3515,7 +3545,7 @@ bool CChainState::MarkConflictingBlock(CValidationState& state, const CChainPara
|
||||
|
||||
// DisconnectTip will add transactions to disconnectpool; try to add these
|
||||
// back to the mempool.
|
||||
UpdateMempoolForReorg(m_mempool, disconnectpool, true);
|
||||
UpdateMempoolForReorg(::ChainstateActive(), m_mempool, disconnectpool, true);
|
||||
} // m_mempool.cs
|
||||
|
||||
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
|
||||
@ -4662,7 +4692,8 @@ bool static LoadBlockIndexDB(ChainstateManager& chainman, const CChainParams& ch
|
||||
void CChainState::LoadMempool(const ArgsManager& args)
|
||||
{
|
||||
if (args.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
|
||||
::LoadMempool(m_mempool);
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(*this));
|
||||
::LoadMempool(m_mempool, *this);
|
||||
}
|
||||
m_mempool.SetIsLoaded(!ShutdownRequested());
|
||||
}
|
||||
@ -5411,7 +5442,7 @@ int VersionBitsTipStateSinceHeight(const Consensus::Params& params, Consensus::D
|
||||
|
||||
static const uint64_t MEMPOOL_DUMP_VERSION = 1;
|
||||
|
||||
bool LoadMempool(CTxMemPool& pool)
|
||||
bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate)
|
||||
{
|
||||
const CChainParams& chainparams = Params();
|
||||
int64_t nExpiryTimeout = gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60;
|
||||
@ -5453,7 +5484,8 @@ bool LoadMempool(CTxMemPool& pool)
|
||||
CValidationState state;
|
||||
if (nTime + nExpiryTimeout > nNow) {
|
||||
LOCK(cs_main);
|
||||
AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, nullptr /* pfMissingInputs */, nTime,
|
||||
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
|
||||
AcceptToMemoryPoolWithTime(chainparams, pool, active_chainstate, state, tx, nullptr /* pfMissingInputs */, nTime,
|
||||
false /* bypass_limits */, 0 /* nAbsurdFee */, false /* test_accept */);
|
||||
if (state.IsValid()) {
|
||||
++count;
|
||||
|
@ -217,7 +217,7 @@ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune);
|
||||
void PruneBlockFilesManual(int nManualPruneHeight);
|
||||
|
||||
/** (try to) add transaction to memory pool */
|
||||
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
|
||||
bool AcceptToMemoryPool(CChainState& active_chainstate, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
|
||||
bool* pfMissingInputs, bool bypass_limits,
|
||||
const CAmount nAbsurdFee, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
@ -246,12 +246,12 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
|
||||
*
|
||||
* See consensus/consensus.h for flag definitions.
|
||||
*/
|
||||
bool CheckFinalTx(const CTransaction &tx, int flags = -1) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
bool CheckFinalTx(const CBlockIndex* active_chain_tip, const CTransaction &tx, int flags = -1) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
/**
|
||||
* Test whether the LockPoints height and time are still valid on the current chain
|
||||
*/
|
||||
bool TestLockPointValidity(const LockPoints* lp) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
bool TestLockPointValidity(CChain& active_chain, const LockPoints* lp) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
/**
|
||||
* Check if transaction will be BIP 68 final in the next block to be created.
|
||||
@ -264,7 +264,12 @@ bool TestLockPointValidity(const LockPoints* lp) EXCLUSIVE_LOCKS_REQUIRED(cs_mai
|
||||
*
|
||||
* See consensus/consensus.h for flag definitions.
|
||||
*/
|
||||
bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flags, LockPoints* lp = nullptr, bool useExistingLockPoints = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
bool CheckSequenceLocks(CChainState& active_chainstate,
|
||||
const CTxMemPool& pool,
|
||||
const CTransaction& tx,
|
||||
int flags,
|
||||
LockPoints* lp = nullptr,
|
||||
bool useExistingLockPoints = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
/**
|
||||
* Closure representing one script verification
|
||||
@ -1046,7 +1051,7 @@ CBlockFileInfo* GetBlockFileInfo(size_t n);
|
||||
bool DumpMempool(const CTxMemPool& pool);
|
||||
|
||||
/** Load the mempool from disk. */
|
||||
bool LoadMempool(CTxMemPool& pool);
|
||||
bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate);
|
||||
|
||||
//! Check whether the block associated with this index entry is pruned or not.
|
||||
inline bool IsBlockPruned(const CBlockIndex* pblockindex)
|
||||
|
Loading…
Reference in New Issue
Block a user