aboutsummaryrefslogtreecommitdiff
path: root/src/txmempool.cpp
diff options
context:
space:
mode:
authorSuhas Daftuar <sdaftuar@gmail.com>2015-11-19 11:18:28 -0500
committerWladimir J. van der Laan <laanwj@gmail.com>2015-12-21 17:19:53 +0100
commit12c469b236aa9b31b3744e5c529b9236dda27b27 (patch)
tree77569facae72f92502391b0cafc89c3f50f4c470 /src/txmempool.cpp
parenteccd67106d7ebfcb1d0913c2036848f57ba344fb (diff)
downloadbitcoin-12c469b236aa9b31b3744e5c529b9236dda27b27.tar.xz
[Mempool] Fix mempool limiting and replace-by-fee for PrioritiseTransaction
1) Fix mempool limiting for PrioritiseTransaction Redo the feerate index to be based on mining score, rather than fee. Update mempool_packages.py to test prioritisetransaction's effect on package scores. 2) Update replace-by-fee logic to use fee deltas 3) Use fee deltas for determining mempool acceptance 4) Remove GetMinRelayFee One test in AcceptToMemoryPool was to compare a transaction's fee agains the value returned by GetMinRelayFee. This value was zero for all small transactions. For larger transactions (between DEFAULT_BLOCK_PRIORITY_SIZE and MAX_STANDARD_TX_SIZE), this function was preventing low fee transactions from ever being accepted. With this function removed, we will now allow transactions in that range with fees (including modifications via PrioritiseTransaction) below the minRelayTxFee, provided that they have sufficient priority. Github-Pull: #7062 Rebased-From: eb306664e786ae43d539fde66f0fbe2a3e89d910 9ef2a25603c9ec4e44c4f45c6a5d4e4386ec86d3 27fae3484cdb21b0d24face833b966fce5926be5 901b01d674031f9aca717deeb372bafa160a24af
Diffstat (limited to 'src/txmempool.cpp')
-rw-r--r--src/txmempool.cpp53
1 files changed, 30 insertions, 23 deletions
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index fea5da8029..c72a1e8c19 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -33,7 +33,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
nCountWithDescendants = 1;
nSizeWithDescendants = nTxSize;
- nFeesWithDescendants = nFee;
+ nModFeesWithDescendants = nFee;
CAmount nValueIn = tx.GetValueOut()+nFee;
assert(inChainInputValue <= nValueIn);
@@ -57,6 +57,7 @@ CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
void CTxMemPoolEntry::UpdateFeeDelta(int64_t newFeeDelta)
{
+ nModFeesWithDescendants += newFeeDelta - feeDelta;
feeDelta = newFeeDelta;
}
@@ -114,7 +115,7 @@ bool CTxMemPool::UpdateForDescendants(txiter updateIt, int maxDescendantsToVisit
BOOST_FOREACH(txiter cit, setAllDescendants) {
if (!setExclude.count(cit->GetTx().GetHash())) {
modifySize += cit->GetTxSize();
- modifyFee += cit->GetFee();
+ modifyFee += cit->GetModifiedFee();
modifyCount++;
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 updateSize = updateCount * it->GetTxSize();
- const CAmount updateFee = updateCount * it->GetFee();
+ const CAmount updateFee = updateCount * it->GetModifiedFee();
BOOST_FOREACH(txiter ancestorIt, setAncestors) {
mapTx.modify(ancestorIt, update_descendant_state(updateSize, updateFee, updateCount));
}
@@ -304,7 +305,7 @@ void CTxMemPoolEntry::SetDirty()
{
nCountWithDescendants = 0;
nSizeWithDescendants = nTxSize;
- nFeesWithDescendants = nFee;
+ nModFeesWithDescendants = GetModifiedFee();
}
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()) {
nSizeWithDescendants += modifySize;
assert(int64_t(nSizeWithDescendants) > 0);
- nFeesWithDescendants += modifyFee;
- assert(nFeesWithDescendants >= 0);
+ nModFeesWithDescendants += modifyFee;
nCountWithDescendants += modifyCount;
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;
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.
// (When we update the entry for in-mempool parents, memory usage will be
// further updated.)
@@ -399,15 +410,6 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
}
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++;
totalTxSize += entry.GetTxSize();
minerPolicyEstimator->processTransaction(entry, fCurrentEstimate);
@@ -644,27 +646,24 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
CTxMemPool::setEntries setChildrenCheck;
std::map<COutPoint, CInPoint>::const_iterator iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0));
int64_t childSizes = 0;
- CAmount childFees = 0;
+ CAmount childModFee = 0;
for (; iter != mapNextTx.end() && iter->first.hash == it->GetTx().GetHash(); ++iter) {
txiter childit = mapTx.find(iter->second.ptx->GetHash());
assert(childit != mapTx.end()); // mapNextTx points to in-mempool transactions
if (setChildrenCheck.insert(childit).second) {
childSizes += childit->GetTxSize();
- childFees += childit->GetFee();
+ childModFee += childit->GetModifiedFee();
}
}
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...
- // also check that the size is less than the size of the entire mempool.
if (!it->IsDirty()) {
assert(it->GetSizeWithDescendants() >= childSizes + it->GetTxSize());
- assert(it->GetFeesWithDescendants() >= childFees + it->GetFee());
} else {
assert(it->GetSizeWithDescendants() == it->GetTxSize());
- assert(it->GetFeesWithDescendants() == it->GetFee());
+ assert(it->GetModFeesWithDescendants() == it->GetModifiedFee());
}
- assert(it->GetFeesWithDescendants() >= 0);
if (fDependsWait)
waitingOnDependants.push_back(&(*it));
@@ -788,6 +787,14 @@ void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash,
txiter it = mapTx.find(hash);
if (it != mapTx.end()) {
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));
@@ -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
// 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.
- CFeeRate removed(it->GetFeesWithDescendants(), it->GetSizeWithDescendants());
+ CFeeRate removed(it->GetModFeesWithDescendants(), it->GetSizeWithDescendants());
removed += minReasonableRelayFee;
trackPackageRemoved(removed);
maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);