Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 680 Lines • ▼ Show 20 Lines | for (const CTxIn &txin : tx.vin) { | ||||
MANDATORY_SCRIPT_VERIFY_FLAGS | extraFlags, true, | MANDATORY_SCRIPT_VERIFY_FLAGS | extraFlags, true, | ||||
false, txdata)) { | false, txdata)) { | ||||
return error( | return error( | ||||
"%s: ConnectInputs failed against MANDATORY but not " | "%s: ConnectInputs failed against MANDATORY but not " | ||||
"STANDARD flags due to promiscuous mempool %s, %s", | "STANDARD flags due to promiscuous mempool %s, %s", | ||||
__func__, txid.ToString(), FormatStateMessage(state)); | __func__, txid.ToString(), FormatStateMessage(state)); | ||||
} | } | ||||
LogPrintf("Warning: -promiscuousmempool flags set to not include " | LogPrint(BCLog::MEMPOOL, | ||||
"Warning: -promiscuousmempool flags set to not include " | |||||
"currently enforced soft forks, this may break mining or " | "currently enforced soft forks, this may break mining or " | ||||
"otherwise cause instability!\n"); | "otherwise cause instability!\n"); | ||||
} | } | ||||
// This transaction should only count for fee estimation if | // This transaction should only count for fee estimation if | ||||
// the node is not behind and it is not dependent on any other | // the node is not behind and it is not dependent on any other | ||||
// transactions in the mempool. | // transactions in the mempool. | ||||
bool validForFeeEstimation = | bool validForFeeEstimation = | ||||
IsCurrentForFeeEstimation() && pool.HasNoInputsOf(tx); | IsCurrentForFeeEstimation() && pool.HasNoInputsOf(tx); | ||||
▲ Show 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | if (chainActive.Tip() == nullptr) { | ||||
return true; | return true; | ||||
} | } | ||||
if (chainActive.Tip()->nChainWork < nMinimumChainWork) { | if (chainActive.Tip()->nChainWork < nMinimumChainWork) { | ||||
return true; | return true; | ||||
} | } | ||||
if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge)) { | if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge)) { | ||||
return true; | return true; | ||||
} | } | ||||
LogPrintf("Leaving InitialBlockDownload (latching to false)\n"); | LogPrint(BCLog::INIT, "Leaving InitialBlockDownload (latching to false)\n"); | ||||
latchToFalse.store(true, std::memory_order_relaxed); | latchToFalse.store(true, std::memory_order_relaxed); | ||||
return false; | return false; | ||||
} | } | ||||
CBlockIndex const *pindexBestForkTip = nullptr; | CBlockIndex const *pindexBestForkTip = nullptr; | ||||
CBlockIndex const *pindexBestForkBase = nullptr; | CBlockIndex const *pindexBestForkBase = nullptr; | ||||
static void AlertNotify(const std::string &strMessage) { | static void AlertNotify(const std::string &strMessage) { | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | if (pindexBestForkTip || | ||||
std::string warning = | std::string warning = | ||||
std::string("'Warning: Large-work fork detected, forking after " | std::string("'Warning: Large-work fork detected, forking after " | ||||
"block ") + | "block ") + | ||||
pindexBestForkBase->phashBlock->ToString() + std::string("'"); | pindexBestForkBase->phashBlock->ToString() + std::string("'"); | ||||
AlertNotify(warning); | AlertNotify(warning); | ||||
} | } | ||||
if (pindexBestForkTip && pindexBestForkBase) { | if (pindexBestForkTip && pindexBestForkBase) { | ||||
LogPrintf("%s: Warning: Large fork found\n forking the " | LogPrint(BCLog::BENCH, | ||||
"%s: Warning: Large fork found\n forking the " | |||||
"chain at height %d (%s)\n lasting to height %d " | "chain at height %d (%s)\n lasting to height %d " | ||||
"(%s).\nChain state database corruption likely.\n", | "(%s).\nChain state database corruption likely.\n", | ||||
__func__, pindexBestForkBase->nHeight, | __func__, pindexBestForkBase->nHeight, | ||||
pindexBestForkBase->phashBlock->ToString(), | pindexBestForkBase->phashBlock->ToString(), | ||||
pindexBestForkTip->nHeight, | pindexBestForkTip->nHeight, | ||||
pindexBestForkTip->phashBlock->ToString()); | pindexBestForkTip->phashBlock->ToString()); | ||||
SetfLargeWorkForkFound(true); | SetfLargeWorkForkFound(true); | ||||
} else { | } else { | ||||
LogPrintf("%s: Warning: Found invalid chain at least ~6 blocks " | LogPrint(BCLog::BENCH, | ||||
"%s: Warning: Found invalid chain at least ~6 blocks " | |||||
"longer than our best chain.\nChain state database " | "longer than our best chain.\nChain state database " | ||||
"corruption likely.\n", | "corruption likely.\n", | ||||
__func__); | __func__); | ||||
SetfLargeWorkInvalidChainFound(true); | SetfLargeWorkInvalidChainFound(true); | ||||
} | } | ||||
} else { | } else { | ||||
SetfLargeWorkForkFound(false); | SetfLargeWorkForkFound(false); | ||||
SetfLargeWorkInvalidChainFound(false); | SetfLargeWorkInvalidChainFound(false); | ||||
} | } | ||||
} | } | ||||
Show All 25 Lines | |||||
} | } | ||||
static void InvalidChainFound(CBlockIndex *pindexNew) { | static void InvalidChainFound(CBlockIndex *pindexNew) { | ||||
if (!pindexBestInvalid || | if (!pindexBestInvalid || | ||||
pindexNew->nChainWork > pindexBestInvalid->nChainWork) { | pindexNew->nChainWork > pindexBestInvalid->nChainWork) { | ||||
pindexBestInvalid = pindexNew; | pindexBestInvalid = pindexNew; | ||||
} | } | ||||
LogPrintf( | LogPrint(BCLog::BENCH, | ||||
"%s: invalid block=%s height=%d log2_work=%.8g date=%s\n", __func__, | "%s: invalid block=%s height=%d log2_work=%.8g date=%s\n", | ||||
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, | __func__, pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, | ||||
log(pindexNew->nChainWork.getdouble()) / log(2.0), | log(pindexNew->nChainWork.getdouble()) / log(2.0), | ||||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexNew->GetBlockTime())); | DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexNew->GetBlockTime())); | ||||
CBlockIndex *tip = chainActive.Tip(); | CBlockIndex *tip = chainActive.Tip(); | ||||
assert(tip); | assert(tip); | ||||
LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", | LogPrint(BCLog::BENCH, | ||||
"%s: current best=%s height=%d log2_work=%.8g date=%s\n", | |||||
__func__, tip->GetBlockHash().ToString(), chainActive.Height(), | __func__, tip->GetBlockHash().ToString(), chainActive.Height(), | ||||
log(tip->nChainWork.getdouble()) / log(2.0), | log(tip->nChainWork.getdouble()) / log(2.0), | ||||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", tip->GetBlockTime())); | DateTimeStrFormat("%Y-%m-%d %H:%M:%S", tip->GetBlockTime())); | ||||
} | } | ||||
static void InvalidBlockFound(CBlockIndex *pindex, | static void InvalidBlockFound(CBlockIndex *pindex, | ||||
const CValidationState &state) { | const CValidationState &state) { | ||||
if (!state.CorruptionPossible()) { | if (!state.CorruptionPossible()) { | ||||
pindex->nStatus = pindex->nStatus.withFailed(); | pindex->nStatus = pindex->nStatus.withFailed(); | ||||
setDirtyBlockIndex.insert(pindex); | setDirtyBlockIndex.insert(pindex); | ||||
InvalidChainFound(pindex); | InvalidChainFound(pindex); | ||||
▲ Show 20 Lines • Show All 211 Lines • ▼ Show 20 Lines | bool UndoReadFromDisk(CBlockUndo &blockundo, const CDiskBlockPos &pos, | ||||
return true; | return true; | ||||
} | } | ||||
/** Abort with a message */ | /** Abort with a message */ | ||||
bool AbortNode(const std::string &strMessage, | bool AbortNode(const std::string &strMessage, | ||||
const std::string &userMessage = "") { | const std::string &userMessage = "") { | ||||
SetMiscWarning(strMessage); | SetMiscWarning(strMessage); | ||||
LogPrintf("*** %s\n", strMessage); | LogPrint(BCLog::BENCH, "*** %s\n", strMessage); | ||||
uiInterface.ThreadSafeMessageBox( | uiInterface.ThreadSafeMessageBox( | ||||
userMessage.empty() ? _("Error: A fatal internal error occurred, see " | userMessage.empty() ? _("Error: A fatal internal error occurred, see " | ||||
"debug.log for details") | "debug.log for details") | ||||
: userMessage, | : userMessage, | ||||
"", CClientUIInterface::MSG_ERROR); | "", CClientUIInterface::MSG_ERROR); | ||||
StartShutdown(); | StartShutdown(); | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 799 Lines • ▼ Show 20 Lines | if (!IsInitialBlockDownload()) { | ||||
// the user: | // the user: | ||||
SetMiscWarning(strWarning); | SetMiscWarning(strWarning); | ||||
if (!fWarned) { | if (!fWarned) { | ||||
AlertNotify(strWarning); | AlertNotify(strWarning); | ||||
fWarned = true; | fWarned = true; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu " | LogPrint(BCLog::BENCH, | ||||
"%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu " | |||||
"date='%s' progress=%f cache=%.1fMiB(%utxo)", | "date='%s' progress=%f cache=%.1fMiB(%utxo)", | ||||
__func__, chainActive.Tip()->GetBlockHash().ToString(), | __func__, chainActive.Tip()->GetBlockHash().ToString(), | ||||
chainActive.Height(), chainActive.Tip()->nVersion, | chainActive.Height(), chainActive.Tip()->nVersion, | ||||
log(chainActive.Tip()->nChainWork.getdouble()) / log(2.0), | log(chainActive.Tip()->nChainWork.getdouble()) / log(2.0), | ||||
(unsigned long)chainActive.Tip()->nChainTx, | (unsigned long)chainActive.Tip()->nChainTx, | ||||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", | DateTimeStrFormat("%Y-%m-%d %H:%M:%S", | ||||
chainActive.Tip()->GetBlockTime()), | chainActive.Tip()->GetBlockTime()), | ||||
GuessVerificationProgress(config.GetChainParams().TxData(), | GuessVerificationProgress(config.GetChainParams().TxData(), | ||||
chainActive.Tip()), | chainActive.Tip()), | ||||
pcoinsTip->DynamicMemoryUsage() * (1.0 / (1 << 20)), | pcoinsTip->DynamicMemoryUsage() * (1.0 / (1 << 20)), | ||||
pcoinsTip->GetCacheSize()); | pcoinsTip->GetCacheSize()); | ||||
if (!warningMessages.empty()) { | if (!warningMessages.empty()) { | ||||
LogPrintf(" warning='%s'", | LogPrint(BCLog::BENCH, " warning='%s'", | ||||
boost::algorithm::join(warningMessages, ", ")); | boost::algorithm::join(warningMessages, ", ")); | ||||
} | } | ||||
LogPrintf("\n"); | LogPrint(BCLog::BENCH, "\n"); | ||||
} | } | ||||
/** | /** | ||||
* Disconnect chainActive's tip. | * Disconnect chainActive's tip. | ||||
* After calling, the mempool will be in an inconsistent state, with | * After calling, the mempool will be in an inconsistent state, with | ||||
* transactions from disconnected blocks being added to disconnectpool. You | * transactions from disconnected blocks being added to disconnectpool. You | ||||
* should make the mempool consistent again by calling updateMempoolForReorg. | * should make the mempool consistent again by calling updateMempoolForReorg. | ||||
* with cs_main held. | * with cs_main held. | ||||
▲ Show 20 Lines • Show All 854 Lines • ▼ Show 20 Lines | if (!fKnown) { | ||||
} | } | ||||
} | } | ||||
pos.nFile = nFile; | pos.nFile = nFile; | ||||
pos.nPos = vinfoBlockFile[nFile].nSize; | pos.nPos = vinfoBlockFile[nFile].nSize; | ||||
} | } | ||||
if ((int)nFile != nLastBlockFile) { | if ((int)nFile != nLastBlockFile) { | ||||
if (!fKnown) { | if (!fKnown) { | ||||
LogPrintf("Leaving block file %i: %s\n", nLastBlockFile, | LogPrint(BCLog::BENCH, "Leaving block file %i: %s\n", | ||||
vinfoBlockFile[nLastBlockFile].ToString()); | nLastBlockFile, vinfoBlockFile[nLastBlockFile].ToString()); | ||||
} | } | ||||
FlushBlockFile(!fKnown); | FlushBlockFile(!fKnown); | ||||
nLastBlockFile = nFile; | nLastBlockFile = nFile; | ||||
} | } | ||||
vinfoBlockFile[nFile].AddBlock(nHeight, nTime); | vinfoBlockFile[nFile].AddBlock(nHeight, nTime); | ||||
if (fKnown) { | if (fKnown) { | ||||
vinfoBlockFile[nFile].nSize = | vinfoBlockFile[nFile].nSize = | ||||
Show All 11 Lines | if (!fKnown) { | ||||
if (nNewChunks > nOldChunks) { | if (nNewChunks > nOldChunks) { | ||||
if (fPruneMode) { | if (fPruneMode) { | ||||
fCheckForPruning = true; | fCheckForPruning = true; | ||||
} | } | ||||
if (CheckDiskSpace(nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos)) { | if (CheckDiskSpace(nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos)) { | ||||
FILE *file = OpenBlockFile(pos); | FILE *file = OpenBlockFile(pos); | ||||
if (file) { | if (file) { | ||||
LogPrintf( | LogPrint( | ||||
BCLog::BENCH, | |||||
"Pre-allocating up to position 0x%x in blk%05u.dat\n", | "Pre-allocating up to position 0x%x in blk%05u.dat\n", | ||||
nNewChunks * BLOCKFILE_CHUNK_SIZE, pos.nFile); | nNewChunks * BLOCKFILE_CHUNK_SIZE, pos.nFile); | ||||
AllocateFileRange(file, pos.nPos, | AllocateFileRange(file, pos.nPos, | ||||
nNewChunks * BLOCKFILE_CHUNK_SIZE - | nNewChunks * BLOCKFILE_CHUNK_SIZE - | ||||
pos.nPos); | pos.nPos); | ||||
fclose(file); | fclose(file); | ||||
} | } | ||||
} else { | } else { | ||||
Show All 24 Lines | static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, | ||||
if (nNewChunks > nOldChunks) { | if (nNewChunks > nOldChunks) { | ||||
if (fPruneMode) { | if (fPruneMode) { | ||||
fCheckForPruning = true; | fCheckForPruning = true; | ||||
} | } | ||||
if (CheckDiskSpace(nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos)) { | if (CheckDiskSpace(nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos)) { | ||||
FILE *file = OpenUndoFile(pos); | FILE *file = OpenUndoFile(pos); | ||||
if (file) { | if (file) { | ||||
LogPrintf("Pre-allocating up to position 0x%x in rev%05u.dat\n", | LogPrint(BCLog::BENCH, | ||||
"Pre-allocating up to position 0x%x in rev%05u.dat\n", | |||||
nNewChunks * UNDOFILE_CHUNK_SIZE, pos.nFile); | nNewChunks * UNDOFILE_CHUNK_SIZE, pos.nFile); | ||||
AllocateFileRange(file, pos.nPos, | AllocateFileRange(file, pos.nPos, | ||||
nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos); | nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos); | ||||
fclose(file); | fclose(file); | ||||
} | } | ||||
} else { | } else { | ||||
return state.Error("out of disk space"); | return state.Error("out of disk space"); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | static bool ContextualCheckBlockHeader(const Config &config, | ||||
int64_t nAdjustedTime) { | int64_t nAdjustedTime) { | ||||
const Consensus::Params &consensusParams = | const Consensus::Params &consensusParams = | ||||
config.GetChainParams().GetConsensus(); | config.GetChainParams().GetConsensus(); | ||||
const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1; | const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1; | ||||
// Check proof of work | // Check proof of work | ||||
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, config)) { | if (block.nBits != GetNextWorkRequired(pindexPrev, &block, config)) { | ||||
LogPrintf("bad bits after height: %d\n", pindexPrev->nHeight); | LogPrint(BCLog::BENCH, "bad bits after height: %d\n", | ||||
pindexPrev->nHeight); | |||||
return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, | return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, | ||||
"incorrect proof of work"); | "incorrect proof of work"); | ||||
} | } | ||||
// Check timestamp against prev | // Check timestamp against prev | ||||
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) { | if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) { | ||||
return state.Invalid(false, REJECT_INVALID, "time-too-old", | return state.Invalid(false, REJECT_INVALID, "time-too-old", | ||||
"block's timestamp is too early"); | "block's timestamp is too early"); | ||||
▲ Show 20 Lines • Show All 272 Lines • ▼ Show 20 Lines | static bool AcceptBlock(const Config &config, | ||||
int64_t newBlockTimeDiff = std::llabs(pindex->GetReceivedTimeDiff()); | int64_t newBlockTimeDiff = std::llabs(pindex->GetReceivedTimeDiff()); | ||||
int64_t chainTipTimeDiff = | int64_t chainTipTimeDiff = | ||||
chainActive.Tip() ? std::llabs(chainActive.Tip()->GetReceivedTimeDiff()) | chainActive.Tip() ? std::llabs(chainActive.Tip()->GetReceivedTimeDiff()) | ||||
: 0; | : 0; | ||||
bool isSameHeight = chainActive.Tip() && | bool isSameHeight = chainActive.Tip() && | ||||
(pindex->nChainWork == chainActive.Tip()->nChainWork); | (pindex->nChainWork == chainActive.Tip()->nChainWork); | ||||
if (isSameHeight) { | if (isSameHeight) { | ||||
LogPrintf("Chain tip timestamp-to-received-time difference: hash=%s, " | LogPrint(BCLog::BENCH, | ||||
"Chain tip timestamp-to-received-time difference: hash=%s, " | |||||
"diff=%d\n", | "diff=%d\n", | ||||
chainActive.Tip()->GetBlockHash().ToString(), | chainActive.Tip()->GetBlockHash().ToString(), | ||||
chainTipTimeDiff); | chainTipTimeDiff); | ||||
LogPrintf("New block timestamp-to-received-time difference: hash=%s, " | LogPrint(BCLog::BENCH, | ||||
"New block timestamp-to-received-time difference: hash=%s, " | |||||
"diff=%d\n", | "diff=%d\n", | ||||
pindex->GetBlockHash().ToString(), newBlockTimeDiff); | pindex->GetBlockHash().ToString(), newBlockTimeDiff); | ||||
} | } | ||||
bool fHasMoreWork = | bool fHasMoreWork = | ||||
(chainActive.Tip() ? pindex->nChainWork > chainActive.Tip()->nChainWork | (chainActive.Tip() ? pindex->nChainWork > chainActive.Tip()->nChainWork | ||||
: true); | : true); | ||||
// Blocks that are too out-of-order needlessly limit the effectiveness of | // Blocks that are too out-of-order needlessly limit the effectiveness of | ||||
// pruning, because pruning will not delete block files that contain any | // pruning, because pruning will not delete block files that contain any | ||||
▲ Show 20 Lines • Show All 238 Lines • ▼ Show 20 Lines | void PruneOneBlockFile(const int fileNumber) { | ||||
setDirtyFileInfo.insert(fileNumber); | setDirtyFileInfo.insert(fileNumber); | ||||
} | } | ||||
void UnlinkPrunedFiles(const std::set<int> &setFilesToPrune) { | void UnlinkPrunedFiles(const std::set<int> &setFilesToPrune) { | ||||
for (const int i : setFilesToPrune) { | for (const int i : setFilesToPrune) { | ||||
CDiskBlockPos pos(i, 0); | CDiskBlockPos pos(i, 0); | ||||
fs::remove(GetBlockPosFilename(pos, "blk")); | fs::remove(GetBlockPosFilename(pos, "blk")); | ||||
fs::remove(GetBlockPosFilename(pos, "rev")); | fs::remove(GetBlockPosFilename(pos, "rev")); | ||||
LogPrintf("Prune: %s deleted blk/rev (%05u)\n", __func__, i); | LogPrint(BCLog::PRUNE, "Prune: %s deleted blk/rev (%05u)\n", __func__, | ||||
i); | |||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Calculate the block/rev files to delete based on height specified by user | * Calculate the block/rev files to delete based on height specified by user | ||||
* with RPC command pruneblockchain | * with RPC command pruneblockchain | ||||
*/ | */ | ||||
static void FindFilesToPruneManual(std::set<int> &setFilesToPrune, | static void FindFilesToPruneManual(std::set<int> &setFilesToPrune, | ||||
Show All 15 Lines | for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) { | ||||
if (vinfoBlockFile[fileNumber].nSize == 0 || | if (vinfoBlockFile[fileNumber].nSize == 0 || | ||||
vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune) { | vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune) { | ||||
continue; | continue; | ||||
} | } | ||||
PruneOneBlockFile(fileNumber); | PruneOneBlockFile(fileNumber); | ||||
setFilesToPrune.insert(fileNumber); | setFilesToPrune.insert(fileNumber); | ||||
count++; | count++; | ||||
} | } | ||||
LogPrintf("Prune (Manual): prune_height=%d removed %d blk/rev pairs\n", | LogPrint(BCLog::PRUNE, | ||||
"Prune (Manual): prune_height=%d removed %d blk/rev pairs\n", | |||||
nLastBlockWeCanPrune, count); | nLastBlockWeCanPrune, count); | ||||
} | } | ||||
/* This function is called from the RPC code for pruneblockchain */ | /* This function is called from the RPC code for pruneblockchain */ | ||||
void PruneBlockFilesManual(int nManualPruneHeight) { | void PruneBlockFilesManual(int nManualPruneHeight) { | ||||
CValidationState state; | CValidationState state; | ||||
const CChainParams &chainparams = Params(); | const CChainParams &chainparams = Params(); | ||||
FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE, nManualPruneHeight); | FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE, nManualPruneHeight); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | static FILE *OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, | ||||
fs::path path = GetBlockPosFilename(pos, prefix); | fs::path path = GetBlockPosFilename(pos, prefix); | ||||
fs::create_directories(path.parent_path()); | fs::create_directories(path.parent_path()); | ||||
FILE *file = fsbridge::fopen(path, "rb+"); | FILE *file = fsbridge::fopen(path, "rb+"); | ||||
if (!file && !fReadOnly) { | if (!file && !fReadOnly) { | ||||
file = fsbridge::fopen(path, "wb+"); | file = fsbridge::fopen(path, "wb+"); | ||||
} | } | ||||
if (!file) { | if (!file) { | ||||
LogPrintf("Unable to open file %s\n", path.string()); | LogPrint(BCLog::BENCH, "Unable to open file %s\n", path.string()); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
if (pos.nPos) { | if (pos.nPos) { | ||||
if (fseek(file, pos.nPos, SEEK_SET)) { | if (fseek(file, pos.nPos, SEEK_SET)) { | ||||
LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, | LogPrint(BCLog::BENCH, "Unable to seek to position %u of %s\n", | ||||
path.string()); | pos.nPos, path.string()); | ||||
fclose(file); | fclose(file); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
return file; | return file; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | for (const std::pair<int, CBlockIndex *> &item : vSortedByHeight) { | ||||
CBlockIndexWorkComparator()(pindexBestHeader, pindex))) { | CBlockIndexWorkComparator()(pindexBestHeader, pindex))) { | ||||
pindexBestHeader = pindex; | pindexBestHeader = pindex; | ||||
} | } | ||||
} | } | ||||
// Load block file info | // Load block file info | ||||
pblocktree->ReadLastBlockFile(nLastBlockFile); | pblocktree->ReadLastBlockFile(nLastBlockFile); | ||||
vinfoBlockFile.resize(nLastBlockFile + 1); | vinfoBlockFile.resize(nLastBlockFile + 1); | ||||
LogPrintf("%s: last block file = %i\n", __func__, nLastBlockFile); | LogPrint(BCLog::BENCH, "%s: last block file = %i\n", __func__, | ||||
nLastBlockFile); | |||||
for (int nFile = 0; nFile <= nLastBlockFile; nFile++) { | for (int nFile = 0; nFile <= nLastBlockFile; nFile++) { | ||||
pblocktree->ReadBlockFileInfo(nFile, vinfoBlockFile[nFile]); | pblocktree->ReadBlockFileInfo(nFile, vinfoBlockFile[nFile]); | ||||
} | } | ||||
LogPrintf("%s: last block file info: %s\n", __func__, | LogPrint(BCLog::BENCH, "%s: last block file info: %s\n", __func__, | ||||
vinfoBlockFile[nLastBlockFile].ToString()); | vinfoBlockFile[nLastBlockFile].ToString()); | ||||
for (int nFile = nLastBlockFile + 1; true; nFile++) { | for (int nFile = nLastBlockFile + 1; true; nFile++) { | ||||
CBlockFileInfo info; | CBlockFileInfo info; | ||||
if (pblocktree->ReadBlockFileInfo(nFile, info)) { | if (pblocktree->ReadBlockFileInfo(nFile, info)) { | ||||
vinfoBlockFile.push_back(info); | vinfoBlockFile.push_back(info); | ||||
} else { | } else { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
// Check presence of blk files | // Check presence of blk files | ||||
LogPrintf("Checking all blk files are present...\n"); | LogPrint(BCLog::BENCH, "Checking all blk files are present...\n"); | ||||
std::set<int> setBlkDataFiles; | std::set<int> setBlkDataFiles; | ||||
for (const std::pair<uint256, CBlockIndex *> &item : mapBlockIndex) { | for (const std::pair<uint256, CBlockIndex *> &item : mapBlockIndex) { | ||||
CBlockIndex *pindex = item.second; | CBlockIndex *pindex = item.second; | ||||
if (pindex->nStatus.hasData()) { | if (pindex->nStatus.hasData()) { | ||||
setBlkDataFiles.insert(pindex->nFile); | setBlkDataFiles.insert(pindex->nFile); | ||||
} | } | ||||
} | } | ||||
for (const int i : setBlkDataFiles) { | for (const int i : setBlkDataFiles) { | ||||
CDiskBlockPos pos(i, 0); | CDiskBlockPos pos(i, 0); | ||||
if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION) | if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION) | ||||
.IsNull()) { | .IsNull()) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
// Check whether we have ever pruned block & undo files | // Check whether we have ever pruned block & undo files | ||||
pblocktree->ReadFlag("prunedblockfiles", fHavePruned); | pblocktree->ReadFlag("prunedblockfiles", fHavePruned); | ||||
if (fHavePruned) { | if (fHavePruned) { | ||||
LogPrintf( | LogPrint( | ||||
BCLog::PRUNE, | |||||
"LoadBlockIndexDB(): Block files have previously been pruned\n"); | "LoadBlockIndexDB(): Block files have previously been pruned\n"); | ||||
} | } | ||||
// Check whether we need to continue reindexing | // Check whether we need to continue reindexing | ||||
bool fReindexing = false; | bool fReindexing = false; | ||||
pblocktree->ReadReindexing(fReindexing); | pblocktree->ReadReindexing(fReindexing); | ||||
fReindex |= fReindexing; | fReindex |= fReindexing; | ||||
// Check whether we have a transaction index | // Check whether we have a transaction index | ||||
pblocktree->ReadFlag("txindex", fTxIndex); | pblocktree->ReadFlag("txindex", fTxIndex); | ||||
LogPrintf("%s: transaction index %s\n", __func__, | LogPrint(BCLog::BENCH, "%s: transaction index %s\n", __func__, | ||||
fTxIndex ? "enabled" : "disabled"); | fTxIndex ? "enabled" : "disabled"); | ||||
return true; | return true; | ||||
} | } | ||||
bool LoadChainTip(const Config &config) { | bool LoadChainTip(const Config &config) { | ||||
if (chainActive.Tip() && | if (chainActive.Tip() && | ||||
chainActive.Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) { | chainActive.Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) { | ||||
return true; | return true; | ||||
} | } | ||||
if (pcoinsTip->GetBestBlock().IsNull() && mapBlockIndex.size() == 1) { | if (pcoinsTip->GetBestBlock().IsNull() && mapBlockIndex.size() == 1) { | ||||
// In case we just added the genesis block, connect it now, so | // In case we just added the genesis block, connect it now, so | ||||
// that we always have a chainActive.Tip() when we return. | // that we always have a chainActive.Tip() when we return. | ||||
LogPrintf("%s: Connecting genesis block...\n", __func__); | LogPrint(BCLog::BENCH, "%s: Connecting genesis block...\n", __func__); | ||||
CValidationState state; | CValidationState state; | ||||
if (!ActivateBestChain(config, state)) { | if (!ActivateBestChain(config, state)) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
// Load pointer to end of best chain | // Load pointer to end of best chain | ||||
BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); | BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); | ||||
if (it == mapBlockIndex.end()) { | if (it == mapBlockIndex.end()) { | ||||
return false; | return false; | ||||
} | } | ||||
chainActive.SetTip(it->second); | chainActive.SetTip(it->second); | ||||
PruneBlockIndexCandidates(); | PruneBlockIndexCandidates(); | ||||
LogPrintf( | LogPrint( | ||||
BCLog::BENCH, | |||||
"Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n", | "Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n", | ||||
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), | chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), | ||||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", | DateTimeStrFormat("%Y-%m-%d %H:%M:%S", | ||||
chainActive.Tip()->GetBlockTime()), | chainActive.Tip()->GetBlockTime()), | ||||
GuessVerificationProgress(config.GetChainParams().TxData(), | GuessVerificationProgress(config.GetChainParams().TxData(), | ||||
chainActive.Tip())); | chainActive.Tip())); | ||||
return true; | return true; | ||||
} | } | ||||
Show All 19 Lines | if (nCheckDepth <= 0) { | ||||
nCheckDepth = 1000000000; | nCheckDepth = 1000000000; | ||||
} | } | ||||
if (nCheckDepth > chainActive.Height()) { | if (nCheckDepth > chainActive.Height()) { | ||||
nCheckDepth = chainActive.Height(); | nCheckDepth = chainActive.Height(); | ||||
} | } | ||||
nCheckLevel = std::max(0, std::min(4, nCheckLevel)); | nCheckLevel = std::max(0, std::min(4, nCheckLevel)); | ||||
LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, | LogPrint(BCLog::BENCH, "Verifying last %i blocks at level %i\n", | ||||
nCheckLevel); | nCheckDepth, nCheckLevel); | ||||
CCoinsViewCache coins(coinsview); | CCoinsViewCache coins(coinsview); | ||||
CBlockIndex *pindexState = chainActive.Tip(); | CBlockIndex *pindexState = chainActive.Tip(); | ||||
CBlockIndex *pindexFailure = nullptr; | CBlockIndex *pindexFailure = nullptr; | ||||
int nGoodTransactions = 0; | int nGoodTransactions = 0; | ||||
CValidationState state; | CValidationState state; | ||||
int reportDone = 0; | int reportDone = 0; | ||||
LogPrintf("[0%%]..."); | LogPrint(BCLog::BENCH, "[0%%]..."); | ||||
for (CBlockIndex *pindex = chainActive.Tip(); pindex && pindex->pprev; | for (CBlockIndex *pindex = chainActive.Tip(); pindex && pindex->pprev; | ||||
pindex = pindex->pprev) { | pindex = pindex->pprev) { | ||||
boost::this_thread::interruption_point(); | boost::this_thread::interruption_point(); | ||||
int percentageDone = std::max( | int percentageDone = std::max( | ||||
1, std::min( | 1, std::min( | ||||
99, | 99, | ||||
(int)(((double)(chainActive.Height() - pindex->nHeight)) / | (int)(((double)(chainActive.Height() - pindex->nHeight)) / | ||||
(double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); | (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); | ||||
if (reportDone < percentageDone / 10) { | if (reportDone < percentageDone / 10) { | ||||
// report every 10% step | // report every 10% step | ||||
LogPrintf("[%d%%]...", percentageDone); | LogPrint(BCLog::BENCH, "[%d%%]...", percentageDone); | ||||
reportDone = percentageDone / 10; | reportDone = percentageDone / 10; | ||||
} | } | ||||
uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone); | uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone); | ||||
if (pindex->nHeight < chainActive.Height() - nCheckDepth) { | if (pindex->nHeight < chainActive.Height() - nCheckDepth) { | ||||
break; | break; | ||||
} | } | ||||
if (fPruneMode && !pindex->nStatus.hasData()) { | if (fPruneMode && !pindex->nStatus.hasData()) { | ||||
// If pruning, only go back as far as we have data. | // If pruning, only go back as far as we have data. | ||||
LogPrintf("VerifyDB(): block verification stopping at height %d " | LogPrint(BCLog::PRUNE, | ||||
"VerifyDB(): block verification stopping at height %d " | |||||
"(pruning, no data)\n", | "(pruning, no data)\n", | ||||
pindex->nHeight); | pindex->nHeight); | ||||
break; | break; | ||||
} | } | ||||
CBlock block; | CBlock block; | ||||
// check level 0: read from disk | // check level 0: read from disk | ||||
if (!ReadBlockFromDisk(block, pindex, config)) { | if (!ReadBlockFromDisk(block, pindex, config)) { | ||||
return error( | return error( | ||||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | if (nCheckLevel >= 4) { | ||||
if (!ConnectBlock(config, block, state, pindex, coins)) { | if (!ConnectBlock(config, block, state, pindex, coins)) { | ||||
return error( | return error( | ||||
"VerifyDB(): *** found unconnectable block at %d, hash=%s", | "VerifyDB(): *** found unconnectable block at %d, hash=%s", | ||||
pindex->nHeight, pindex->GetBlockHash().ToString()); | pindex->nHeight, pindex->GetBlockHash().ToString()); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
LogPrintf("[DONE].\n"); | LogPrint(BCLog::BENCH, "[DONE].\n"); | ||||
LogPrintf("No coin database inconsistencies in last %i blocks (%i " | LogPrint(BCLog::BENCH, | ||||
"No coin database inconsistencies in last %i blocks (%i " | |||||
"transactions)\n", | "transactions)\n", | ||||
chainActive.Height() - pindexState->nHeight, nGoodTransactions); | chainActive.Height() - pindexState->nHeight, nGoodTransactions); | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* Apply the effects of a block on the utxo cache, ignoring that it may already | * Apply the effects of a block on the utxo cache, ignoring that it may already | ||||
* have been applied. | * have been applied. | ||||
*/ | */ | ||||
Show All 35 Lines | if (hashHeads.empty()) { | ||||
return true; | return true; | ||||
} | } | ||||
if (hashHeads.size() != 2) { | if (hashHeads.size() != 2) { | ||||
return error("ReplayBlocks(): unknown inconsistent state"); | return error("ReplayBlocks(): unknown inconsistent state"); | ||||
} | } | ||||
uiInterface.ShowProgress(_("Replaying blocks..."), 0); | uiInterface.ShowProgress(_("Replaying blocks..."), 0); | ||||
LogPrintf("Replaying blocks\n"); | LogPrint(BCLog::BENCH, "Replaying blocks\n"); | ||||
// Old tip during the interrupted flush. | // Old tip during the interrupted flush. | ||||
const CBlockIndex *pindexOld = nullptr; | const CBlockIndex *pindexOld = nullptr; | ||||
// New tip during the interrupted flush. | // New tip during the interrupted flush. | ||||
const CBlockIndex *pindexNew; | const CBlockIndex *pindexNew; | ||||
// Latest block common to both the old and the new tip. | // Latest block common to both the old and the new tip. | ||||
const CBlockIndex *pindexFork = nullptr; | const CBlockIndex *pindexFork = nullptr; | ||||
Show All 23 Lines | while (pindexOld != pindexFork) { | ||||
CBlock block; | CBlock block; | ||||
if (!ReadBlockFromDisk(block, pindexOld, config)) { | if (!ReadBlockFromDisk(block, pindexOld, config)) { | ||||
return error("RollbackBlock(): ReadBlockFromDisk() failed at " | return error("RollbackBlock(): ReadBlockFromDisk() failed at " | ||||
"%d, hash=%s", | "%d, hash=%s", | ||||
pindexOld->nHeight, | pindexOld->nHeight, | ||||
pindexOld->GetBlockHash().ToString()); | pindexOld->GetBlockHash().ToString()); | ||||
} | } | ||||
LogPrintf("Rolling back %s (%i)\n", | LogPrint(BCLog::BENCH, "Rolling back %s (%i)\n", | ||||
pindexOld->GetBlockHash().ToString(), pindexOld->nHeight); | pindexOld->GetBlockHash().ToString(), pindexOld->nHeight); | ||||
DisconnectResult res = DisconnectBlock(block, pindexOld, cache); | DisconnectResult res = DisconnectBlock(block, pindexOld, cache); | ||||
if (res == DISCONNECT_FAILED) { | if (res == DISCONNECT_FAILED) { | ||||
return error( | return error( | ||||
"RollbackBlock(): DisconnectBlock failed at %d, hash=%s", | "RollbackBlock(): DisconnectBlock failed at %d, hash=%s", | ||||
pindexOld->nHeight, pindexOld->GetBlockHash().ToString()); | pindexOld->nHeight, pindexOld->GetBlockHash().ToString()); | ||||
} | } | ||||
// If DISCONNECT_UNCLEAN is returned, it means a non-existing UTXO | // If DISCONNECT_UNCLEAN is returned, it means a non-existing UTXO | ||||
// was deleted, or an existing UTXO was overwritten. It corresponds | // was deleted, or an existing UTXO was overwritten. It corresponds | ||||
// to cases where the block-to-be-disconnect never had all its | // to cases where the block-to-be-disconnect never had all its | ||||
// operations applied to the UTXO set. However, as both writing a | // operations applied to the UTXO set. However, as both writing a | ||||
// UTXO and deleting a UTXO are idempotent operations, the result is | // UTXO and deleting a UTXO are idempotent operations, the result is | ||||
// still a version of the UTXO set with the effects of that block | // still a version of the UTXO set with the effects of that block | ||||
// undone. | // undone. | ||||
} | } | ||||
pindexOld = pindexOld->pprev; | pindexOld = pindexOld->pprev; | ||||
} | } | ||||
// Roll forward from the forking point to the new tip. | // Roll forward from the forking point to the new tip. | ||||
int nForkHeight = pindexFork ? pindexFork->nHeight : 0; | int nForkHeight = pindexFork ? pindexFork->nHeight : 0; | ||||
for (int nHeight = nForkHeight + 1; nHeight <= pindexNew->nHeight; | for (int nHeight = nForkHeight + 1; nHeight <= pindexNew->nHeight; | ||||
++nHeight) { | ++nHeight) { | ||||
const CBlockIndex *pindex = pindexNew->GetAncestor(nHeight); | const CBlockIndex *pindex = pindexNew->GetAncestor(nHeight); | ||||
LogPrintf("Rolling forward %s (%i)\n", | LogPrint(BCLog::BENCH, "Rolling forward %s (%i)\n", | ||||
pindex->GetBlockHash().ToString(), nHeight); | pindex->GetBlockHash().ToString(), nHeight); | ||||
if (!RollforwardBlock(pindex, cache, config)) { | if (!RollforwardBlock(pindex, cache, config)) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
cache.SetBestBlock(pindexNew->GetBlockHash()); | cache.SetBestBlock(pindexNew->GetBlockHash()); | ||||
cache.Flush(); | cache.Flush(); | ||||
uiInterface.ShowProgress("", 100); | uiInterface.ShowProgress("", 100); | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | bool LoadBlockIndex(const Config &config) { | ||||
if (needs_init) { | if (needs_init) { | ||||
// Everything here is for *new* reindex/DBs. Thus, though | // Everything here is for *new* reindex/DBs. Thus, though | ||||
// LoadBlockIndexDB may have set fReindex if we shut down | // LoadBlockIndexDB may have set fReindex if we shut down | ||||
// mid-reindex previously, we don't check fReindex and | // mid-reindex previously, we don't check fReindex and | ||||
// instead only check it prior to LoadBlockIndexDB to set | // instead only check it prior to LoadBlockIndexDB to set | ||||
// needs_init. | // needs_init. | ||||
LogPrintf("Initializing databases...\n"); | LogPrint(BCLog::INIT, "Initializing databases...\n"); | ||||
// Use the provided setting for -txindex in the new database | // Use the provided setting for -txindex in the new database | ||||
fTxIndex = gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX); | fTxIndex = gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX); | ||||
pblocktree->WriteFlag("txindex", fTxIndex); | pblocktree->WriteFlag("txindex", fTxIndex); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool LoadGenesisBlock(const CChainParams &chainparams) { | bool LoadGenesisBlock(const CChainParams &chainparams) { | ||||
▲ Show 20 Lines • Show All 176 Lines • ▼ Show 20 Lines | try { | ||||
} | } | ||||
} | } | ||||
range.first++; | range.first++; | ||||
mapBlocksUnknownParent.erase(it); | mapBlocksUnknownParent.erase(it); | ||||
NotifyHeaderTip(); | NotifyHeaderTip(); | ||||
} | } | ||||
} | } | ||||
} catch (const std::exception &e) { | } catch (const std::exception &e) { | ||||
LogPrintf("%s: Deserialize or I/O error - %s\n", __func__, | LogPrint(BCLog::REINDEX, "%s: Deserialize or I/O error - %s\n", | ||||
e.what()); | __func__, e.what()); | ||||
} | } | ||||
} | } | ||||
} catch (const std::runtime_error &e) { | } catch (const std::runtime_error &e) { | ||||
AbortNode(std::string("System error: ") + e.what()); | AbortNode(std::string("System error: ") + e.what()); | ||||
} | } | ||||
if (nLoaded > 0) { | if (nLoaded > 0) { | ||||
LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, | LogPrint(BCLog::REINDEX, | ||||
"Loaded %i blocks from external file in %dms\n", nLoaded, | |||||
GetTimeMillis() - nStart); | GetTimeMillis() - nStart); | ||||
} | } | ||||
return nLoaded > 0; | return nLoaded > 0; | ||||
} | } | ||||
static void CheckBlockIndex(const Consensus::Params &consensusParams) { | static void CheckBlockIndex(const Consensus::Params &consensusParams) { | ||||
if (!fCheckBlockIndex) { | if (!fCheckBlockIndex) { | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 326 Lines • ▼ Show 20 Lines | |||||
static const uint64_t MEMPOOL_DUMP_VERSION = 1; | static const uint64_t MEMPOOL_DUMP_VERSION = 1; | ||||
bool LoadMempool(const Config &config) { | bool LoadMempool(const Config &config) { | ||||
int64_t nExpiryTimeout = | int64_t nExpiryTimeout = | ||||
gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60; | gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60; | ||||
FILE *filestr = fsbridge::fopen(GetDataDir() / "mempool.dat", "rb"); | FILE *filestr = fsbridge::fopen(GetDataDir() / "mempool.dat", "rb"); | ||||
CAutoFile file(filestr, SER_DISK, CLIENT_VERSION); | CAutoFile file(filestr, SER_DISK, CLIENT_VERSION); | ||||
if (file.IsNull()) { | if (file.IsNull()) { | ||||
LogPrintf( | LogPrint(BCLog::MEMPOOL, | ||||
"Failed to open mempool file from disk. Continuing anyway.\n"); | "Failed to open mempool file from disk. Continuing anyway.\n"); | ||||
return false; | return false; | ||||
} | } | ||||
int64_t count = 0; | int64_t count = 0; | ||||
int64_t skipped = 0; | int64_t skipped = 0; | ||||
int64_t failed = 0; | int64_t failed = 0; | ||||
int64_t nNow = GetTime(); | int64_t nNow = GetTime(); | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | try { | ||||
std::map<uint256, Amount> mapDeltas; | std::map<uint256, Amount> mapDeltas; | ||||
file >> mapDeltas; | file >> mapDeltas; | ||||
for (const auto &i : mapDeltas) { | for (const auto &i : mapDeltas) { | ||||
mempool.PrioritiseTransaction(i.first, i.first.ToString(), | mempool.PrioritiseTransaction(i.first, i.first.ToString(), | ||||
prioritydummy, i.second); | prioritydummy, i.second); | ||||
} | } | ||||
} catch (const std::exception &e) { | } catch (const std::exception &e) { | ||||
LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing " | LogPrint(BCLog::MEMPOOL, | ||||
"Failed to deserialize mempool data on disk: %s. Continuing " | |||||
"anyway.\n", | "anyway.\n", | ||||
e.what()); | e.what()); | ||||
return false; | return false; | ||||
} | } | ||||
LogPrintf("Imported mempool transactions from disk: %i successes, %i " | LogPrint(BCLog::MEMPOOL, | ||||
"Imported mempool transactions from disk: %i successes, %i " | |||||
"failed, %i expired\n", | "failed, %i expired\n", | ||||
count, failed, skipped); | count, failed, skipped); | ||||
return true; | return true; | ||||
} | } | ||||
void DumpMempool(void) { | void DumpMempool(void) { | ||||
int64_t start = GetTimeMicros(); | int64_t start = GetTimeMicros(); | ||||
std::map<uint256, Amount> mapDeltas; | std::map<uint256, Amount> mapDeltas; | ||||
std::vector<TxMempoolInfo> vinfo; | std::vector<TxMempoolInfo> vinfo; | ||||
Show All 29 Lines | try { | ||||
} | } | ||||
file << mapDeltas; | file << mapDeltas; | ||||
FileCommit(file.Get()); | FileCommit(file.Get()); | ||||
file.fclose(); | file.fclose(); | ||||
RenameOver(GetDataDir() / "mempool.dat.new", | RenameOver(GetDataDir() / "mempool.dat.new", | ||||
GetDataDir() / "mempool.dat"); | GetDataDir() / "mempool.dat"); | ||||
int64_t last = GetTimeMicros(); | int64_t last = GetTimeMicros(); | ||||
LogPrintf("Dumped mempool: %gs to copy, %gs to dump\n", | LogPrint(BCLog::MEMPOOL, "Dumped mempool: %gs to copy, %gs to dump\n", | ||||
(mid - start) * 0.000001, (last - mid) * 0.000001); | (mid - start) * 0.000001, (last - mid) * 0.000001); | ||||
} catch (const std::exception &e) { | } catch (const std::exception &e) { | ||||
LogPrintf("Failed to dump mempool: %s. Continuing anyway.\n", e.what()); | LogPrint(BCLog::MEMPOOL, | ||||
"Failed to dump mempool: %s. Continuing anyway.\n", e.what()); | |||||
} | } | ||||
} | } | ||||
//! Guess how far we are in the verification process at the given block index | //! Guess how far we are in the verification process at the given block index | ||||
double GuessVerificationProgress(const ChainTxData &data, CBlockIndex *pindex) { | double GuessVerificationProgress(const ChainTxData &data, CBlockIndex *pindex) { | ||||
if (pindex == nullptr) { | if (pindex == nullptr) { | ||||
return 0.0; | return 0.0; | ||||
} | } | ||||
Show All 26 Lines |