aboutsummaryrefslogtreecommitdiff
path: root/src/miner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/miner.cpp')
-rw-r--r--src/miner.cpp44
1 files changed, 37 insertions, 7 deletions
diff --git a/src/miner.cpp b/src/miner.cpp
index 4fd99c5282..69a89bd617 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -126,6 +126,8 @@ void BlockAssembler::resetBlock()
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn, bool fMineWitnessTx)
{
+ int64_t nTimeStart = GetTimeMicros();
+
resetBlock();
pblocktemplate.reset(new CBlockTemplate());
@@ -164,7 +166,11 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
// transaction (which in most cases can be a no-op).
fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()) && fMineWitnessTx;
- addPackageTxs();
+ int nPackagesSelected = 0;
+ int nDescendantsUpdated = 0;
+ addPackageTxs(nPackagesSelected, nDescendantsUpdated);
+
+ int64_t nTime1 = GetTimeMicros();
nLastBlockTx = nBlockTx;
nLastBlockSize = nBlockSize;
@@ -196,6 +202,9 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
}
+ int64_t nTime2 = GetTimeMicros();
+
+ LogPrint(BCLog::BENCH, "CreateNewBlock() packages: %.2fms (%d packages, %d updated descendants), validity: %.2fms (total %.2fms)\n", 0.001 * (nTime1 - nTimeStart), nPackagesSelected, nDescendantsUpdated, 0.001 * (nTime2 - nTime1), 0.001 * (nTime2 - nTimeStart));
return std::move(pblocktemplate);
}
@@ -269,9 +278,10 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
}
}
-void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded,
+int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded,
indexed_modified_transaction_set &mapModifiedTx)
{
+ int nDescendantsUpdated = 0;
BOOST_FOREACH(const CTxMemPool::txiter it, alreadyAdded) {
CTxMemPool::setEntries descendants;
mempool.CalculateDescendants(it, descendants);
@@ -279,6 +289,7 @@ void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alread
BOOST_FOREACH(CTxMemPool::txiter desc, descendants) {
if (alreadyAdded.count(desc))
continue;
+ ++nDescendantsUpdated;
modtxiter mit = mapModifiedTx.find(desc);
if (mit == mapModifiedTx.end()) {
CTxMemPoolModifiedEntry modEntry(desc);
@@ -291,6 +302,7 @@ void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alread
}
}
}
+ return nDescendantsUpdated;
}
// Skip entries in mapTx that are already in a block or are present
@@ -305,9 +317,7 @@ void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alread
bool BlockAssembler::SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx)
{
assert (it != mempool.mapTx.end());
- if (mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it))
- return true;
- return false;
+ return mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it);
}
void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, std::vector<CTxMemPool::txiter>& sortedEntries)
@@ -331,7 +341,7 @@ void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, CTxMemP
// Each time through the loop, we compare the best transaction in
// mapModifiedTxs with the next transaction in the mempool to decide what
// transaction package to work on next.
-void BlockAssembler::addPackageTxs()
+void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated)
{
// mapModifiedTx will store sorted packages after they are modified
// because some of their txs are already in the block
@@ -345,6 +355,13 @@ void BlockAssembler::addPackageTxs()
CTxMemPool::indexed_transaction_set::index<ancestor_score>::type::iterator mi = mempool.mapTx.get<ancestor_score>().begin();
CTxMemPool::txiter iter;
+
+ // Limit the number of attempts to add transactions to the block when it is
+ // close to full; this is just a simple heuristic to finish quickly if the
+ // mempool has a lot of entries.
+ const int64_t MAX_CONSECUTIVE_FAILURES = 1000;
+ int64_t nConsecutiveFailed = 0;
+
while (mi != mempool.mapTx.get<ancestor_score>().end() || !mapModifiedTx.empty())
{
// First try to find a new transaction in mapTx to evaluate.
@@ -406,6 +423,14 @@ void BlockAssembler::addPackageTxs()
mapModifiedTx.get<ancestor_score>().erase(modit);
failedTx.insert(iter);
}
+
+ ++nConsecutiveFailed;
+
+ if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight >
+ nBlockMaxWeight - 4000) {
+ // Give up if we're close to full and haven't succeeded in a while
+ break;
+ }
continue;
}
@@ -426,6 +451,9 @@ void BlockAssembler::addPackageTxs()
continue;
}
+ // This transaction will make it in; reset the failed counter.
+ nConsecutiveFailed = 0;
+
// Package can be added. Sort the entries in a valid order.
std::vector<CTxMemPool::txiter> sortedEntries;
SortForBlock(ancestors, iter, sortedEntries);
@@ -436,8 +464,10 @@ void BlockAssembler::addPackageTxs()
mapModifiedTx.erase(sortedEntries[i]);
}
+ ++nPackagesSelected;
+
// Update transactions that depend on each of these
- UpdatePackagesForAdded(ancestors, mapModifiedTx);
+ nDescendantsUpdated += UpdatePackagesForAdded(ancestors, mapModifiedTx);
}
}