Skip to content

Commit

Permalink
Replaced mapNextTx with smaller map to reduce memory usage.
Browse files Browse the repository at this point in the history
Ref: PR bitcoin#7997 in Bitcoin core
  • Loading branch information
wqking committed Dec 13, 2019
1 parent be2f913 commit 3a7c813
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 40 deletions.
1 change: 1 addition & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ BITCOIN_CORE_H = \
hash.h \
httprpc.h \
httpserver.h \
indirectmap.h \
init.h \
kernel.h \
swifttx.h \
Expand Down
57 changes: 57 additions & 0 deletions src/indirectmap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) 2016 The Bitcoin Core developers
// Copyright (c) 2019 The Phore Developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_INDIRECTMAP_H
#define BITCOIN_INDIRECTMAP_H

template <class T>
struct DereferencingComparator { bool operator()(const T a, const T b) const { return *a < *b; } };

/* Map whose keys are pointers, but are compared by their dereferenced values.
*
* Differs from a plain std::map<const K*, T, DereferencingComparator<K*> > in
* that methods that take a key for comparison take a K rather than taking a K*
* (taking a K* would be confusing, since it's the value rather than the address
* of the object for comparison that matters due to the dereferencing comparator).
*
* Objects pointed to by keys must not be modified in any way that changes the
* result of DereferencingComparator.
*/
template <class K, class T>
class IndirectMap {
private:
typedef std::map<const K*, T, DereferencingComparator<const K*> > base;
base m;
public:
typedef typename base::iterator iterator;
typedef typename base::const_iterator const_iterator;
typedef typename base::size_type size_type;
typedef typename base::value_type value_type;

// passthrough (pointer interface)
std::pair<iterator, bool> insert(const value_type& value) { return m.insert(value); }

// pass address (value interface)
iterator find(const K& key) { return m.find(&key); }
const_iterator find(const K& key) const { return m.find(&key); }
iterator lower_bound(const K& key) { return m.lower_bound(&key); }
const_iterator lower_bound(const K& key) const { return m.lower_bound(&key); }
size_type erase(const K& key) { return m.erase(&key); }
size_type count(const K& key) const { return m.count(&key); }

// passthrough
bool empty() const { return m.empty(); }
size_type size() const { return m.size(); }
size_type max_size() const { return m.max_size(); }
void clear() { m.clear(); }
iterator begin() { return m.begin(); }
iterator end() { return m.end(); }
const_iterator begin() const { return m.begin(); }
const_iterator end() const { return m.end(); }
const_iterator cbegin() const { return m.cbegin(); }
const_iterator cend() const { return m.cend(); }
};

#endif // BITCOIN_INDIRECTMAP_H
33 changes: 15 additions & 18 deletions src/txmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,11 +392,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++;
}
}
Expand Down Expand Up @@ -425,7 +425,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry& entry)
const CTransaction& tx = mapTx[hash].GetTx();
if(!tx.IsZerocoinSpend()) {
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));
}
nTransactionsUpdated++;
totalTxSize += entry.GetTxSize();
Expand All @@ -447,10 +447,10 @@ void CTxMemPool::remove(const CTransaction& origTx, std::list<CTransaction>& rem
// 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;
txToRemove.push_back(it->second.ptx->GetHash());
txToRemove.push_back(it->second->GetHash());
}
}
while (!txToRemove.empty()) {
Expand All @@ -461,10 +461,10 @@ void CTxMemPool::remove(const CTransaction& origTx, std::list<CTransaction>& rem
const CTransaction& tx = mapTx[hash].GetTx();
if (fRecursive) {
for (unsigned int i = 0; i < tx.vout.size(); i++) {
std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(hash, i));
auto it = mapNextTx.find(COutPoint(hash, i));
if (it == mapNextTx.end())
continue;
txToRemove.push_back(it->second.ptx->GetHash());
txToRemove.push_back(it->second->GetHash());
}
}
BOOST_FOREACH (const CTxIn& txin, tx.vin)
Expand Down Expand Up @@ -509,9 +509,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) {
remove(txConflict, removed, true);
}
Expand Down Expand Up @@ -582,10 +582,9 @@ 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->second == &tx);
i++;
}
if (fDependsWait)
Expand Down Expand Up @@ -613,14 +612,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.begin(); it != mapNextTx.end(); it++) {
uint256 hash = it->second->GetHash();
map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(hash);
const CTransaction& tx = it2->second.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);
Expand Down
24 changes: 2 additions & 22 deletions src/txmempool.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "amount.h"
#include "coins.h"
#include "indirectmap.h"
#include "primitives/transaction.h"
#include "sync.h"

Expand Down Expand Up @@ -69,27 +70,6 @@ class CTxMemPoolEntry

class CMinerPolicyEstimator;

/** An inpoint - a combination of a transaction and an index n into its vin */
class CInPoint
{
public:
const CTransaction* ptx;
uint32_t n;

CInPoint() { SetNull(); }
CInPoint(const CTransaction* ptxIn, uint32_t nIn)
{
ptx = ptxIn;
n = nIn;
}
void SetNull()
{
ptx = NULL;
n = (uint32_t)-1;
}
bool IsNull() const { return (ptx == NULL && n == (uint32_t)-1); }
};

/**
* CTxMemPool stores valid-according-to-the-current-best-chain
* transactions that may be included in the next block.
Expand All @@ -113,7 +93,7 @@ class CTxMemPool
public:
mutable CCriticalSection cs;
std::map<uint256, CTxMemPoolEntry> mapTx;
std::map<COutPoint, CInPoint> mapNextTx;
IndirectMap<COutPoint, const CTransaction*> mapNextTx;
std::map<uint256, std::pair<double, CAmount> > mapDeltas;

CTxMemPool(const CFeeRate& _minRelayFee);
Expand Down

0 comments on commit 3a7c813

Please sign in to comment.