|
|
@ -23,18 +23,18 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, |
|
|
|
int64_t _nTime, double _entryPriority, unsigned int _entryHeight, |
|
|
|
int64_t _nTime, double _entryPriority, unsigned int _entryHeight, |
|
|
|
bool poolHasNoInputsOf, CAmount _inChainInputValue, |
|
|
|
bool poolHasNoInputsOf, CAmount _inChainInputValue, |
|
|
|
bool _spendsCoinbase, unsigned int _sigOps, LockPoints lp): |
|
|
|
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), |
|
|
|
hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue), |
|
|
|
spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOps), lockPoints(lp) |
|
|
|
spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOps), lockPoints(lp) |
|
|
|
{ |
|
|
|
{ |
|
|
|
nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); |
|
|
|
nTxSize = ::GetSerializeSize(_tx, SER_NETWORK, PROTOCOL_VERSION); |
|
|
|
nModSize = tx.CalculateModifiedSize(nTxSize); |
|
|
|
nModSize = _tx.CalculateModifiedSize(nTxSize); |
|
|
|
nUsageSize = RecursiveDynamicUsage(tx); |
|
|
|
nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx); |
|
|
|
|
|
|
|
|
|
|
|
nCountWithDescendants = 1; |
|
|
|
nCountWithDescendants = 1; |
|
|
|
nSizeWithDescendants = nTxSize; |
|
|
|
nSizeWithDescendants = nTxSize; |
|
|
|
nModFeesWithDescendants = nFee; |
|
|
|
nModFeesWithDescendants = nFee; |
|
|
|
CAmount nValueIn = tx.GetValueOut()+nFee; |
|
|
|
CAmount nValueIn = _tx.GetValueOut()+nFee; |
|
|
|
assert(inChainInputValue <= nValueIn); |
|
|
|
assert(inChainInputValue <= nValueIn); |
|
|
|
|
|
|
|
|
|
|
|
feeDelta = 0; |
|
|
|
feeDelta = 0; |
|
|
@ -768,50 +768,86 @@ bool CTxMemPool::CompareDepthAndScore(const uint256& hasha, const uint256& hashb |
|
|
|
namespace { |
|
|
|
namespace { |
|
|
|
class DepthAndScoreComparator |
|
|
|
class DepthAndScoreComparator |
|
|
|
{ |
|
|
|
{ |
|
|
|
CTxMemPool *mp; |
|
|
|
|
|
|
|
public: |
|
|
|
public: |
|
|
|
DepthAndScoreComparator(CTxMemPool *mempool) : mp(mempool) {} |
|
|
|
bool operator()(const CTxMemPool::indexed_transaction_set::const_iterator& a, const CTxMemPool::indexed_transaction_set::const_iterator& b) |
|
|
|
bool operator()(const uint256& a, const uint256& b) { return mp->CompareDepthAndScore(a, b); } |
|
|
|
{ |
|
|
|
|
|
|
|
uint64_t counta = a->GetCountWithAncestors(); |
|
|
|
|
|
|
|
uint64_t countb = b->GetCountWithAncestors(); |
|
|
|
|
|
|
|
if (counta == countb) { |
|
|
|
|
|
|
|
return CompareTxMemPoolEntryByScore()(*a, *b); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return counta < countb; |
|
|
|
|
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CTxMemPool::queryHashes(vector<uint256>& vtxid) |
|
|
|
std::vector<CTxMemPool::indexed_transaction_set::const_iterator> CTxMemPool::GetSortedDepthAndScore() const |
|
|
|
{ |
|
|
|
{ |
|
|
|
vtxid.clear(); |
|
|
|
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); |
|
|
|
LOCK(cs); |
|
|
|
|
|
|
|
auto iters = GetSortedDepthAndScore(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vtxid.clear(); |
|
|
|
vtxid.reserve(mapTx.size()); |
|
|
|
vtxid.reserve(mapTx.size()); |
|
|
|
for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) |
|
|
|
|
|
|
|
vtxid.push_back(mi->GetTx().GetHash()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::sort(vtxid.begin(), vtxid.end(), DepthAndScoreComparator(this)); |
|
|
|
for (auto it : iters) { |
|
|
|
|
|
|
|
vtxid.push_back(it->GetTx().GetHash()); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<TxMempoolInfo> CTxMemPool::infoAll() const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LOCK(cs); |
|
|
|
|
|
|
|
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())}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool CTxMemPool::lookup(uint256 hash, CTransaction& result, int64_t& time) const |
|
|
|
std::shared_ptr<const CTransaction> CTxMemPool::get(const uint256& hash) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
LOCK(cs); |
|
|
|
LOCK(cs); |
|
|
|
indexed_transaction_set::const_iterator i = mapTx.find(hash); |
|
|
|
indexed_transaction_set::const_iterator i = mapTx.find(hash); |
|
|
|
if (i == mapTx.end()) return false; |
|
|
|
if (i == mapTx.end()) |
|
|
|
result = i->GetTx(); |
|
|
|
return nullptr; |
|
|
|
time = i->GetTime(); |
|
|
|
return i->GetSharedTx(); |
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const |
|
|
|
bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
int64_t time; |
|
|
|
auto tx = get(hash); |
|
|
|
return CTxMemPool::lookup(hash, result, time); |
|
|
|
if (tx) { |
|
|
|
|
|
|
|
result = *tx; |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool CTxMemPool::lookupFeeRate(const uint256& hash, CFeeRate& feeRate) const |
|
|
|
TxMempoolInfo CTxMemPool::info(const uint256& hash) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
LOCK(cs); |
|
|
|
LOCK(cs); |
|
|
|
indexed_transaction_set::const_iterator i = mapTx.find(hash); |
|
|
|
indexed_transaction_set::const_iterator i = mapTx.find(hash); |
|
|
|
if (i == mapTx.end()) |
|
|
|
if (i == mapTx.end()) |
|
|
|
return false; |
|
|
|
return TxMempoolInfo(); |
|
|
|
feeRate = CFeeRate(i->GetFee(), i->GetTxSize()); |
|
|
|
return TxMempoolInfo{i->GetSharedTx(), i->GetTime(), CFeeRate(i->GetFee(), i->GetTxSize())}; |
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CFeeRate CTxMemPool::estimateFee(int nBlocks) const |
|
|
|
CFeeRate CTxMemPool::estimateFee(int nBlocks) const |
|
|
|