aboutsummaryrefslogtreecommitdiff
path: root/src/txmempool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/txmempool.cpp')
-rw-r--r--src/txmempool.cpp126
1 files changed, 79 insertions, 47 deletions
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index aa5df6ca4e..205ffd6379 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -23,18 +23,18 @@ 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):
- tx(_tx), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight),
+ tx(std::make_shared<CTransaction>(_tx)), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight),
hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue),
spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOps), lockPoints(lp)
{
- nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
- nModSize = tx.CalculateModifiedSize(nTxSize);
- nUsageSize = RecursiveDynamicUsage(tx);
+ nTxSize = ::GetSerializeSize(_tx, SER_NETWORK, PROTOCOL_VERSION);
+ nModSize = _tx.CalculateModifiedSize(nTxSize);
+ nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx);
nCountWithDescendants = 1;
nSizeWithDescendants = nTxSize;
nModFeesWithDescendants = nFee;
- CAmount nValueIn = tx.GetValueOut()+nFee;
+ CAmount nValueIn = _tx.GetValueOut()+nFee;
assert(inChainInputValue <= nValueIn);
feeDelta = 0;
@@ -147,11 +147,11 @@ void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashes
if (it == mapTx.end()) {
continue;
}
- std::map<COutPoint, CInPoint>::iterator iter = mapNextTx.lower_bound(COutPoint(hash, 0));
+ auto iter = mapNextTx.lower_bound(COutPoint(hash, 0));
// First calculate the children, and update setMemPoolChildren to
// include them, and update their setMemPoolParents to include this tx.
- for (; iter != mapNextTx.end() && iter->first.hash == hash; ++iter) {
- const uint256 &childHash = iter->second.ptx->GetHash();
+ for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) {
+ const uint256 &childHash = iter->second->GetHash();
txiter childIter = mapTx.find(childHash);
assert(childIter != mapTx.end());
// We can skip updating entries we've encountered before or that
@@ -365,11 +365,11 @@ void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
{
LOCK(cs);
- std::map<COutPoint, CInPoint>::iterator it = mapNextTx.lower_bound(COutPoint(hashTx, 0));
+ auto it = mapNextTx.lower_bound(COutPoint(hashTx, 0));
// iterate over all COutPoints in mapNextTx whose hash equals the provided hashTx
- while (it != mapNextTx.end() && it->first.hash == hashTx) {
- coins.Spend(it->first.n); // and remove those outputs from coins
+ while (it != mapNextTx.end() && it->first->hash == hashTx) {
+ coins.Spend(it->first->n); // and remove those outputs from coins
it++;
}
}
@@ -414,7 +414,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
const CTransaction& tx = newit->GetTx();
std::set<uint256> setParentTransactions;
for (unsigned int i = 0; i < tx.vin.size(); i++) {
- mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i);
+ mapNextTx.insert(std::make_pair(&tx.vin[i].prevout, &tx));
setParentTransactions.insert(tx.vin[i].prevout.hash);
}
// Don't bother worrying about child transactions of this one.
@@ -500,10 +500,10 @@ void CTxMemPool::removeRecursive(const CTransaction &origTx, std::list<CTransact
// happen during chain re-orgs if origTx isn't re-accepted into
// the mempool for any reason.
for (unsigned int i = 0; i < origTx.vout.size(); i++) {
- std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(origTx.GetHash(), i));
+ auto it = mapNextTx.find(COutPoint(origTx.GetHash(), i));
if (it == mapNextTx.end())
continue;
- txiter nextit = mapTx.find(it->second.ptx->GetHash());
+ txiter nextit = mapTx.find(it->second->GetHash());
assert(nextit != mapTx.end());
txToRemove.insert(nextit);
}
@@ -561,9 +561,9 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>
list<CTransaction> result;
LOCK(cs);
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
- std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(txin.prevout);
+ auto it = mapNextTx.find(txin.prevout);
if (it != mapNextTx.end()) {
- const CTransaction &txConflict = *it->second.ptx;
+ const CTransaction &txConflict = *it->second;
if (txConflict != tx)
{
removeRecursive(txConflict, removed);
@@ -671,10 +671,10 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
assert(coins && coins->IsAvailable(txin.prevout.n));
}
// Check whether its inputs are marked in mapNextTx.
- std::map<COutPoint, CInPoint>::const_iterator it3 = mapNextTx.find(txin.prevout);
+ auto it3 = mapNextTx.find(txin.prevout);
assert(it3 != mapNextTx.end());
- assert(it3->second.ptx == &tx);
- assert(it3->second.n == i);
+ assert(it3->first == &txin.prevout);
+ assert(it3->second == &tx);
i++;
}
assert(setParentCheck == GetMemPoolParents(it));
@@ -701,10 +701,10 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
// Check children against mapNextTx
CTxMemPool::setEntries setChildrenCheck;
- std::map<COutPoint, CInPoint>::const_iterator iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0));
+ auto iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0));
int64_t childSizes = 0;
- for (; iter != mapNextTx.end() && iter->first.hash == it->GetTx().GetHash(); ++iter) {
- txiter childit = mapTx.find(iter->second.ptx->GetHash());
+ for (; iter != mapNextTx.end() && iter->first->hash == it->GetTx().GetHash(); ++iter) {
+ txiter childit = mapTx.find(iter->second->GetHash());
assert(childit != mapTx.end()); // mapNextTx points to in-mempool transactions
if (setChildrenCheck.insert(childit).second) {
childSizes += childit->GetTxSize();
@@ -738,14 +738,12 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
stepsSinceLastRemove = 0;
}
}
- for (std::map<COutPoint, CInPoint>::const_iterator it = mapNextTx.begin(); it != mapNextTx.end(); it++) {
- uint256 hash = it->second.ptx->GetHash();
+ for (auto it = mapNextTx.cbegin(); it != mapNextTx.cend(); it++) {
+ uint256 hash = it->second->GetHash();
indexed_transaction_set::const_iterator it2 = mapTx.find(hash);
const CTransaction& tx = it2->GetTx();
assert(it2 != mapTx.end());
- assert(&tx == it->second.ptx);
- assert(tx.vin.size() > it->second.n);
- assert(it->first == it->second.ptx->vin[it->second.n].prevout);
+ assert(&tx == it->second);
}
assert(totalTxSize == checkTotal);
@@ -770,42 +768,76 @@ bool CTxMemPool::CompareDepthAndScore(const uint256& hasha, const uint256& hashb
namespace {
class DepthAndScoreComparator
{
- CTxMemPool *mp;
public:
- DepthAndScoreComparator(CTxMemPool *mempool) : mp(mempool) {}
- bool operator()(const uint256& a, const uint256& b) { return mp->CompareDepthAndScore(a, b); }
+ bool operator()(const CTxMemPool::indexed_transaction_set::const_iterator& a, const CTxMemPool::indexed_transaction_set::const_iterator& b)
+ {
+ uint64_t counta = a->GetCountWithAncestors();
+ uint64_t countb = b->GetCountWithAncestors();
+ if (counta == countb) {
+ return CompareTxMemPoolEntryByScore()(*a, *b);
+ }
+ return counta < countb;
+ }
};
}
+std::vector<CTxMemPool::indexed_transaction_set::const_iterator> CTxMemPool::GetSortedDepthAndScore() const
+{
+ std::vector<indexed_transaction_set::const_iterator> iters;
+ AssertLockHeld(cs);
+
+ iters.reserve(mapTx.size());
+
+ for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) {
+ iters.push_back(mi);
+ }
+ std::sort(iters.begin(), iters.end(), DepthAndScoreComparator());
+ return iters;
+}
+
void CTxMemPool::queryHashes(vector<uint256>& vtxid)
{
+ LOCK(cs);
+ auto iters = GetSortedDepthAndScore();
+
vtxid.clear();
+ vtxid.reserve(mapTx.size());
+ for (auto it : iters) {
+ vtxid.push_back(it->GetTx().GetHash());
+ }
+}
+
+std::vector<TxMempoolInfo> CTxMemPool::infoAll() const
+{
LOCK(cs);
- vtxid.reserve(mapTx.size());
- for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi)
- vtxid.push_back(mi->GetTx().GetHash());
+ auto iters = GetSortedDepthAndScore();
+
+ std::vector<TxMempoolInfo> ret;
+ ret.reserve(mapTx.size());
+ for (auto it : iters) {
+ ret.push_back(TxMempoolInfo{it->GetSharedTx(), it->GetTime(), CFeeRate(it->GetFee(), it->GetTxSize())});
+ }
- std::sort(vtxid.begin(), vtxid.end(), DepthAndScoreComparator(this));
+ return ret;
}
-bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const
+std::shared_ptr<const CTransaction> CTxMemPool::get(const uint256& hash) const
{
LOCK(cs);
indexed_transaction_set::const_iterator i = mapTx.find(hash);
- if (i == mapTx.end()) return false;
- result = i->GetTx();
- return true;
+ if (i == mapTx.end())
+ return nullptr;
+ return i->GetSharedTx();
}
-bool CTxMemPool::lookupFeeRate(const uint256& hash, CFeeRate& feeRate) const
+TxMempoolInfo CTxMemPool::info(const uint256& hash) const
{
LOCK(cs);
indexed_transaction_set::const_iterator i = mapTx.find(hash);
if (i == mapTx.end())
- return false;
- feeRate = CFeeRate(i->GetFee(), i->GetTxSize());
- return true;
+ return TxMempoolInfo();
+ return TxMempoolInfo{i->GetSharedTx(), i->GetTime(), CFeeRate(i->GetFee(), i->GetTxSize())};
}
CFeeRate CTxMemPool::estimateFee(int nBlocks) const
@@ -918,9 +950,9 @@ bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const {
// 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.
- CTransaction tx;
- if (mempool.lookup(txid, tx)) {
- coins = CCoins(tx, MEMPOOL_HEIGHT);
+ shared_ptr<const CTransaction> ptx = mempool.get(txid);
+ if (ptx) {
+ coins = CCoins(*ptx, MEMPOOL_HEIGHT);
return true;
}
return (base->GetCoins(txid, coins) && !coins.IsPruned());
@@ -1071,8 +1103,8 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<uint256>* pvNoSpendsRe
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
if (exists(txin.prevout.hash))
continue;
- std::map<COutPoint, CInPoint>::iterator it = mapNextTx.lower_bound(COutPoint(txin.prevout.hash, 0));
- if (it == mapNextTx.end() || it->first.hash != txin.prevout.hash)
+ auto it = mapNextTx.lower_bound(COutPoint(txin.prevout.hash, 0));
+ if (it == mapNextTx.end() || it->first->hash != txin.prevout.hash)
pvNoSpendsRemaining->push_back(txin.prevout.hash);
}
}