@ -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,76 @@ 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
bool CTxMemPool : : lookup ( uint256 hash , CTransaction & result , int64_t & time ) const
{
{
LOCK ( cs ) ;
LOCK ( cs ) ;
indexed_transaction_set : : const_iterator i = mapTx . find ( hash ) ;
auto iters = GetSortedDepthAndScore ( ) ;
if ( i = = mapTx . end ( ) ) return false ;
result = i - > GetTx ( ) ;
std : : vector < TxMempoolInfo > ret ;
time = i - > GetTime ( ) ;
ret . reserve ( mapTx . size ( ) ) ;
return true ;
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 ) const
std : : shared_ptr < const CTransaction > CTxMemPool : : get ( const uint256 & hash ) const
{
{
int64_t time ;
LOCK ( cs ) ;
return CTxMemPool : : lookup ( hash , result , time ) ;
indexed_transaction_set : : const_iterator i = mapTx . find ( hash ) ;
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 ) ;
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
@ -924,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
// 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)
// 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.
// transactions. First checking the underlying cache risks returning a pruned entry instead.
CTransaction tx ;
shared_ptr < const CTransaction > p tx = mempool . get ( txid ) ;
if ( mem pool . lookup ( txid , tx ) ) {
if ( ptx ) {
coins = CCoins ( tx , MEMPOOL_HEIGHT ) ;
coins = CCoins ( * p tx, MEMPOOL_HEIGHT ) ;
return true ;
return true ;
}
}
return ( base - > GetCoins ( txid , coins ) & & ! coins . IsPruned ( ) ) ;
return ( base - > GetCoins ( txid , coins ) & & ! coins . IsPruned ( ) ) ;