Separate core memory usage computation in core_memusage.h
This commit is contained in:
parent
89289d875d
commit
9e38d0f745
11 changed files with 76 additions and 99 deletions
|
@ -94,6 +94,7 @@ BITCOIN_CORE_H = \
|
||||||
consensus/params.h \
|
consensus/params.h \
|
||||||
consensus/validation.h \
|
consensus/validation.h \
|
||||||
core_io.h \
|
core_io.h \
|
||||||
|
core_memusage.h \
|
||||||
eccryptoverify.h \
|
eccryptoverify.h \
|
||||||
ecwrapper.h \
|
ecwrapper.h \
|
||||||
hash.h \
|
hash.h \
|
||||||
|
|
|
@ -83,7 +83,7 @@ CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const
|
||||||
// version as fresh.
|
// version as fresh.
|
||||||
ret->second.flags = CCoinsCacheEntry::FRESH;
|
ret->second.flags = CCoinsCacheEntry::FRESH;
|
||||||
}
|
}
|
||||||
cachedCoinsUsage += memusage::DynamicUsage(ret->second.coins);
|
cachedCoinsUsage += ret->second.coins.DynamicMemoryUsage();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) {
|
||||||
ret.first->second.flags = CCoinsCacheEntry::FRESH;
|
ret.first->second.flags = CCoinsCacheEntry::FRESH;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cachedCoinUsage = memusage::DynamicUsage(ret.first->second.coins);
|
cachedCoinUsage = ret.first->second.coins.DynamicMemoryUsage();
|
||||||
}
|
}
|
||||||
// Assume that whenever ModifyCoins is called, the entry will be modified.
|
// Assume that whenever ModifyCoins is called, the entry will be modified.
|
||||||
ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
|
ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
|
||||||
|
@ -159,7 +159,7 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
|
||||||
assert(it->second.flags & CCoinsCacheEntry::FRESH);
|
assert(it->second.flags & CCoinsCacheEntry::FRESH);
|
||||||
CCoinsCacheEntry& entry = cacheCoins[it->first];
|
CCoinsCacheEntry& entry = cacheCoins[it->first];
|
||||||
entry.coins.swap(it->second.coins);
|
entry.coins.swap(it->second.coins);
|
||||||
cachedCoinsUsage += memusage::DynamicUsage(entry.coins);
|
cachedCoinsUsage += entry.coins.DynamicMemoryUsage();
|
||||||
entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH;
|
entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -167,13 +167,13 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
|
||||||
// The grandparent does not have an entry, and the child is
|
// The grandparent does not have an entry, and the child is
|
||||||
// modified and being pruned. This means we can just delete
|
// modified and being pruned. This means we can just delete
|
||||||
// it from the parent.
|
// it from the parent.
|
||||||
cachedCoinsUsage -= memusage::DynamicUsage(itUs->second.coins);
|
cachedCoinsUsage -= itUs->second.coins.DynamicMemoryUsage();
|
||||||
cacheCoins.erase(itUs);
|
cacheCoins.erase(itUs);
|
||||||
} else {
|
} else {
|
||||||
// A normal modification.
|
// A normal modification.
|
||||||
cachedCoinsUsage -= memusage::DynamicUsage(itUs->second.coins);
|
cachedCoinsUsage -= itUs->second.coins.DynamicMemoryUsage();
|
||||||
itUs->second.coins.swap(it->second.coins);
|
itUs->second.coins.swap(it->second.coins);
|
||||||
cachedCoinsUsage += memusage::DynamicUsage(itUs->second.coins);
|
cachedCoinsUsage += itUs->second.coins.DynamicMemoryUsage();
|
||||||
itUs->second.flags |= CCoinsCacheEntry::DIRTY;
|
itUs->second.flags |= CCoinsCacheEntry::DIRTY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,6 +261,6 @@ CCoinsModifier::~CCoinsModifier()
|
||||||
cache.cacheCoins.erase(it);
|
cache.cacheCoins.erase(it);
|
||||||
} else {
|
} else {
|
||||||
// If the coin still exists after the modification, add the new usage
|
// If the coin still exists after the modification, add the new usage
|
||||||
cache.cachedCoinsUsage += memusage::DynamicUsage(it->second.coins);
|
cache.cachedCoinsUsage += it->second.coins.DynamicMemoryUsage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#define BITCOIN_COINS_H
|
#define BITCOIN_COINS_H
|
||||||
|
|
||||||
#include "compressor.h"
|
#include "compressor.h"
|
||||||
|
#include "core_memusage.h"
|
||||||
#include "memusage.h"
|
#include "memusage.h"
|
||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
|
@ -257,8 +258,7 @@ public:
|
||||||
size_t DynamicMemoryUsage() const {
|
size_t DynamicMemoryUsage() const {
|
||||||
size_t ret = memusage::DynamicUsage(vout);
|
size_t ret = memusage::DynamicUsage(vout);
|
||||||
BOOST_FOREACH(const CTxOut &out, vout) {
|
BOOST_FOREACH(const CTxOut &out, vout) {
|
||||||
const std::vector<unsigned char> *script = &out.scriptPubKey;
|
ret += RecursiveDynamicUsage(out.scriptPubKey);
|
||||||
ret += memusage::DynamicUsage(*script);
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
62
src/core_memusage.h
Normal file
62
src/core_memusage.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// Copyright (c) 2015 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#ifndef BITCOIN_CORE_MEMUSAGE_H
|
||||||
|
#define BITCOIN_CORE_MEMUSAGE_H
|
||||||
|
|
||||||
|
#include "primitives/transaction.h"
|
||||||
|
#include "primitives/block.h"
|
||||||
|
#include "memusage.h"
|
||||||
|
|
||||||
|
static inline size_t RecursiveDynamicUsage(const CScript& script) {
|
||||||
|
return memusage::DynamicUsage(*static_cast<const std::vector<unsigned char>*>(&script));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t RecursiveDynamicUsage(const COutPoint& out) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t RecursiveDynamicUsage(const CTxIn& in) {
|
||||||
|
return RecursiveDynamicUsage(in.scriptSig) + RecursiveDynamicUsage(in.prevout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t RecursiveDynamicUsage(const CTxOut& out) {
|
||||||
|
return RecursiveDynamicUsage(out.scriptPubKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t RecursiveDynamicUsage(const CTransaction& tx) {
|
||||||
|
size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout);
|
||||||
|
for (std::vector<CTxIn>::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) {
|
||||||
|
mem += RecursiveDynamicUsage(*it);
|
||||||
|
}
|
||||||
|
for (std::vector<CTxOut>::const_iterator it = tx.vout.begin(); it != tx.vout.end(); it++) {
|
||||||
|
mem += RecursiveDynamicUsage(*it);
|
||||||
|
}
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t RecursiveDynamicUsage(const CMutableTransaction& tx) {
|
||||||
|
size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout);
|
||||||
|
for (std::vector<CTxIn>::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) {
|
||||||
|
mem += RecursiveDynamicUsage(*it);
|
||||||
|
}
|
||||||
|
for (std::vector<CTxOut>::const_iterator it = tx.vout.begin(); it != tx.vout.end(); it++) {
|
||||||
|
mem += RecursiveDynamicUsage(*it);
|
||||||
|
}
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t RecursiveDynamicUsage(const CBlock& block) {
|
||||||
|
size_t mem = memusage::DynamicUsage(block.vtx) + memusage::DynamicUsage(block.vMerkleTree);
|
||||||
|
for (std::vector<CTransaction>::const_iterator it = block.vtx.begin(); it != block.vtx.end(); it++) {
|
||||||
|
mem += RecursiveDynamicUsage(*it);
|
||||||
|
}
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t RecursiveDynamicUsage(const CBlockLocator& locator) {
|
||||||
|
return memusage::DynamicUsage(locator.vHave);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BITCOIN_CORE_MEMUSAGE_H
|
|
@ -34,28 +34,14 @@ static inline size_t DynamicUsage(const float& v) { return 0; }
|
||||||
static inline size_t DynamicUsage(const double& v) { return 0; }
|
static inline size_t DynamicUsage(const double& v) { return 0; }
|
||||||
template<typename X> static inline size_t DynamicUsage(X * const &v) { return 0; }
|
template<typename X> static inline size_t DynamicUsage(X * const &v) { return 0; }
|
||||||
template<typename X> static inline size_t DynamicUsage(const X * const &v) { return 0; }
|
template<typename X> static inline size_t DynamicUsage(const X * const &v) { return 0; }
|
||||||
template<typename X, typename Y> static inline size_t DynamicUsage(std::pair<X, Y> &p) { return 0; }
|
|
||||||
|
|
||||||
/** Compute the memory used for dynamically allocated but owned data structures.
|
/** Compute the memory used for dynamically allocated but owned data structures.
|
||||||
* For generic data types, this is *not* recursive. DynamicUsage(vector<vector<int> >)
|
* For generic data types, this is *not* recursive. DynamicUsage(vector<vector<int> >)
|
||||||
* will compute the memory used for the vector<int>'s, but not for the ints inside.
|
* will compute the memory used for the vector<int>'s, but not for the ints inside.
|
||||||
* This is for efficiency reasons, as these functions are intended to be fast. If
|
* This is for efficiency reasons, as these functions are intended to be fast. If
|
||||||
* application data structures require more accurate inner accounting, they should
|
* application data structures require more accurate inner accounting, they should
|
||||||
* use RecursiveDynamicUsage, iterate themselves, or use more efficient caching +
|
* iterate themselves, or use more efficient caching + updating on modification.
|
||||||
* updating on modification.
|
|
||||||
*/
|
*/
|
||||||
template<typename X> static size_t DynamicUsage(const std::vector<X>& v);
|
|
||||||
template<typename X> static size_t DynamicUsage(const std::set<X>& s);
|
|
||||||
template<typename X, typename Y> static size_t DynamicUsage(const std::map<X, Y>& m);
|
|
||||||
template<typename X, typename Y> static size_t DynamicUsage(const boost::unordered_set<X, Y>& s);
|
|
||||||
template<typename X, typename Y, typename Z> static size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& s);
|
|
||||||
template<typename X> static size_t DynamicUsage(const X& x);
|
|
||||||
|
|
||||||
template<typename X> static size_t RecursiveDynamicUsage(const std::vector<X>& v);
|
|
||||||
template<typename X> static size_t RecursiveDynamicUsage(const std::set<X>& v);
|
|
||||||
template<typename X, typename Y> static size_t RecursiveDynamicUsage(const std::map<X, Y>& v);
|
|
||||||
template<typename X, typename Y> static size_t RecursiveDynamicUsage(const std::pair<X, Y>& v);
|
|
||||||
template<typename X> static size_t RecursiveDynamicUsage(const X& v);
|
|
||||||
|
|
||||||
static inline size_t MallocUsage(size_t alloc)
|
static inline size_t MallocUsage(size_t alloc)
|
||||||
{
|
{
|
||||||
|
@ -88,54 +74,18 @@ static inline size_t DynamicUsage(const std::vector<X>& v)
|
||||||
return MallocUsage(v.capacity() * sizeof(X));
|
return MallocUsage(v.capacity() * sizeof(X));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename X>
|
|
||||||
static inline size_t RecursiveDynamicUsage(const std::vector<X>& v)
|
|
||||||
{
|
|
||||||
size_t usage = DynamicUsage(v);
|
|
||||||
BOOST_FOREACH(const X& x, v) {
|
|
||||||
usage += RecursiveDynamicUsage(x);
|
|
||||||
}
|
|
||||||
return usage;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename X>
|
template<typename X>
|
||||||
static inline size_t DynamicUsage(const std::set<X>& s)
|
static inline size_t DynamicUsage(const std::set<X>& s)
|
||||||
{
|
{
|
||||||
return MallocUsage(sizeof(stl_tree_node<X>)) * s.size();
|
return MallocUsage(sizeof(stl_tree_node<X>)) * s.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename X>
|
|
||||||
static inline size_t RecursiveDynamicUsage(const std::set<X>& v)
|
|
||||||
{
|
|
||||||
size_t usage = DynamicUsage(v);
|
|
||||||
BOOST_FOREACH(const X& x, v) {
|
|
||||||
usage += RecursiveDynamicUsage(x);
|
|
||||||
}
|
|
||||||
return usage;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename X, typename Y>
|
template<typename X, typename Y>
|
||||||
static inline size_t DynamicUsage(const std::map<X, Y>& m)
|
static inline size_t DynamicUsage(const std::map<X, Y>& m)
|
||||||
{
|
{
|
||||||
return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y> >)) * m.size();
|
return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y> >)) * m.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename X, typename Y>
|
|
||||||
static inline size_t RecursiveDynamicUsage(const std::map<X, Y>& v)
|
|
||||||
{
|
|
||||||
size_t usage = DynamicUsage(v);
|
|
||||||
for (typename std::map<X, Y>::const_iterator it = v.begin(); it != v.end(); it++) {
|
|
||||||
usage += RecursiveDynamicUsage(*it);
|
|
||||||
}
|
|
||||||
return usage;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename X, typename Y>
|
|
||||||
static inline size_t RecursiveDynamicUsage(const std::pair<X, Y>& v)
|
|
||||||
{
|
|
||||||
return RecursiveDynamicUsage(v.first) + RecursiveDynamicUsage(v.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Boost data structures
|
// Boost data structures
|
||||||
|
|
||||||
template<typename X>
|
template<typename X>
|
||||||
|
@ -157,20 +107,6 @@ static inline size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& m)
|
||||||
return MallocUsage(sizeof(boost_unordered_node<std::pair<const X, Y> >)) * m.size() + MallocUsage(sizeof(void*) * m.bucket_count());
|
return MallocUsage(sizeof(boost_unordered_node<std::pair<const X, Y> >)) * m.size() + MallocUsage(sizeof(void*) * m.bucket_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispatch to class method as fallback
|
|
||||||
|
|
||||||
template<typename X>
|
|
||||||
static inline size_t DynamicUsage(const X& x)
|
|
||||||
{
|
|
||||||
return x.DynamicMemoryUsage();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename X>
|
|
||||||
static inline size_t RecursiveDynamicUsage(const X& x)
|
|
||||||
{
|
|
||||||
return DynamicUsage(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -72,11 +72,6 @@ void CTransaction::UpdateHash() const
|
||||||
*const_cast<uint256*>(&hash) = SerializeHash(*this);
|
*const_cast<uint256*>(&hash) = SerializeHash(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CTransaction::DynamicMemoryUsage() const
|
|
||||||
{
|
|
||||||
return memusage::RecursiveDynamicUsage(vin) + memusage::RecursiveDynamicUsage(vout);
|
|
||||||
}
|
|
||||||
|
|
||||||
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { }
|
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { }
|
||||||
|
|
||||||
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {
|
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#define BITCOIN_PRIMITIVES_TRANSACTION_H
|
#define BITCOIN_PRIMITIVES_TRANSACTION_H
|
||||||
|
|
||||||
#include "amount.h"
|
#include "amount.h"
|
||||||
#include "memusage.h"
|
|
||||||
#include "script/script.h"
|
#include "script/script.h"
|
||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
|
@ -49,8 +48,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
|
|
||||||
size_t DynamicMemoryUsage() const { return 0; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** An input of a transaction. It contains the location of the previous
|
/** An input of a transaction. It contains the location of the previous
|
||||||
|
@ -99,8 +96,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
|
|
||||||
size_t DynamicMemoryUsage() const { return scriptSig.DynamicMemoryUsage(); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** An output of a transaction. It contains the public key that the next input
|
/** An output of a transaction. It contains the public key that the next input
|
||||||
|
@ -171,8 +166,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
|
|
||||||
size_t DynamicMemoryUsage() const { return scriptPubKey.DynamicMemoryUsage(); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CMutableTransaction;
|
struct CMutableTransaction;
|
||||||
|
@ -256,8 +249,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
|
|
||||||
size_t DynamicMemoryUsage() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A mutable version of CTransaction. */
|
/** A mutable version of CTransaction. */
|
||||||
|
|
|
@ -260,8 +260,3 @@ std::string CScript::ToString() const
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CScript::DynamicMemoryUsage() const
|
|
||||||
{
|
|
||||||
return memusage::DynamicUsage(*(static_cast<const std::vector<unsigned char>*>(this)));
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#ifndef BITCOIN_SCRIPT_SCRIPT_H
|
#ifndef BITCOIN_SCRIPT_SCRIPT_H
|
||||||
#define BITCOIN_SCRIPT_SCRIPT_H
|
#define BITCOIN_SCRIPT_SCRIPT_H
|
||||||
|
|
||||||
#include "memusage.h"
|
|
||||||
#include "crypto/common.h"
|
#include "crypto/common.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -608,8 +607,6 @@ public:
|
||||||
// The default std::vector::clear() does not release memory.
|
// The default std::vector::clear() does not release memory.
|
||||||
std::vector<unsigned char>().swap(*this);
|
std::vector<unsigned char>().swap(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t DynamicMemoryUsage() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CReserveScript
|
class CReserveScript
|
||||||
|
|
|
@ -70,9 +70,9 @@ public:
|
||||||
// Manually recompute the dynamic usage of the whole data, and compare it.
|
// Manually recompute the dynamic usage of the whole data, and compare it.
|
||||||
size_t ret = memusage::DynamicUsage(cacheCoins);
|
size_t ret = memusage::DynamicUsage(cacheCoins);
|
||||||
for (CCoinsMap::iterator it = cacheCoins.begin(); it != cacheCoins.end(); it++) {
|
for (CCoinsMap::iterator it = cacheCoins.begin(); it != cacheCoins.end(); it++) {
|
||||||
ret += memusage::DynamicUsage(it->second.coins);
|
ret += it->second.coins.DynamicMemoryUsage();
|
||||||
}
|
}
|
||||||
BOOST_CHECK_EQUAL(memusage::DynamicUsage(*this), ret);
|
BOOST_CHECK_EQUAL(DynamicMemoryUsage(), ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
|
||||||
{
|
{
|
||||||
nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
|
nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
|
||||||
nModSize = tx.CalculateModifiedSize(nTxSize);
|
nModSize = tx.CalculateModifiedSize(nTxSize);
|
||||||
nUsageSize = tx.DynamicMemoryUsage();
|
nUsageSize = RecursiveDynamicUsage(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
|
CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
|
||||||
|
|
Loading…
Reference in a new issue