Move orphan processing to ActivateBestChain
This further decouples "main" and "net" processing logic by moving orphan processing out of the chain-connecting cs_main lock and into its own cs_main lock, beside all of the other chain callbacks. Once further decoupling of net and main processing logic occurs, orphan handing should move to its own lock, out of cs_main. Note that this will introduce a race if there are any cases where we assume the orphan map to be consistent with the current chain tip, however I am confident there is no such case (ATMP will fail without DoS score in all such cases).
This commit is contained in:
parent
9346f84299
commit
ec4525ccc1
1 changed files with 27 additions and 20 deletions
47
src/main.cpp
47
src/main.cpp
|
@ -2461,7 +2461,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
|
|
||||||
CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
|
CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
|
||||||
|
|
||||||
std::vector<uint256> vOrphanErase;
|
|
||||||
std::vector<int> prevheights;
|
std::vector<int> prevheights;
|
||||||
CAmount nFees = 0;
|
CAmount nFees = 0;
|
||||||
int nInputs = 0;
|
int nInputs = 0;
|
||||||
|
@ -2492,17 +2491,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
prevheights[j] = view.AccessCoins(tx.vin[j].prevout.hash)->nHeight;
|
prevheights[j] = view.AccessCoins(tx.vin[j].prevout.hash)->nHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Which orphan pool entries must we evict?
|
|
||||||
for (size_t j = 0; j < tx.vin.size(); j++) {
|
|
||||||
auto itByPrev = mapOrphanTransactionsByPrev.find(tx.vin[j].prevout);
|
|
||||||
if (itByPrev == mapOrphanTransactionsByPrev.end()) continue;
|
|
||||||
for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) {
|
|
||||||
const CTransaction& orphanTx = (*mi)->second.tx;
|
|
||||||
const uint256& orphanHash = orphanTx.GetHash();
|
|
||||||
vOrphanErase.push_back(orphanHash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SequenceLocks(tx, nLockTimeFlags, &prevheights, *pindex)) {
|
if (!SequenceLocks(tx, nLockTimeFlags, &prevheights, *pindex)) {
|
||||||
return state.DoS(100, error("%s: contains a non-BIP68-final transaction", __func__),
|
return state.DoS(100, error("%s: contains a non-BIP68-final transaction", __func__),
|
||||||
REJECT_INVALID, "bad-txns-nonfinal");
|
REJECT_INVALID, "bad-txns-nonfinal");
|
||||||
|
@ -2592,14 +2580,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
GetMainSignals().UpdatedTransaction(hashPrevBestCoinBase);
|
GetMainSignals().UpdatedTransaction(hashPrevBestCoinBase);
|
||||||
hashPrevBestCoinBase = block.vtx[0].GetHash();
|
hashPrevBestCoinBase = block.vtx[0].GetHash();
|
||||||
|
|
||||||
// Erase orphan transactions include or precluded by this block
|
|
||||||
if (vOrphanErase.size()) {
|
|
||||||
int nErased = 0;
|
|
||||||
BOOST_FOREACH(uint256 &orphanHash, vOrphanErase) {
|
|
||||||
nErased += EraseOrphanTx(orphanHash);
|
|
||||||
}
|
|
||||||
LogPrint("mempool", "Erased %d orphan tx included or conflicted by block\n", nErased);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t nTime6 = GetTimeMicros(); nTimeCallbacks += nTime6 - nTime5;
|
int64_t nTime6 = GetTimeMicros(); nTimeCallbacks += nTime6 - nTime5;
|
||||||
LogPrint("bench", " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime6 - nTime5), nTimeCallbacks * 0.000001);
|
LogPrint("bench", " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime6 - nTime5), nTimeCallbacks * 0.000001);
|
||||||
|
@ -3105,6 +3085,33 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
|
||||||
}
|
}
|
||||||
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
|
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
|
||||||
|
|
||||||
|
// Remove orphan transactions with cs_main
|
||||||
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
|
std::vector<uint256> vOrphanErase;
|
||||||
|
for(unsigned int i = 0; i < txChanged.size(); i++) {
|
||||||
|
const CTransaction& tx = std::get<0>(txChanged[i]);
|
||||||
|
// Which orphan pool entries must we evict?
|
||||||
|
for (size_t j = 0; j < tx.vin.size(); j++) {
|
||||||
|
auto itByPrev = mapOrphanTransactionsByPrev.find(tx.vin[j].prevout);
|
||||||
|
if (itByPrev == mapOrphanTransactionsByPrev.end()) continue;
|
||||||
|
for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) {
|
||||||
|
const CTransaction& orphanTx = (*mi)->second.tx;
|
||||||
|
const uint256& orphanHash = orphanTx.GetHash();
|
||||||
|
vOrphanErase.push_back(orphanHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Erase orphan transactions include or precluded by this block
|
||||||
|
if (vOrphanErase.size()) {
|
||||||
|
int nErased = 0;
|
||||||
|
BOOST_FOREACH(uint256 &orphanHash, vOrphanErase) {
|
||||||
|
nErased += EraseOrphanTx(orphanHash);
|
||||||
|
}
|
||||||
|
LogPrint("mempool", "Erased %d orphan tx included or conflicted by block\n", nErased);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Notifications/callbacks that can run without cs_main
|
// Notifications/callbacks that can run without cs_main
|
||||||
|
|
||||||
// throw all transactions though the signal-interface
|
// throw all transactions though the signal-interface
|
||||||
|
|
Loading…
Reference in a new issue