aboutsummaryrefslogtreecommitdiff
path: root/src/txmempool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/txmempool.cpp')
-rw-r--r--src/txmempool.cpp70
1 files changed, 37 insertions, 33 deletions
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 9fa7b4e251..4413da7ea7 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -8,7 +8,6 @@
#include <consensus/consensus.h>
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
-#include <optional.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/settings.h>
@@ -19,11 +18,14 @@
#include <validation.h>
#include <validationinterface.h>
+#include <cmath>
+#include <optional>
+
CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
int64_t _nTime, unsigned int _entryHeight,
bool _spendsCoinbase, int64_t _sigOpsCost, LockPoints lp)
: tx(_tx), nFee(_nFee), nTxWeight(GetTransactionWeight(*tx)), nUsageSize(RecursiveDynamicUsage(tx)), nTime(_nTime), entryHeight(_entryHeight),
- spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp), m_epoch(0)
+ spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp)
{
nCountWithDescendants = 1;
nSizeWithDescendants = GetTxSize();
@@ -132,7 +134,7 @@ void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashes
// include them, and update their CTxMemPoolEntry::m_parents to include this tx.
// we cache the in-mempool children to avoid duplicate updates
{
- const auto epoch = GetFreshEpoch();
+ WITH_FRESH_EPOCH(m_epoch);
for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) {
const uint256 &childHash = iter->second->GetHash();
txiter childIter = mapTx.find(childHash);
@@ -159,7 +161,7 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntr
// GetMemPoolParents() is only valid for entries in the mempool, so we
// iterate mapTx to find parents.
for (unsigned int i = 0; i < tx.vin.size(); i++) {
- Optional<txiter> piter = GetIter(tx.vin[i].prevout.hash);
+ std::optional<txiter> piter = GetIter(tx.vin[i].prevout.hash);
if (piter) {
staged_ancestors.insert(**piter);
if (staged_ancestors.size() + 1 > limitAncestorCount) {
@@ -503,7 +505,7 @@ void CTxMemPool::removeRecursive(const CTransaction &origTx, MemPoolRemovalReaso
RemoveStaged(setAllRemoves, false, reason);
}
-void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags)
+void CTxMemPool::removeForReorg(CChainState& active_chainstate, int flags)
{
// Remove transactions spending a coinbase which are now immature and no-longer-final transactions
AssertLockHeld(cs);
@@ -511,8 +513,11 @@ 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);
+ CCoinsViewMemPool viewMempool(&active_chainstate.CoinsTip(), *this);
+ if (!CheckFinalTx(active_chainstate.m_chain.Tip(), tx, flags)
+ || !CheckSequenceLocks(active_chainstate.m_chain.Tip(), viewMempool, 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);
@@ -521,8 +526,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;
@@ -617,7 +623,7 @@ static void CheckInputsAndUpdateCoins(const CTransaction& tx, CCoinsViewCache& m
UpdateCoins(tx, mempoolDuplicate, std::numeric_limits<int>::max());
}
-void CTxMemPool::check(const CCoinsViewCache *pcoins) const
+void CTxMemPool::check(CChainState& active_chainstate) const
{
if (m_check_ratio == 0) return;
@@ -631,8 +637,11 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
CAmount check_total_fee{0};
uint64_t innerUsage = 0;
- CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
- const int64_t spendheight = g_chainman.m_blockman.GetSpendHeight(mempoolDuplicate);
+ CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip();
+ assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(active_coins_tip)); // TODO: REVIEW-ONLY, REMOVE IN FUTURE COMMIT
+ CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip));
+ const int64_t spendheight = active_chainstate.m_chain.Height() + 1;
+ assert(g_chainman.m_blockman.GetSpendHeight(mempoolDuplicate) == spendheight); // TODO: REVIEW-ONLY, REMOVE IN FUTURE COMMIT
std::list<const CTxMemPoolEntry*> waitingOnDependants;
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
@@ -653,7 +662,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
fDependsWait = true;
setParentCheck.insert(*it2);
} else {
- assert(pcoins->HaveCoin(txin.prevout));
+ assert(active_coins_tip.HaveCoin(txin.prevout));
}
// Check whether its inputs are marked in mapNextTx.
auto it3 = mapNextTx.find(txin.prevout);
@@ -885,11 +894,11 @@ const CTransaction* CTxMemPool::GetConflictTx(const COutPoint& prevout) const
return it == mapNextTx.end() ? nullptr : it->second;
}
-Optional<CTxMemPool::txiter> CTxMemPool::GetIter(const uint256& txid) const
+std::optional<CTxMemPool::txiter> CTxMemPool::GetIter(const uint256& txid) const
{
auto it = mapTx.find(txid);
if (it != mapTx.end()) return it;
- return Optional<txiter>{};
+ return std::nullopt;
}
CTxMemPool::setEntries CTxMemPool::GetIterSet(const std::set<uint256>& hashes) const
@@ -913,6 +922,13 @@ bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView* baseIn, const CTxMemPool& mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
bool CCoinsViewMemPool::GetCoin(const COutPoint &outpoint, Coin &coin) const {
+ // Check to see if the inputs are made available by another tx in the package.
+ // These Coins would not be available in the underlying CoinsView.
+ if (auto it = m_temp_added.find(outpoint); it != m_temp_added.end()) {
+ coin = it->second;
+ return true;
+ }
+
// If an entry in the mempool exists, always return that one, as it's guaranteed to never
// conflict with the underlying cache, and it cannot have pruned entries (as it contains full)
// transactions. First checking the underlying cache risks returning a pruned entry instead.
@@ -928,6 +944,13 @@ bool CCoinsViewMemPool::GetCoin(const COutPoint &outpoint, Coin &coin) const {
return base->GetCoin(outpoint, coin);
}
+void CCoinsViewMemPool::PackageAddTransaction(const CTransactionRef& tx)
+{
+ for (unsigned int n = 0; n < tx->vout.size(); ++n) {
+ m_temp_added.emplace(COutPoint(tx->GetHash(), n), Coin(tx->vout[n], MEMPOOL_HEIGHT, false));
+ }
+}
+
size_t CTxMemPool::DynamicMemoryUsage() const {
LOCK(cs);
// Estimate the overhead of mapTx to be 15 pointers + an allocation, as no exact formula for boost::multi_index_contained is implemented.
@@ -1117,22 +1140,3 @@ void CTxMemPool::SetIsLoaded(bool loaded)
LOCK(cs);
m_is_loaded = loaded;
}
-
-
-CTxMemPool::EpochGuard CTxMemPool::GetFreshEpoch() const
-{
- return EpochGuard(*this);
-}
-CTxMemPool::EpochGuard::EpochGuard(const CTxMemPool& in) : pool(in)
-{
- assert(!pool.m_has_epoch_guard);
- ++pool.m_epoch;
- pool.m_has_epoch_guard = true;
-}
-
-CTxMemPool::EpochGuard::~EpochGuard()
-{
- // prevents stale results being used
- ++pool.m_epoch;
- pool.m_has_epoch_guard = false;
-}