#include <list>
+#include "addressindex.h"
+#include "spentindex.h"
#include "amount.h"
#include "coins.h"
#include "primitives/transaction.h"
#include "sync.h"
+#undef foreach
+#include "boost/multi_index_container.hpp"
+#include "boost/multi_index/ordered_index.hpp"
+
class CAutoFile;
inline double AllowFreeThreshold()
CAmount nFee; //! Cached to avoid expensive parent-transaction lookups
size_t nTxSize; //! ... and avoid recomputing tx size
size_t nModSize; //! ... and modified size for priority
+ size_t nUsageSize; //! ... and total memory usage
+ CFeeRate feeRate; //! ... and fee per kB
int64_t nTime; //! Local time when entering the mempool
double dPriority; //! Priority when entering the mempool
unsigned int nHeight; //! Chain height when entering the mempool
bool hadNoDependencies; //! Not dependent on any other txs when it entered the mempool
+ bool spendsCoinbase; //! keep track of transactions that spend a coinbase
+ uint32_t nBranchId; //! Branch ID this transaction is known to commit to, cached for efficiency
public:
CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
- int64_t _nTime, double _dPriority, unsigned int _nHeight, bool poolHasNoInputsOf = false);
+ int64_t _nTime, double _dPriority, unsigned int _nHeight,
+ bool poolHasNoInputsOf, bool spendsCoinbase, uint32_t nBranchId);
CTxMemPoolEntry();
CTxMemPoolEntry(const CTxMemPoolEntry& other);
const CTransaction& GetTx() const { return this->tx; }
double GetPriority(unsigned int currentHeight) const;
CAmount GetFee() const { return nFee; }
+ CFeeRate GetFeeRate() const { return feeRate; }
size_t GetTxSize() const { return nTxSize; }
int64_t GetTime() const { return nTime; }
unsigned int GetHeight() const { return nHeight; }
bool WasClearAtEntry() const { return hadNoDependencies; }
+ size_t DynamicMemoryUsage() const { return nUsageSize; }
+
+ bool GetSpendsCoinbase() const { return spendsCoinbase; }
+ uint32_t GetValidatedBranchId() const { return nBranchId; }
+};
+
+// extracts a TxMemPoolEntry's transaction hash
+struct mempoolentry_txid
+{
+ typedef uint256 result_type;
+ result_type operator() (const CTxMemPoolEntry &entry) const
+ {
+ return entry.GetTx().GetHash();
+ }
+};
+
+class CompareTxMemPoolEntryByFee
+{
+public:
+ bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b)
+ {
+ if (a.GetFeeRate() == b.GetFeeRate())
+ return a.GetTime() < b.GetTime();
+ return a.GetFeeRate() > b.GetFeeRate();
+ }
};
class CBlockPolicyEstimator;
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); }
+ size_t DynamicMemoryUsage() const { return 0; }
};
/**
class CTxMemPool
{
private:
- bool fSanityCheck; //! Normally false, true if -checkmempool or -regtest
+ uint32_t nCheckFrequency; //! Value n means that n times in 2^32 we check.
unsigned int nTransactionsUpdated;
CBlockPolicyEstimator* minerPolicyEstimator;
- uint64_t totalTxSize; //! sum of all mempool tx' byte sizes
+ uint64_t totalTxSize = 0; //! sum of all mempool tx' byte sizes
+ uint64_t cachedInnerUsage; //! sum of dynamic memory usage of all the map elements (NOT the maps themselves)
public:
+ typedef boost::multi_index_container<
+ CTxMemPoolEntry,
+ boost::multi_index::indexed_by<
+ // sorted by txid
+ boost::multi_index::ordered_unique<mempoolentry_txid>,
+ // sorted by fee rate
+ boost::multi_index::ordered_non_unique<
+ boost::multi_index::identity<CTxMemPoolEntry>,
+ CompareTxMemPoolEntryByFee
+ >
+ >
+ > indexed_transaction_set;
+
mutable CCriticalSection cs;
- std::map<uint256, CTxMemPoolEntry> mapTx;
+ indexed_transaction_set mapTx;
+
+private:
+ typedef std::map<CMempoolAddressDeltaKey, CMempoolAddressDelta, CMempoolAddressDeltaKeyCompare> addressDeltaMap;
+ addressDeltaMap mapAddress;
+
+ typedef std::map<uint256, std::vector<CMempoolAddressDeltaKey> > addressDeltaMapInserted;
+ addressDeltaMapInserted mapAddressInserted;
+
+ typedef std::map<CSpentIndexKey, CSpentIndexValue, CSpentIndexKeyCompare> mapSpentIndex;
+ mapSpentIndex mapSpent;
+
+ typedef std::map<uint256, std::vector<CSpentIndexKey> > mapSpentIndexInserted;
+ mapSpentIndexInserted mapSpentInserted;
+
+public:
std::map<COutPoint, CInPoint> mapNextTx;
std::map<uint256, const CTransaction*> mapNullifiers;
std::map<uint256, std::pair<double, CAmount> > mapDeltas;
* check does nothing.
*/
void check(const CCoinsViewCache *pcoins) const;
- void setSanityCheck(bool _fSanityCheck) { fSanityCheck = _fSanityCheck; }
+ void setSanityCheck(double dFrequency = 1.0) { nCheckFrequency = dFrequency * 4294967296.0; }
bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate = true);
+ void addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view);
+ bool getAddressIndex(std::vector<std::pair<uint160, int> > &addresses,
+ std::vector<std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> > &results);
+ bool removeAddressIndex(const uint256 txhash);
+
+ void addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view);
+ bool getSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value);
+ bool removeSpentIndex(const uint256 txhash);
void remove(const CTransaction &tx, std::list<CTransaction>& removed, bool fRecursive = false);
void removeWithAnchor(const uint256 &invalidRoot);
- void removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight);
+ void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
void removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed);
+ void removeExpired(unsigned int nBlockHeight);
void removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
std::list<CTransaction>& conflicts, bool fCurrentEstimate = true);
+ void removeWithoutBranchId(uint32_t nMemPoolBranchId);
void clear();
void queryHashes(std::vector<uint256>& vtxid);
void pruneSpent(const uint256& hash, CCoins &coins);
LOCK(cs);
return mapTx.size();
}
+
uint64_t GetTotalTxSize()
{
LOCK(cs);
/** Write/Read estimates to disk */
bool WriteFeeEstimates(CAutoFile& fileout) const;
bool ReadFeeEstimates(CAutoFile& filein);
+
+ size_t DynamicMemoryUsage() const;
};
/**