@ -33,7 +33,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
nCountWithDescendants = 1 ;
nCountWithDescendants = 1 ;
nSizeWithDescendants = nTxSize ;
nSizeWithDescendants = nTxSize ;
nFeesWithDescendants = nFee ;
nMod FeesWithDescendants = nFee ;
CAmount nValueIn = tx . GetValueOut ( ) + nFee ;
CAmount nValueIn = tx . GetValueOut ( ) + nFee ;
assert ( inChainInputValue < = nValueIn ) ;
assert ( inChainInputValue < = nValueIn ) ;
@ -57,6 +57,7 @@ CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
void CTxMemPoolEntry : : UpdateFeeDelta ( int64_t newFeeDelta )
void CTxMemPoolEntry : : UpdateFeeDelta ( int64_t newFeeDelta )
{
{
nModFeesWithDescendants + = newFeeDelta - feeDelta ;
feeDelta = newFeeDelta ;
feeDelta = newFeeDelta ;
}
}
@ -114,7 +115,7 @@ bool CTxMemPool::UpdateForDescendants(txiter updateIt, int maxDescendantsToVisit
BOOST_FOREACH ( txiter cit , setAllDescendants ) {
BOOST_FOREACH ( txiter cit , setAllDescendants ) {
if ( ! setExclude . count ( cit - > GetTx ( ) . GetHash ( ) ) ) {
if ( ! setExclude . count ( cit - > GetTx ( ) . GetHash ( ) ) ) {
modifySize + = cit - > GetTxSize ( ) ;
modifySize + = cit - > GetTxSize ( ) ;
modifyFee + = cit - > GetFee ( ) ;
modifyFee + = cit - > GetModified Fee ( ) ;
modifyCount + + ;
modifyCount + + ;
cachedDescendants [ updateIt ] . insert ( cit ) ;
cachedDescendants [ updateIt ] . insert ( cit ) ;
}
}
@ -244,7 +245,7 @@ void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors
}
}
const int64_t updateCount = ( add ? 1 : - 1 ) ;
const int64_t updateCount = ( add ? 1 : - 1 ) ;
const int64_t updateSize = updateCount * it - > GetTxSize ( ) ;
const int64_t updateSize = updateCount * it - > GetTxSize ( ) ;
const CAmount updateFee = updateCount * it - > GetFee ( ) ;
const CAmount updateFee = updateCount * it - > GetModified Fee ( ) ;
BOOST_FOREACH ( txiter ancestorIt , setAncestors ) {
BOOST_FOREACH ( txiter ancestorIt , setAncestors ) {
mapTx . modify ( ancestorIt , update_descendant_state ( updateSize , updateFee , updateCount ) ) ;
mapTx . modify ( ancestorIt , update_descendant_state ( updateSize , updateFee , updateCount ) ) ;
}
}
@ -304,7 +305,7 @@ void CTxMemPoolEntry::SetDirty()
{
{
nCountWithDescendants = 0 ;
nCountWithDescendants = 0 ;
nSizeWithDescendants = nTxSize ;
nSizeWithDescendants = nTxSize ;
nFeesWithDescendants = nFee ;
nMod FeesWithDescendants = GetModifiedFee ( ) ;
}
}
void CTxMemPoolEntry : : UpdateState ( int64_t modifySize , CAmount modifyFee , int64_t modifyCount )
void CTxMemPoolEntry : : UpdateState ( int64_t modifySize , CAmount modifyFee , int64_t modifyCount )
@ -312,8 +313,7 @@ void CTxMemPoolEntry::UpdateState(int64_t modifySize, CAmount modifyFee, int64_t
if ( ! IsDirty ( ) ) {
if ( ! IsDirty ( ) ) {
nSizeWithDescendants + = modifySize ;
nSizeWithDescendants + = modifySize ;
assert ( int64_t ( nSizeWithDescendants ) > 0 ) ;
assert ( int64_t ( nSizeWithDescendants ) > 0 ) ;
nFeesWithDescendants + = modifyFee ;
nModFeesWithDescendants + = modifyFee ;
assert ( nFeesWithDescendants > = 0 ) ;
nCountWithDescendants + = modifyCount ;
nCountWithDescendants + = modifyCount ;
assert ( int64_t ( nCountWithDescendants ) > 0 ) ;
assert ( int64_t ( nCountWithDescendants ) > 0 ) ;
}
}
@ -372,6 +372,17 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
indexed_transaction_set : : iterator newit = mapTx . insert ( entry ) . first ;
indexed_transaction_set : : iterator newit = mapTx . insert ( entry ) . first ;
mapLinks . insert ( make_pair ( newit , TxLinks ( ) ) ) ;
mapLinks . insert ( make_pair ( newit , TxLinks ( ) ) ) ;
// Update transaction for any feeDelta created by PrioritiseTransaction
// TODO: refactor so that the fee delta is calculated before inserting
// into mapTx.
std : : map < uint256 , std : : pair < double , CAmount > > : : const_iterator pos = mapDeltas . find ( hash ) ;
if ( pos ! = mapDeltas . end ( ) ) {
const std : : pair < double , CAmount > & deltas = pos - > second ;
if ( deltas . second ) {
mapTx . modify ( newit , update_fee_delta ( deltas . second ) ) ;
}
}
// Update cachedInnerUsage to include contained transaction's usage.
// Update cachedInnerUsage to include contained transaction's usage.
// (When we update the entry for in-mempool parents, memory usage will be
// (When we update the entry for in-mempool parents, memory usage will be
// further updated.)
// further updated.)
@ -399,15 +410,6 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
}
}
UpdateAncestorsOf ( true , newit , setAncestors ) ;
UpdateAncestorsOf ( true , newit , setAncestors ) ;
// Update transaction's score for any feeDelta created by PrioritiseTransaction
std : : map < uint256 , std : : pair < double , CAmount > > : : const_iterator pos = mapDeltas . find ( hash ) ;
if ( pos ! = mapDeltas . end ( ) ) {
const std : : pair < double , CAmount > & deltas = pos - > second ;
if ( deltas . second ) {
mapTx . modify ( newit , update_fee_delta ( deltas . second ) ) ;
}
}
nTransactionsUpdated + + ;
nTransactionsUpdated + + ;
totalTxSize + = entry . GetTxSize ( ) ;
totalTxSize + = entry . GetTxSize ( ) ;
minerPolicyEstimator - > processTransaction ( entry , fCurrentEstimate ) ;
minerPolicyEstimator - > processTransaction ( entry , fCurrentEstimate ) ;
@ -644,27 +646,24 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
CTxMemPool : : setEntries setChildrenCheck ;
CTxMemPool : : setEntries setChildrenCheck ;
std : : map < COutPoint , CInPoint > : : const_iterator iter = mapNextTx . lower_bound ( COutPoint ( it - > GetTx ( ) . GetHash ( ) , 0 ) ) ;
std : : map < COutPoint , CInPoint > : : const_iterator iter = mapNextTx . lower_bound ( COutPoint ( it - > GetTx ( ) . GetHash ( ) , 0 ) ) ;
int64_t childSizes = 0 ;
int64_t childSizes = 0 ;
CAmount childFees = 0 ;
CAmount childMod Fee = 0 ;
for ( ; iter ! = mapNextTx . end ( ) & & iter - > first . hash = = it - > GetTx ( ) . GetHash ( ) ; + + iter ) {
for ( ; iter ! = mapNextTx . end ( ) & & iter - > first . hash = = it - > GetTx ( ) . GetHash ( ) ; + + iter ) {
txiter childit = mapTx . find ( iter - > second . ptx - > GetHash ( ) ) ;
txiter childit = mapTx . find ( iter - > second . ptx - > GetHash ( ) ) ;
assert ( childit ! = mapTx . end ( ) ) ; // mapNextTx points to in-mempool transactions
assert ( childit ! = mapTx . end ( ) ) ; // mapNextTx points to in-mempool transactions
if ( setChildrenCheck . insert ( childit ) . second ) {
if ( setChildrenCheck . insert ( childit ) . second ) {
childSizes + = childit - > GetTxSize ( ) ;
childSizes + = childit - > GetTxSize ( ) ;
childFees + = childit - > GetFee ( ) ;
childMod Fee + = childit - > GetModified Fee ( ) ;
}
}
}
}
assert ( setChildrenCheck = = GetMemPoolChildren ( it ) ) ;
assert ( setChildrenCheck = = GetMemPoolChildren ( it ) ) ;
// Also check to make sure size/fees is greater than sum with immediate children.
// Also check to make sure size is greater than sum with immediate children.
// just a sanity check, not definitive that this calc is correct...
// just a sanity check, not definitive that this calc is correct...
// also check that the size is less than the size of the entire mempool.
if ( ! it - > IsDirty ( ) ) {
if ( ! it - > IsDirty ( ) ) {
assert ( it - > GetSizeWithDescendants ( ) > = childSizes + it - > GetTxSize ( ) ) ;
assert ( it - > GetSizeWithDescendants ( ) > = childSizes + it - > GetTxSize ( ) ) ;
assert ( it - > GetFeesWithDescendants ( ) > = childFees + it - > GetFee ( ) ) ;
} else {
} else {
assert ( it - > GetSizeWithDescendants ( ) = = it - > GetTxSize ( ) ) ;
assert ( it - > GetSizeWithDescendants ( ) = = it - > GetTxSize ( ) ) ;
assert ( it - > GetFeesWithDescendants ( ) = = it - > GetFee ( ) ) ;
assert ( it - > GetMod FeesWithDescendants ( ) = = it - > GetModified Fee ( ) ) ;
}
}
assert ( it - > GetFeesWithDescendants ( ) > = 0 ) ;
if ( fDependsWait )
if ( fDependsWait )
waitingOnDependants . push_back ( & ( * it ) ) ;
waitingOnDependants . push_back ( & ( * it ) ) ;
@ -788,6 +787,14 @@ void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash,
txiter it = mapTx . find ( hash ) ;
txiter it = mapTx . find ( hash ) ;
if ( it ! = mapTx . end ( ) ) {
if ( it ! = mapTx . end ( ) ) {
mapTx . modify ( it , update_fee_delta ( deltas . second ) ) ;
mapTx . modify ( it , update_fee_delta ( deltas . second ) ) ;
// Now update all ancestors' modified fees with descendants
setEntries setAncestors ;
uint64_t nNoLimit = std : : numeric_limits < uint64_t > : : max ( ) ;
std : : string dummy ;
CalculateMemPoolAncestors ( * it , setAncestors , nNoLimit , nNoLimit , nNoLimit , nNoLimit , dummy , false ) ;
BOOST_FOREACH ( txiter ancestorIt , setAncestors ) {
mapTx . modify ( ancestorIt , update_descendant_state ( 0 , nFeeDelta , 0 ) ) ;
}
}
}
}
}
LogPrintf ( " PrioritiseTransaction: %s priority += %f, fee += %d \n " , strHash , dPriorityDelta , FormatMoney ( nFeeDelta ) ) ;
LogPrintf ( " PrioritiseTransaction: %s priority += %f, fee += %d \n " , strHash , dPriorityDelta , FormatMoney ( nFeeDelta ) ) ;
@ -956,7 +963,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<uint256>* pvNoSpendsRe
// "minimum reasonable fee rate" (ie some value under which we consider txn
// "minimum reasonable fee rate" (ie some value under which we consider txn
// to have 0 fee). This way, we don't allow txn to enter mempool with feerate
// to have 0 fee). This way, we don't allow txn to enter mempool with feerate
// equal to txn which were removed with no block in between.
// equal to txn which were removed with no block in between.
CFeeRate removed ( it - > GetFeesWithDescendants ( ) , it - > GetSizeWithDescendants ( ) ) ;
CFeeRate removed ( it - > GetMod FeesWithDescendants ( ) , it - > GetSizeWithDescendants ( ) ) ;
removed + = minReasonableRelayFee ;
removed + = minReasonableRelayFee ;
trackPackageRemoved ( removed ) ;
trackPackageRemoved ( removed ) ;
maxFeeRateRemoved = std : : max ( maxFeeRateRemoved , removed ) ;
maxFeeRateRemoved = std : : max ( maxFeeRateRemoved , removed ) ;