aboutsummaryrefslogtreecommitdiff
path: root/src/txmempool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/txmempool.cpp')
-rw-r--r--src/txmempool.cpp69
1 files changed, 46 insertions, 23 deletions
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 205ffd6379..b631c48484 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -9,6 +9,7 @@
#include "consensus/consensus.h"
#include "consensus/validation.h"
#include "main.h"
+#include "policy/policy.h"
#include "policy/fees.h"
#include "streams.h"
#include "timedata.h"
@@ -22,17 +23,17 @@ using namespace std;
CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
int64_t _nTime, double _entryPriority, unsigned int _entryHeight,
bool poolHasNoInputsOf, CAmount _inChainInputValue,
- bool _spendsCoinbase, unsigned int _sigOps, LockPoints lp):
+ bool _spendsCoinbase, int64_t _sigOpsCost, LockPoints lp):
tx(std::make_shared<CTransaction>(_tx)), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight),
hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue),
- spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOps), lockPoints(lp)
+ spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp)
{
- nTxSize = ::GetSerializeSize(_tx, SER_NETWORK, PROTOCOL_VERSION);
- nModSize = _tx.CalculateModifiedSize(nTxSize);
+ nTxWeight = GetTransactionWeight(_tx);
+ nModSize = _tx.CalculateModifiedSize(GetTxSize());
nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx);
nCountWithDescendants = 1;
- nSizeWithDescendants = nTxSize;
+ nSizeWithDescendants = GetTxSize();
nModFeesWithDescendants = nFee;
CAmount nValueIn = _tx.GetValueOut()+nFee;
assert(inChainInputValue <= nValueIn);
@@ -40,9 +41,9 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
feeDelta = 0;
nCountWithAncestors = 1;
- nSizeWithAncestors = nTxSize;
+ nSizeWithAncestors = GetTxSize();
nModFeesWithAncestors = nFee;
- nSigOpCountWithAncestors = sigOpCount;
+ nSigOpCostWithAncestors = sigOpCost;
}
CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
@@ -72,6 +73,11 @@ void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
lockPoints = lp;
}
+size_t CTxMemPoolEntry::GetTxSize() const
+{
+ return GetVirtualTransactionSize(nTxWeight, sigOpCost);
+}
+
// Update the given tx for any in-mempool descendants.
// Assumes that setMemPoolChildren is correct for the given tx and all
// descendants.
@@ -111,7 +117,7 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan
modifyCount++;
cachedDescendants[updateIt].insert(cit);
// Update ancestor state for each descendant
- mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCount()));
+ mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCost()));
}
}
mapTx.modify(updateIt, update_descendant_state(modifySize, modifyFee, modifyCount));
@@ -247,13 +253,13 @@ void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncesto
int64_t updateCount = setAncestors.size();
int64_t updateSize = 0;
CAmount updateFee = 0;
- int updateSigOps = 0;
+ int64_t updateSigOpsCost = 0;
BOOST_FOREACH(txiter ancestorIt, setAncestors) {
updateSize += ancestorIt->GetTxSize();
updateFee += ancestorIt->GetModifiedFee();
- updateSigOps += ancestorIt->GetSigOpCount();
+ updateSigOpsCost += ancestorIt->GetSigOpCost();
}
- mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOps));
+ mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOpsCost));
}
void CTxMemPool::UpdateChildrenForRemoval(txiter it)
@@ -282,7 +288,7 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b
setDescendants.erase(removeIt); // don't update state for self
int64_t modifySize = -((int64_t)removeIt->GetTxSize());
CAmount modifyFee = -removeIt->GetModifiedFee();
- int modifySigOps = -removeIt->GetSigOpCount();
+ int modifySigOps = -removeIt->GetSigOpCost();
BOOST_FOREACH(txiter dit, setDescendants) {
mapTx.modify(dit, update_ancestor_state(modifySize, modifyFee, -1, modifySigOps));
}
@@ -338,8 +344,8 @@ void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee,
nModFeesWithAncestors += modifyFee;
nCountWithAncestors += modifyCount;
assert(int64_t(nCountWithAncestors) > 0);
- nSigOpCountWithAncestors += modifySigOps;
- assert(int(nSigOpCountWithAncestors) >= 0);
+ nSigOpCostWithAncestors += modifySigOps;
+ assert(int(nSigOpCostWithAncestors) >= 0);
}
CTxMemPool::CTxMemPool(const CFeeRate& _minReasonableRelayFee) :
@@ -438,6 +444,9 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
totalTxSize += entry.GetTxSize();
minerPolicyEstimator->processTransaction(entry, fCurrentEstimate);
+ vTxHashes.emplace_back(hash, newit);
+ newit->vTxHashesIdx = vTxHashes.size() - 1;
+
return true;
}
@@ -447,6 +456,15 @@ void CTxMemPool::removeUnchecked(txiter it)
BOOST_FOREACH(const CTxIn& txin, it->GetTx().vin)
mapNextTx.erase(txin.prevout);
+ if (vTxHashes.size() > 1) {
+ vTxHashes[it->vTxHashesIdx] = std::move(vTxHashes.back());
+ vTxHashes[it->vTxHashesIdx].second->vTxHashesIdx = it->vTxHashesIdx;
+ vTxHashes.pop_back();
+ if (vTxHashes.size() * 2 < vTxHashes.capacity())
+ vTxHashes.shrink_to_fit();
+ } else
+ vTxHashes.clear();
+
totalTxSize -= it->GetTxSize();
cachedInnerUsage -= it->DynamicMemoryUsage();
cachedInnerUsage -= memusage::DynamicUsage(mapLinks[it].parents) + memusage::DynamicUsage(mapLinks[it].children);
@@ -639,6 +657,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
uint64_t innerUsage = 0;
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
+ const int64_t nSpendHeight = GetSpendHeight(mempoolDuplicate);
LOCK(cs);
list<const CTxMemPoolEntry*> waitingOnDependants;
@@ -654,7 +673,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
bool fDependsWait = false;
setEntries setParentCheck;
int64_t parentSizes = 0;
- unsigned int parentSigOpCount = 0;
+ int64_t parentSigOpCost = 0;
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
// Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
@@ -664,7 +683,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
fDependsWait = true;
if (setParentCheck.insert(it2).second) {
parentSizes += it2->GetTxSize();
- parentSigOpCount += it2->GetSigOpCount();
+ parentSigOpCost += it2->GetSigOpCost();
}
} else {
const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
@@ -686,17 +705,17 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
uint64_t nCountCheck = setAncestors.size() + 1;
uint64_t nSizeCheck = it->GetTxSize();
CAmount nFeesCheck = it->GetModifiedFee();
- unsigned int nSigOpCheck = it->GetSigOpCount();
+ int64_t nSigOpCheck = it->GetSigOpCost();
BOOST_FOREACH(txiter ancestorIt, setAncestors) {
nSizeCheck += ancestorIt->GetTxSize();
nFeesCheck += ancestorIt->GetModifiedFee();
- nSigOpCheck += ancestorIt->GetSigOpCount();
+ nSigOpCheck += ancestorIt->GetSigOpCost();
}
assert(it->GetCountWithAncestors() == nCountCheck);
assert(it->GetSizeWithAncestors() == nSizeCheck);
- assert(it->GetSigOpCountWithAncestors() == nSigOpCheck);
+ assert(it->GetSigOpCostWithAncestors() == nSigOpCheck);
assert(it->GetModFeesWithAncestors() == nFeesCheck);
// Check children against mapNextTx
@@ -719,7 +738,9 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
waitingOnDependants.push_back(&(*it));
else {
CValidationState state;
- assert(CheckInputs(tx, state, mempoolDuplicate, false, 0, false, NULL));
+ bool fCheckResult = tx.IsCoinBase() ||
+ Consensus::CheckTxInputs(tx, state, mempoolDuplicate, nSpendHeight);
+ assert(fCheckResult);
UpdateCoins(tx, mempoolDuplicate, 1000000);
}
}
@@ -733,7 +754,9 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
stepsSinceLastRemove++;
assert(stepsSinceLastRemove < waitingOnDependants.size());
} else {
- assert(CheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, NULL));
+ bool fCheckResult = entry->GetTx().IsCoinBase() ||
+ Consensus::CheckTxInputs(entry->GetTx(), state, mempoolDuplicate, nSpendHeight);
+ assert(fCheckResult);
UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000);
stepsSinceLastRemove = 0;
}
@@ -965,7 +988,7 @@ bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) const {
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.
- return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 15 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + cachedInnerUsage;
+ return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 15 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + memusage::DynamicUsage(vTxHashes) + cachedInnerUsage;
}
void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants) {
@@ -1075,7 +1098,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<uint256>* pvNoSpendsRe
unsigned nTxnRemoved = 0;
CFeeRate maxFeeRateRemoved(0);
- while (DynamicMemoryUsage() > sizelimit) {
+ while (!mapTx.empty() && DynamicMemoryUsage() > sizelimit) {
indexed_transaction_set::index<descendant_score>::type::iterator it = mapTx.get<descendant_score>().begin();
// We set the new mempool min fee to the feerate of the removed set, plus the