diff options
Diffstat (limited to 'src/validation.cpp')
| -rw-r--r-- | src/validation.cpp | 105 |
1 files changed, 90 insertions, 15 deletions
diff --git a/src/validation.cpp b/src/validation.cpp index bc14c1d8c..3faa1bf00 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -185,7 +185,8 @@ enum FlushStateMode { }; // See definition for documentation -bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode); +bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int nManualPruneHeight=0); +void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight); bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) { @@ -525,6 +526,18 @@ std::string FormatStateMessage(const CValidationState &state) state.GetRejectCode()); } +static bool IsCurrentForFeeEstimation() +{ + AssertLockHeld(cs_main); + if (IsInitialBlockDownload()) + return false; + if (chainActive.Tip()->GetBlockTime() < (GetTime() - MAX_FEE_ESTIMATION_TIP_AGE)) + return false; + if (chainActive.Height() < pindexBestHeader->nHeight - 1) + return false; + return true; +} + bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree, bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, const CAmount& nAbsurdFee, std::vector<uint256>& vHashTxnToUncache) @@ -692,7 +705,8 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C } } - CTxMemPoolEntry entry(ptx, nFees, nAcceptTime, dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOpsCost, lp); + CTxMemPoolEntry entry(ptx, nFees, nAcceptTime, dPriority, chainActive.Height(), + inChainInputValue, fSpendsCoinbase, nSigOpsCost, lp); unsigned int nSize = entry.GetTxSize(); // Check that the transaction doesn't have an excessive number of @@ -940,8 +954,13 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C } pool.RemoveStaged(allConflicting, false); + // This transaction should only count for fee estimation if + // the node is not behind and it is not dependent on any other + // transactions in the mempool + bool validForFeeEstimation = IsCurrentForFeeEstimation() && pool.HasNoInputsOf(tx); + // Store transaction in memory - pool.addUnchecked(hash, entry, setAncestors, !IsInitialBlockDownload()); + pool.addUnchecked(hash, entry, setAncestors, validForFeeEstimation); // trim mempool and check if tx was trimmed if (!fOverrideMempoolLimit) { @@ -1499,7 +1518,7 @@ bool AbortNode(CValidationState& state, const std::string& strMessage, const std * @param out The out point that corresponds to the tx input. * @return True on success. */ -static bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint& out) +bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint& out) { bool fClean = true; @@ -1916,7 +1935,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin * if they're too large, if it's been a while since the last write, * or always and in all cases if we're in prune mode and are deleting files. */ -bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { +bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int nManualPruneHeight) { + int64_t nMempoolUsage = mempool.DynamicMemoryUsage(); const CChainParams& chainparams = Params(); LOCK2(cs_main, cs_LastBlockFile); static int64_t nLastWrite = 0; @@ -1925,9 +1945,13 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { std::set<int> setFilesToPrune; bool fFlushForPrune = false; try { - if (fPruneMode && fCheckForPruning && !fReindex) { - FindFilesToPrune(setFilesToPrune, chainparams.PruneAfterHeight()); - fCheckForPruning = false; + if (fPruneMode && (fCheckForPruning || nManualPruneHeight > 0) && !fReindex) { + if (nManualPruneHeight > 0) { + FindFilesToPruneManual(setFilesToPrune, nManualPruneHeight); + } else { + FindFilesToPrune(setFilesToPrune, chainparams.PruneAfterHeight()); + fCheckForPruning = false; + } if (!setFilesToPrune.empty()) { fFlushForPrune = true; if (!fHavePruned) { @@ -1947,11 +1971,13 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { if (nLastSetChain == 0) { nLastSetChain = nNow; } - size_t cacheSize = pcoinsTip->DynamicMemoryUsage(); - // The cache is large and close to the limit, but we have time now (not in the middle of a block processing). - bool fCacheLarge = mode == FLUSH_STATE_PERIODIC && cacheSize * (10.0/9) > nCoinCacheUsage; + int64_t nMempoolSizeMax = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; + int64_t cacheSize = pcoinsTip->DynamicMemoryUsage(); + int64_t nTotalSpace = nCoinCacheUsage + std::max<int64_t>(nMempoolSizeMax - nMempoolUsage, 0); + // The cache is large and we're within 10% and 100 MiB of the limit, but we have time now (not in the middle of a block processing). + bool fCacheLarge = mode == FLUSH_STATE_PERIODIC && cacheSize > std::max((9 * nTotalSpace) / 10, nTotalSpace - 100 * 1024 * 1024); // The cache is over the limit, we have to write now. - bool fCacheCritical = mode == FLUSH_STATE_IF_NEEDED && cacheSize > nCoinCacheUsage; + bool fCacheCritical = mode == FLUSH_STATE_IF_NEEDED && cacheSize > nTotalSpace; // It's been a while since we wrote the block index to disk. Do this frequently, so we don't need to redownload after a crash. bool fPeriodicWrite = mode == FLUSH_STATE_PERIODIC && nNow > nLastWrite + (int64_t)DATABASE_WRITE_INTERVAL * 1000000; // It's been very long since we flushed the cache. Do this infrequently, to optimize cache usage. @@ -2080,7 +2106,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion, log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), - Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); + GuessVerificationProgress(chainParams.TxData(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); if (!warningMessages.empty()) LogPrintf(" warning='%s'", boost::algorithm::join(warningMessages, ", ")); LogPrintf("\n"); @@ -2203,7 +2229,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4; LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); // Remove conflicting transactions from the mempool.; - mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight, !IsInitialBlockDownload()); + mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight); // Update chainActive & related variables. UpdateTip(pindexNew, chainparams); @@ -3226,6 +3252,35 @@ void UnlinkPrunedFiles(std::set<int>& setFilesToPrune) } } +/* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */ +void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight) +{ + assert(fPruneMode && nManualPruneHeight > 0); + + LOCK2(cs_main, cs_LastBlockFile); + if (chainActive.Tip() == NULL) + return; + + // last block to prune is the lesser of (user-specified height, MIN_BLOCKS_TO_KEEP from the tip) + unsigned int nLastBlockWeCanPrune = min((unsigned)nManualPruneHeight, chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP); + int count=0; + for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) { + if (vinfoBlockFile[fileNumber].nSize == 0 || vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune) + continue; + PruneOneBlockFile(fileNumber); + setFilesToPrune.insert(fileNumber); + count++; + } + LogPrintf("Prune (Manual): prune_height=%d removed %d blk/rev pairs\n", nLastBlockWeCanPrune, count); +} + +/* This function is called from the RPC code for pruneblockchain */ +void PruneBlockFilesManual(int nManualPruneHeight) +{ + CValidationState state; + FlushStateToDisk(state, FLUSH_STATE_NONE, nManualPruneHeight); +} + /* Calculate the block/rev files that should be deleted to remain under target*/ void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight) { @@ -3445,7 +3500,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) LogPrintf("%s: hashBestChain=%s height=%d date=%s progress=%f\n", __func__, chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), - Checkpoints::GuessVerificationProgress(chainparams.Checkpoints(), chainActive.Tip())); + GuessVerificationProgress(chainparams.TxData(), chainActive.Tip())); return true; } @@ -4078,6 +4133,8 @@ bool LoadMempool(void) } else { ++skipped; } + if (ShutdownRequested()) + return false; } std::map<uint256, CAmount> mapDeltas; file >> mapDeltas; @@ -4141,6 +4198,24 @@ void DumpMempool(void) } } +//! Guess how far we are in the verification process at the given block index +double GuessVerificationProgress(const ChainTxData& data, CBlockIndex *pindex) { + if (pindex == NULL) + return 0.0; + + int64_t nNow = time(NULL); + + double fTxTotal; + + if (pindex->nChainTx <= data.nTxCount) { + fTxTotal = data.nTxCount + (nNow - data.nTime) * data.dTxRate; + } else { + fTxTotal = pindex->nChainTx + (nNow - pindex->GetBlockTime()) * data.dTxRate; + } + + return pindex->nChainTx / fTxTotal; +} + class CMainCleanup { public: |