53 #include <boost/algorithm/string/replace.hpp> 55 #define MICRO 0.000001 77 "level 0 reads the blocks from disk",
78 "level 1 verifies block validity",
79 "level 2 verifies undo data",
80 "level 3 checks disconnection of tip blocks",
81 "level 4 tries to reconnect the blocks",
82 "each level includes the checks of the previous levels",
96 if (pa < pb)
return false;
97 if (pa > pb)
return true;
155 std::vector<CBlockFileInfo> vinfoBlockFile;
156 int nLastBlockFile = 0;
161 bool fCheckForPruning =
false;
164 std::set<CBlockIndex*> setDirtyBlockIndex;
167 std::set<int> setDirtyFileInfo;
173 BlockMap::const_iterator
it = g_chainman.
BlockIndex().find(hash);
174 return it == g_chainman.
BlockIndex().end() ? nullptr : it->second;
213 flags = std::max(flags, 0);
232 return IsFinalTx(tx, nBlockHeight, nBlockTime);
271 std::pair<int, int64_t> lockPair;
272 if (useExistingLockPoints) {
274 lockPair.first = lp->
height;
275 lockPair.second = lp->
time;
280 std::vector<int> prevheights;
281 prevheights.resize(tx.
vin.size());
282 for (
size_t txinIndex = 0; txinIndex < tx.
vin.size(); txinIndex++) {
283 const CTxIn& txin = tx.
vin[txinIndex];
286 return error(
"%s: Missing input", __func__);
290 prevheights[txinIndex] = tip->
nHeight + 1;
292 prevheights[txinIndex] = coin.
nHeight;
297 lp->
height = lockPair.first;
298 lp->
time = lockPair.second;
312 int maxInputHeight = 0;
313 for (
const int height : prevheights) {
315 if (height != tip->
nHeight+1) {
316 maxInputHeight = std::max(maxInputHeight, height);
331 int expired = pool.
Expire(GetTime<std::chrono::seconds>() - age);
338 for (
const COutPoint& removed : vNoSpendsRemaining)
382 if (!fAddToMempool || (*it)->IsCoinBase() ||
388 }
else if (mempool.
exists((*it)->GetHash())) {
389 vHashUpdate.push_back((*it)->GetHash());
427 if (coin.
IsSpent())
return false;
454 explicit MemPoolAccept(
CTxMemPool& mempool) : m_pool(mempool), m_view(&m_dummy), m_viewmempool(&::
ChainstateActive().CoinsTip(), m_pool),
465 const int64_t m_accept_time;
466 std::list<CTransactionRef>* m_replaced_transactions;
467 const bool m_bypass_limits;
475 std::vector<COutPoint>& m_coins_to_uncache;
476 const bool m_test_accept;
487 explicit Workspace(
const CTransactionRef& ptx) : m_ptx(ptx), m_hash(ptx->GetHash()) {}
488 std::set<uint256> m_conflicts;
491 std::unique_ptr<CTxMemPoolEntry> m_entry;
493 bool m_replacement_transaction;
496 size_t m_conflicting_size;
527 if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) {
531 if (package_fee < ::minRelayTxFee.
GetFee(package_size)) {
544 const size_t m_limit_ancestors;
545 const size_t m_limit_ancestor_size;
548 size_t m_limit_descendants;
549 size_t m_limit_descendant_size;
552 bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
556 const uint256& hash = ws.m_hash;
560 const int64_t nAcceptTime = args.m_accept_time;
561 const bool bypass_limits = args.m_bypass_limits;
562 std::vector<COutPoint>& coins_to_uncache = args.m_coins_to_uncache;
565 std::set<uint256>& setConflicts = ws.m_conflicts;
568 std::unique_ptr<CTxMemPoolEntry>& entry = ws.m_entry;
569 bool& fReplacementTransaction = ws.m_replacement_transaction;
570 CAmount& nModifiedFees = ws.m_modified_fees;
571 CAmount& nConflictingFees = ws.m_conflicting_fees;
572 size_t& nConflictingSize = ws.m_conflicting_size;
601 if (m_pool.exists(hash)) {
609 if (ptxConflicting) {
610 if (!setConflicts.count(ptxConflicting->
GetHash()))
624 bool fReplacementOptOut =
true;
625 for (
const CTxIn &_txin : ptxConflicting->
vin)
629 fReplacementOptOut =
false;
633 if (fReplacementOptOut) {
637 setConflicts.insert(ptxConflicting->
GetHash());
643 m_view.SetBackend(m_viewmempool);
649 coins_to_uncache.push_back(txin.
prevout);
655 if (!m_view.HaveCoin(txin.
prevout)) {
657 for (
size_t out = 0; out < tx.
vout.size(); out++) {
669 m_view.GetBestBlock();
674 m_view.SetBackend(m_dummy);
690 if (args.m_fee_out) {
691 *args.m_fee_out = nFees;
695 const auto& params = args.m_chainparams.GetConsensus();
708 nModifiedFees = nFees;
709 m_pool.ApplyDelta(hash, nModifiedFees);
713 bool fSpendsCoinbase =
false;
715 const Coin &coin = m_view.AccessCoin(txin.
prevout);
717 fSpendsCoinbase =
true;
723 fSpendsCoinbase, nSigOpsCost, lp));
724 unsigned int nSize = entry->GetTxSize();
732 if (!bypass_limits && !
CheckFeeRate(nSize, nModifiedFees, state))
return false;
736 if (setConflicts.size() == 1) {
764 assert(setIterConflicting.size() == 1);
767 m_limit_descendants += 1;
768 m_limit_descendant_size += conflict->GetSizeWithDescendants();
771 std::string errString;
772 if (!m_pool.CalculateMemPoolAncestors(*entry, setAncestors, m_limit_ancestors, m_limit_ancestor_size, m_limit_descendants, m_limit_descendant_size, errString)) {
773 setAncestors.clear();
775 std::string dummy_err_string;
788 !m_pool.CalculateMemPoolAncestors(*entry, setAncestors, 2, m_limit_ancestor_size, m_limit_descendants + 1, m_limit_descendant_size +
EXTRA_DESCENDANT_TX_SIZE_LIMIT, dummy_err_string)) {
799 const uint256 &hashAncestor = ancestorIt->GetTx().GetHash();
800 if (setConflicts.count(hashAncestor))
803 strprintf(
"%s spends conflicting transaction %s",
811 nConflictingFees = 0;
812 nConflictingSize = 0;
813 uint64_t nConflictingCount = 0;
818 fReplacementTransaction = setConflicts.size();
819 if (fReplacementTransaction)
821 CFeeRate newFeeRate(nModifiedFees, nSize);
822 std::set<uint256> setConflictsParents;
823 const int maxDescendantsToVisit = 100;
824 for (
const auto& mi : setIterConflicting) {
839 CFeeRate oldFeeRate(mi->GetModifiedFee(), mi->GetTxSize());
840 if (newFeeRate <= oldFeeRate)
843 strprintf(
"rejecting replacement %s; new feerate %s <= old feerate %s",
846 oldFeeRate.ToString()));
849 for (
const CTxIn &txin : mi->GetTx().vin)
854 nConflictingCount += mi->GetCountWithDescendants();
859 if (nConflictingCount <= maxDescendantsToVisit) {
863 m_pool.CalculateDescendants(
it, allConflicting);
866 nConflictingFees +=
it->GetModifiedFee();
867 nConflictingSize +=
it->GetTxSize();
871 strprintf(
"rejecting replacement %s; too many potential replacements (%d > %d)\n",
874 maxDescendantsToVisit));
877 for (
unsigned int j = 0; j < tx.
vin.size(); j++)
888 if (!setConflictsParents.count(tx.
vin[j].prevout.hash))
893 if (m_pool.exists(tx.
vin[j].prevout.hash)) {
895 strprintf(
"replacement %s adds unconfirmed input, idx %d",
904 if (nModifiedFees < nConflictingFees)
907 strprintf(
"rejecting replacement %s, less fees than conflicting txs; %s < %s",
913 CAmount nDeltaFees = nModifiedFees - nConflictingFees;
917 strprintf(
"rejecting replacement %s, not enough additional fees to relay; %s < %s",
936 if (!
CheckInputScripts(tx, state, m_view, scriptVerifyFlags,
true,
false, txdata)) {
956 const uint256& hash = ws.m_hash;
978 return error(
"%s: BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s",
985 bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws)
988 const uint256& hash = ws.m_hash;
990 const bool bypass_limits = args.m_bypass_limits;
994 const CAmount& nModifiedFees = ws.m_modified_fees;
995 const CAmount& nConflictingFees = ws.m_conflicting_fees;
996 const size_t& nConflictingSize = ws.m_conflicting_size;
997 const bool fReplacementTransaction = ws.m_replacement_transaction;
998 std::unique_ptr<CTxMemPoolEntry>& entry = ws.m_entry;
1004 it->GetTx().GetHash().ToString(),
1007 (int)entry->GetTxSize() - (int)nConflictingSize);
1008 if (args.m_replaced_transactions)
1009 args.m_replaced_transactions->push_back(
it->GetSharedTx());
1018 bool validForFeeEstimation = !fReplacementTransaction && !bypass_limits &&
IsCurrentForFeeEstimation() && m_pool.HasNoInputsOf(tx);
1021 m_pool.addUnchecked(*entry, setAncestors, validForFeeEstimation);
1024 if (!bypass_limits) {
1026 if (!m_pool.exists(hash))
1032 bool MemPoolAccept::AcceptSingleTransaction(
const CTransactionRef& ptx, ATMPArgs& args)
1037 Workspace workspace(ptx);
1039 if (!PreChecks(args, workspace))
return false;
1047 if (!PolicyScriptChecks(args, workspace, txdata))
return false;
1049 if (!ConsensusScriptChecks(args, workspace, txdata))
return false;
1052 if (args.m_test_accept)
return true;
1054 if (!Finalize(args, workspace))
return false;
1065 int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
1068 std::vector<COutPoint> coins_to_uncache;
1069 MemPoolAccept::ATMPArgs args { chainparams, state, nAcceptTime, plTxnReplaced, bypass_limits, coins_to_uncache, test_accept, fee_out };
1070 bool res = MemPoolAccept(pool).AcceptSingleTransaction(tx, args);
1077 for (
const COutPoint& hashTx : coins_to_uncache)
1087 std::list<CTransactionRef>* plTxnReplaced,
1088 bool bypass_limits,
bool test_accept,
CAmount* fee_out)
1101 for (
const auto& tx : block.
vtx) {
1112 if (ptx)
return ptx;
1116 if (
g_txindex->FindTx(hash, hashBlock, tx))
return tx;
1131 return error(
"WriteBlockToDisk: OpenBlockFile failed");
1135 fileout << messageStart << nSize;
1138 long fileOutPos = ftell(fileout.
Get());
1140 return error(
"WriteBlockToDisk: ftell failed");
1141 pos.
nPos = (
unsigned int)fileOutPos;
1154 return error(
"ReadBlockFromDisk: OpenBlockFile failed for %s", pos.
ToString());
1160 catch (
const std::exception& e) {
1161 return error(
"%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.
ToString());
1166 return error(
"ReadBlockFromDisk: Errors in block header at %s", pos.
ToString());
1170 return error(
"ReadBlockFromDisk: Errors in block solution at %s", pos.
ToString());
1187 return error(
"ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
1198 return error(
"%s: OpenBlockFile failed for %s", __func__, pos.
ToString());
1203 unsigned int blk_size;
1205 filein >> blk_start >> blk_size;
1208 return error(
"%s: Block magic mismatch for %s: %s versus expected %s", __func__, pos.
ToString(),
1214 return error(
"%s: Block data is larger than maximum deserialization size for %s: %s versus %s", __func__, pos.
ToString(),
1218 block.resize(blk_size);
1219 filein.
read((
char*)block.data(), blk_size);
1220 }
catch(
const std::exception& e) {
1221 return error(
"%s: Read from block file failed: %s for %s", __func__, e.what(), pos.
ToString());
1247 nSubsidy >>= halvings;
1252 std::string ldb_name,
1253 size_t cache_size_bytes,
1255 bool should_wipe) : m_dbview(
1256 GetDataDir() / ldb_name, cache_size_bytes, in_memory, should_wipe),
1257 m_catcherview(&m_dbview) {}
1259 void CoinsViews::InitCache()
1261 m_cacheview = MakeUnique<CCoinsViewCache>(&m_catcherview);
1265 : m_blockman(blockman),
1267 m_from_snapshot_blockhash(from_snapshot_blockhash) {}
1270 size_t cache_size_bytes,
1273 std::string leveldb_name)
1280 leveldb_name, cache_size_bytes, in_memory, should_wipe);
1283 void CChainState::InitCoinsCache(
size_t cache_size_bytes)
1312 LogPrintf(
"Leaving InitialBlockDownload (latching to false)\n");
1321 std::string strCmd =
gArgs.
GetArg(
"-alertnotify",
"");
1322 if (strCmd.empty())
return;
1327 std::string singleQuote(
"'");
1329 safeStatus = singleQuote+safeStatus+singleQuote;
1330 boost::replace_all(strCmd,
"%s", safeStatus);
1332 std::thread t(runCommand, strCmd);
1347 LogPrintf(
"%s: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n", __func__);
1357 if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork)
1358 pindexBestInvalid = pindexNew;
1359 if (pindexBestHeader !=
nullptr && pindexBestHeader->
GetAncestor(pindexNew->nHeight) == pindexNew) {
1363 LogPrintf(
"%s: invalid block=%s height=%d log2_work=%f date=%s\n", __func__,
1364 pindexNew->GetBlockHash().ToString(), pindexNew->nHeight,
1368 LogPrintf(
"%s: current best=%s height=%d log2_work=%f date=%s\n", __func__,
1380 setDirtyBlockIndex.insert(pindex);
1408 const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
1417 return pindexPrev->
nHeight + 1;
1430 g_scriptExecutionCacheHasher.
Write(nonce.
begin(), 32);
1431 g_scriptExecutionCacheHasher.
Write(nonce.
begin(), 32);
1435 size_t nElems = g_scriptExecutionCache.
setup_bytes(nMaxCacheSize);
1436 LogPrintf(
"Using %zu MiB out of %zu/2 requested for script execution cache, able to store %zu elements\n",
1437 (nElems*
sizeof(
uint256)) >>20, (nMaxCacheSize*2)>>20, nElems);
1464 pvChecks->reserve(tx.
vin.size());
1476 if (g_scriptExecutionCache.
contains(hashCacheEntry, !cacheFullScriptStore)) {
1481 std::vector<CTxOut> spent_outputs;
1482 spent_outputs.reserve(tx.
vin.size());
1484 for (
const auto& txin : tx.
vin) {
1485 const COutPoint& prevout = txin.prevout;
1486 const Coin& coin = inputs.AccessCoin(prevout);
1488 spent_outputs.emplace_back(coin.
out);
1490 txdata.
Init(tx, std::move(spent_outputs));
1494 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
1506 check.
swap(pvChecks->back());
1507 }
else if (!check()) {
1518 flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheSigStore, &txdata);
1535 if (cacheFullScriptStore && !pvChecks) {
1538 g_scriptExecutionCache.
insert(hashCacheEntry);
1549 return error(
"%s: OpenUndoFile failed", __func__);
1553 fileout << messageStart << nSize;
1556 long fileOutPos = ftell(fileout.
Get());
1558 return error(
"%s: ftell failed", __func__);
1559 pos.
nPos = (
unsigned int)fileOutPos;
1560 fileout << blockundo;
1564 hasher << hashBlock;
1565 hasher << blockundo;
1575 return error(
"%s: no undo data available", __func__);
1581 return error(
"%s: OpenUndoFile failed", __func__);
1588 verifier >> blockundo;
1589 filein >> hashChecksum;
1591 catch (
const std::exception& e) {
1592 return error(
"%s: Deserialize or I/O error - %s", __func__, e.what());
1596 if (hashChecksum != verifier.
GetHash())
1597 return error(
"%s: Checksum mismatch", __func__);
1607 if (user_message.empty()) {
1608 user_message =
_(
"A fatal internal error occurred, see debug.log for details");
1618 return state.
Error(strMessage);
1632 if (view.
HaveCoin(out)) fClean =
false;
1634 if (undo.nHeight == 0) {
1640 undo.nHeight = alternate.
nHeight;
1651 view.
AddCoin(out, std::move(undo), !fClean);
1664 error(
"DisconnectBlock(): failure reading undo data");
1668 if (blockUndo.
vtxundo.size() + 1 != block.
vtx.size()) {
1669 error(
"DisconnectBlock(): block and undo data inconsistent");
1674 for (
int i = block.
vtx.size() - 1; i >= 0; i--) {
1681 for (
size_t o = 0; o < tx.
vout.size(); o++) {
1682 if (!tx.
vout[o].scriptPubKey.IsUnspendable()) {
1685 bool is_spent = view.
SpendCoin(out, &coin);
1696 error(
"DisconnectBlock(): transaction and undo data inconsistent");
1699 for (
unsigned int j = tx.
vin.size(); j-- > 0;) {
1717 FlatFilePos undo_pos_old(block_file, vinfoBlockFile[block_file].nUndoSize);
1718 if (!
UndoFileSeq().Flush(undo_pos_old, finalize)) {
1719 AbortNode(
"Flushing undo file to disk failed. This is likely the result of an I/O error.");
1725 LOCK(cs_LastBlockFile);
1726 FlatFilePos block_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nSize);
1728 AbortNode(
"Flushing block file to disk failed. This is likely the result of an I/O error.");
1732 if (!fFinalize || finalize_undo)
FlushUndoFile(nLastBlockFile, finalize_undo);
1743 return error(
"ConnectBlock(): FindUndoPos failed");
1745 return AbortNode(state,
"Failed to write undo data");
1751 if (_pos.
nFile < nLastBlockFile && static_cast<uint32_t>(pindex->
nHeight) == vinfoBlockFile[_pos.
nFile].nHeightLast) {
1758 setDirtyBlockIndex.insert(pindex);
1768 scriptcheckqueue.
Thread();
1781 nVersion |=
VersionBitsMask(params, static_cast<Consensus::DeploymentPos>(i));
1808 ((pindex->
nVersion >> bit) & 1) != 0 &&
1821 return params.
SegwitHeight != std::numeric_limits<int>::max();
1834 if (consensusparams.BIP16Exception.IsNull() ||
1836 *pindex->
phashBlock != consensusparams.BIP16Exception)
1848 if (pindex->
nHeight >= consensusparams.BIP66Height) {
1853 if (pindex->
nHeight >= consensusparams.BIP65Height) {
1858 if (pindex->
nHeight >= consensusparams.CSVHeight) {
1915 return AbortNode(state,
"Corrupt block found indicating potential hardware failure; shutting down");
1917 return error(
"%s: Consensus::CheckBlock: %s", __func__, state.
ToString());
1934 bool fScriptChecks =
true;
1935 if (!hashAssumeValid.
IsNull()) {
1941 BlockMap::const_iterator
it =
m_blockman.m_block_index.find(hashAssumeValid);
1943 if (it->second->GetAncestor(pindex->
nHeight) == pindex &&
1965 int64_t nTime1 =
GetTimeMicros(); nTimeCheck += nTime1 - nTimeStart;
1980 bool fEnforceBIP30 = !((pindex->
nHeight==91842 && pindex->
GetBlockHash() ==
uint256S(
"0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
1981 (pindex->
nHeight==91880 && pindex->
GetBlockHash() ==
uint256S(
"0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
2009 static constexpr
int BIP34_IMPLIES_BIP30_LIMIT = 1983702;
2047 if (fEnforceBIP30 || pindex->
nHeight >= BIP34_IMPLIES_BIP30_LIMIT) {
2048 for (
const auto& tx : block.
vtx) {
2049 for (
size_t o = 0; o < tx->
vout.size(); o++) {
2051 LogPrintf(
"ERROR: ConnectBlock(): tried to overwrite transaction\n");
2059 int nLockTimeFlags = 0;
2067 int64_t nTime2 =
GetTimeMicros(); nTimeForks += nTime2 - nTime1;
2068 LogPrint(
BCLog::BENCH,
" - Fork checks: %.2fms [%.2fs (%.2fms/blk)]\n",
MILLI * (nTime2 - nTime1), nTimeForks * MICRO, nTimeForks *
MILLI / nBlocksTotal);
2078 std::vector<PrecomputedTransactionData> txsdata(block.
vtx.size());
2080 std::vector<int> prevheights;
2083 int64_t nSigOpsCost = 0;
2084 blockundo.
vtxundo.reserve(block.
vtx.size() - 1);
2085 for (
unsigned int i = 0; i < block.
vtx.size(); i++)
2089 nInputs += tx.
vin.size();
2103 LogPrintf(
"ERROR: %s: accumulated fee in the block out of range.\n", __func__);
2110 prevheights.resize(tx.
vin.size());
2111 for (
size_t j = 0; j < tx.
vin.size(); j++) {
2115 if (!
SequenceLocks(tx, nLockTimeFlags, prevheights, *pindex)) {
2116 LogPrintf(
"ERROR: %s: contains a non-BIP68-final transaction\n", __func__);
2127 LogPrintf(
"ERROR: ConnectBlock(): too many sigops\n");
2133 std::vector<CScriptCheck> vChecks;
2134 bool fCacheResults = fJustCheck;
2140 return error(
"ConnectBlock(): CheckInputScripts on %s failed with %s",
2143 control.
Add(vChecks);
2152 int64_t nTime3 =
GetTimeMicros(); nTimeConnect += nTime3 - nTime2;
2153 LogPrint(
BCLog::BENCH,
" - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs (%.2fms/blk)]\n", (
unsigned)block.
vtx.size(),
MILLI * (nTime3 - nTime2),
MILLI * (nTime3 - nTime2) / block.
vtx.size(), nInputs <= 1 ? 0 :
MILLI * (nTime3 - nTime2) / (nInputs-1), nTimeConnect *
MICRO, nTimeConnect *
MILLI /
nBlocksTotal);
2156 if (block.
vtx[0]->GetValueOut() > blockReward) {
2157 LogPrintf(
"ERROR: ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)\n", block.
vtx[0]->GetValueOut(), blockReward);
2161 if (!control.
Wait()) {
2162 LogPrintf(
"ERROR: %s: CheckQueue failed\n", __func__);
2165 int64_t nTime4 =
GetTimeMicros(); nTimeVerify += nTime4 - nTime2;
2166 LogPrint(
BCLog::BENCH,
" - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs (%.2fms/blk)]\n", nInputs - 1,
MILLI * (nTime4 - nTime2), nInputs <= 1 ? 0 :
MILLI * (nTime4 - nTime2) / (nInputs-1), nTimeVerify * MICRO, nTimeVerify *
MILLI / nBlocksTotal);
2176 setDirtyBlockIndex.insert(pindex);
2183 int64_t nTime5 =
GetTimeMicros(); nTimeIndex += nTime5 - nTime4;
2184 LogPrint(
BCLog::BENCH,
" - Index writing: %.2fms [%.2fs (%.2fms/blk)]\n",
MILLI * (nTime5 - nTime4), nTimeIndex * MICRO, nTimeIndex *
MILLI / nBlocksTotal);
2186 int64_t nTime6 =
GetTimeMicros(); nTimeCallbacks += nTime6 - nTime5;
2187 LogPrint(
BCLog::BENCH,
" - Callbacks: %.2fms [%.2fs (%.2fms/blk)]\n",
MILLI * (nTime6 - nTime5), nTimeCallbacks * MICRO, nTimeCallbacks *
MILLI / nBlocksTotal);
2194 return this->GetCoinsCacheSizeState(
2202 size_t max_coins_cache_size_bytes,
2203 size_t max_mempool_size_bytes)
2207 int64_t nTotalSpace =
2208 max_coins_cache_size_bytes + std::max<int64_t>(max_mempool_size_bytes - nMempoolUsage, 0);
2211 static constexpr int64_t MAX_BLOCK_COINSDB_USAGE_BYTES = 10 * 1024 * 1024;
2212 int64_t large_threshold =
2213 std::max((9 * nTotalSpace) / 10, nTotalSpace - MAX_BLOCK_COINSDB_USAGE_BYTES);
2215 if (cacheSize > nTotalSpace) {
2216 LogPrintf(
"Cache size (%s) exceeds total space (%s)\n", cacheSize, nTotalSpace);
2218 }
else if (cacheSize > large_threshold) {
2224 bool CChainState::FlushStateToDisk(
2228 int nManualPruneHeight)
2231 assert(this->CanFlushToDisk());
2232 static std::chrono::microseconds nLastWrite{0};
2233 static std::chrono::microseconds nLastFlush{0};
2234 std::set<int> setFilesToPrune;
2235 bool full_flush_completed =
false;
2242 bool fFlushForPrune =
false;
2243 bool fDoFullFlush =
false;
2245 LOCK(cs_LastBlockFile);
2247 if (nManualPruneHeight > 0) {
2255 fCheckForPruning =
false;
2257 if (!setFilesToPrune.empty()) {
2258 fFlushForPrune =
true;
2260 pblocktree->WriteFlag(
"prunedblockfiles",
true);
2265 const auto nNow = GetTime<std::chrono::microseconds>();
2267 if (nLastWrite.count() == 0) {
2270 if (nLastFlush.count() == 0) {
2282 fDoFullFlush = (mode ==
FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune;
2284 if (fDoFullFlush || fPeriodicWrite) {
2287 return AbortNode(state,
"Disk space is too low!",
_(
"Disk space is too low!"));
2300 std::vector<std::pair<int, const CBlockFileInfo*> > vFiles;
2301 vFiles.reserve(setDirtyFileInfo.size());
2302 for (std::set<int>::iterator
it = setDirtyFileInfo.begin();
it != setDirtyFileInfo.end(); ) {
2303 vFiles.push_back(std::make_pair(*
it, &vinfoBlockFile[*
it]));
2304 setDirtyFileInfo.erase(it++);
2306 std::vector<const CBlockIndex*> vBlocks;
2307 vBlocks.reserve(setDirtyBlockIndex.size());
2308 for (std::set<CBlockIndex*>::iterator
it = setDirtyBlockIndex.begin();
it != setDirtyBlockIndex.end(); ) {
2309 vBlocks.push_back(*
it);
2310 setDirtyBlockIndex.erase(
it++);
2312 if (!
pblocktree->WriteBatchSync(vFiles, nLastBlockFile, vBlocks)) {
2313 return AbortNode(state,
"Failed to write to block index database");
2317 if (fFlushForPrune) {
2325 if (fDoFullFlush && !
CoinsTip().GetBestBlock().IsNull()) {
2327 coins_count, coins_mem_usage / 1000));
2335 return AbortNode(state,
"Disk space is too low!",
_(
"Disk space is too low!"));
2339 return AbortNode(state,
"Failed to write to coin database");
2341 full_flush_completed =
true;
2344 if (full_flush_completed) {
2348 }
catch (
const std::runtime_error& e) {
2349 return AbortNode(state, std::string(
"System error while flushing: ") + e.what());
2364 fCheckForPruning =
true;
2374 static bool fWarned =
false;
2397 LOCK(g_best_block_mutex);
2398 g_best_block = pindexNew->GetBlockHash();
2418 LogPrintf(
"%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)%s\n", __func__,
2419 pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion,
2420 log(pindexNew->nChainWork.getdouble())/log(2.0), (
unsigned long)pindexNew->nChainTx,
2444 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
2447 return error(
"DisconnectTip(): Failed to read block");
2455 bool flushed = view.
Flush();
2463 if (disconnectpool) {
2465 for (
auto it = block.vtx.rbegin();
it != block.vtx.rend(); ++
it) {
2511 assert(!blocksConnected.back().pindex);
2514 blocksConnected.back().pindex = pindex;
2515 blocksConnected.back().pblock = std::move(pblock);
2516 blocksConnected.emplace_back();
2525 assert(!blocksConnected.back().pindex);
2526 blocksConnected.pop_back();
2527 return blocksConnected;
2545 std::shared_ptr<const CBlock> pthisBlock;
2547 std::shared_ptr<CBlock> pblockNew = std::make_shared<CBlock>();
2549 return AbortNode(state,
"Failed to read block");
2550 pthisBlock = pblockNew;
2552 pthisBlock = pblock;
2554 const CBlock& blockConnecting = *pthisBlock;
2556 int64_t nTime2 =
GetTimeMicros(); nTimeReadFromDisk += nTime2 - nTime1;
2561 bool rv =
ConnectBlock(blockConnecting, state, pindexNew, view, chainparams);
2568 nTime3 =
GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
2569 assert(nBlocksTotal > 0);
2570 LogPrint(
BCLog::BENCH,
" - Connect total: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime3 - nTime2) * MILLI, nTimeConnectTotal * MICRO, nTimeConnectTotal * MILLI / nBlocksTotal);
2571 bool flushed = view.
Flush();
2574 int64_t nTime4 =
GetTimeMicros(); nTimeFlush += nTime4 - nTime3;
2575 LogPrint(
BCLog::BENCH,
" - Flush: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime4 - nTime3) * MILLI, nTimeFlush * MICRO, nTimeFlush * MILLI / nBlocksTotal);
2579 int64_t nTime5 =
GetTimeMicros(); nTimeChainState += nTime5 - nTime4;
2580 LogPrint(
BCLog::BENCH,
" - Writing chainstate: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime5 - nTime4) * MILLI, nTimeChainState * MICRO, nTimeChainState * MILLI / nBlocksTotal);
2588 int64_t nTime6 =
GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
2589 LogPrint(
BCLog::BENCH,
" - Connect postprocess: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime6 - nTime5) * MILLI, nTimePostConnect * MICRO, nTimePostConnect * MILLI / nBlocksTotal);
2590 LogPrint(
BCLog::BENCH,
"- Connect block: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime6 - nTime1) * MILLI, nTimeTotal * MICRO, nTimeTotal * MILLI / nBlocksTotal);
2615 bool fInvalidAncestor =
false;
2625 if (fFailedChain || fMissingData) {
2627 if (fFailedChain && (pindexBestInvalid ==
nullptr || pindexNew->
nChainWork > pindexBestInvalid->nChainWork))
2628 pindexBestInvalid = pindexNew;
2631 while (pindexTest != pindexFailed) {
2634 }
else if (fMissingData) {
2639 std::make_pair(pindexFailed->
pprev, pindexFailed));
2642 pindexFailed = pindexFailed->
pprev;
2645 fInvalidAncestor =
true;
2648 pindexTest = pindexTest->
pprev;
2650 if (!fInvalidAncestor)
2682 bool fBlocksDisconnected =
false;
2693 AbortNode(state,
"Failed to disconnect block; see debug.log for details");
2696 fBlocksDisconnected =
true;
2700 std::vector<CBlockIndex*> vpindexToConnect;
2701 bool fContinue =
true;
2703 while (fContinue && nHeight != pindexMostWork->
nHeight) {
2706 int nTargetHeight = std::min(nHeight + 32, pindexMostWork->
nHeight);
2707 vpindexToConnect.clear();
2708 vpindexToConnect.reserve(nTargetHeight - nHeight);
2710 while (pindexIter && pindexIter->
nHeight != nHeight) {
2711 vpindexToConnect.push_back(pindexIter);
2712 pindexIter = pindexIter->
pprev;
2714 nHeight = nTargetHeight;
2718 if (!
ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool)) {
2725 fInvalidFound =
true;
2746 if (fBlocksDisconnected) {
2766 bool fNotify =
false;
2767 bool fInitialBlockDownload =
false;
2774 if (pindexHeader != pindexHeaderOld) {
2777 pindexHeaderOld = pindexHeader;
2824 bool blocks_connected =
false;
2830 if (pindexMostWork ==
nullptr) {
2835 if (pindexMostWork ==
nullptr || pindexMostWork ==
m_chain.
Tip()) {
2839 bool fInvalidFound =
false;
2840 std::shared_ptr<const CBlock> nullBlockPtr;
2841 if (!
ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->
GetBlockHash() ? pblock : nullBlockPtr, fInvalidFound, connectTrace)) {
2845 blocks_connected =
true;
2847 if (fInvalidFound) {
2849 pindexMostWork =
nullptr;
2854 assert(trace.pblock && trace.pindex);
2858 if (!blocks_connected)
return true;
2865 if (pindexFork != pindexNewTip) {
2882 }
while (pindexNewTip != pindexMostWork);
2932 bool pindex_was_in_chain =
false;
2933 int disconnected = 0;
2947 std::multimap<const arith_uint256, CBlockIndex *> candidate_blocks_by_work;
2951 for (
const auto& entry :
m_blockman.m_block_index) {
2962 candidate_blocks_by_work.insert(std::make_pair(candidate->
nChainWork, candidate));
2977 pindex_was_in_chain =
true;
2983 bool ret =
DisconnectTip(state, chainparams, &disconnectpool);
2990 if (!ret)
return false;
2999 setDirtyBlockIndex.insert(invalid_walk_tip);
3006 setDirtyBlockIndex.insert(to_mark_failed);
3010 auto candidate_it = candidate_blocks_by_work.lower_bound(invalid_walk_tip->
pprev->
nChainWork);
3011 while (candidate_it != candidate_blocks_by_work.end()) {
3014 candidate_it = candidate_blocks_by_work.erase(candidate_it);
3022 to_mark_failed = invalid_walk_tip;
3036 setDirtyBlockIndex.insert(to_mark_failed);
3047 BlockMap::iterator
it =
m_blockman.m_block_index.begin();
3048 while (it !=
m_blockman.m_block_index.end()) {
3059 if (pindex_was_in_chain) {
3075 BlockMap::iterator
it =
m_blockman.m_block_index.begin();
3076 while (it !=
m_blockman.m_block_index.end()) {
3077 if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) {
3079 setDirtyBlockIndex.insert(it->second);
3083 if (it->second == pindexBestInvalid) {
3085 pindexBestInvalid =
nullptr;
3093 while (pindex !=
nullptr) {
3096 setDirtyBlockIndex.insert(pindex);
3099 pindex = pindex->
pprev;
3113 BlockMap::iterator
it = m_block_index.find(hash);
3114 if (it != m_block_index.end())
3123 BlockMap::iterator mi = m_block_index.insert(std::make_pair(hash, pindexNew)).first;
3124 pindexNew->phashBlock = &((*mi).first);
3125 BlockMap::iterator miPrev = m_block_index.find(block.
hashPrevBlock);
3126 if (miPrev != m_block_index.end())
3128 pindexNew->pprev = (*miPrev).second;
3129 pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
3130 pindexNew->BuildSkip();
3132 pindexNew->nTimeMax = (pindexNew->pprev ? std::max(pindexNew->pprev->nTimeMax, pindexNew->nTime) : pindexNew->nTime);
3133 pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) +
GetBlockProof(*pindexNew);
3135 if (pindexBestHeader ==
nullptr || pindexBestHeader->
nChainWork < pindexNew->nChainWork)
3136 pindexBestHeader = pindexNew;
3138 setDirtyBlockIndex.insert(pindexNew);
3146 pindexNew->
nTx = block.
vtx.size();
3156 setDirtyBlockIndex.insert(pindexNew);
3160 std::deque<CBlockIndex*> queue;
3161 queue.push_back(pindexNew);
3164 while (!queue.empty()) {
3175 std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range =
m_blockman.
m_blocks_unlinked.equal_range(pindex);
3176 while (range.first != range.second) {
3177 std::multimap<CBlockIndex*, CBlockIndex*>::iterator
it = range.first;
3178 queue.push_back(it->second);
3192 LOCK(cs_LastBlockFile);
3194 unsigned int nFile = fKnown ? pos.
nFile : nLastBlockFile;
3195 if (vinfoBlockFile.size() <= nFile) {
3196 vinfoBlockFile.resize(nFile + 1);
3199 bool finalize_undo =
false;
3207 if (vinfoBlockFile.size() <= nFile) {
3208 vinfoBlockFile.resize(nFile + 1);
3212 pos.
nPos = vinfoBlockFile[nFile].nSize;
3215 if ((
int)nFile != nLastBlockFile) {
3217 LogPrintf(
"Leaving block file %i: %s\n", nLastBlockFile, vinfoBlockFile[nLastBlockFile].
ToString());
3220 nLastBlockFile = nFile;
3223 vinfoBlockFile[nFile].AddBlock(nHeight, nTime);
3225 vinfoBlockFile[nFile].nSize = std::max(pos.
nPos + nAddSize, vinfoBlockFile[nFile].nSize);
3227 vinfoBlockFile[nFile].nSize += nAddSize;
3233 return AbortNode(
"Disk space is too low!",
_(
"Disk space is too low!"));
3236 fCheckForPruning =
true;
3240 setDirtyFileInfo.insert(nFile);
3248 LOCK(cs_LastBlockFile);
3250 pos.
nPos = vinfoBlockFile[nFile].nUndoSize;
3251 vinfoBlockFile[nFile].nUndoSize += nAddSize;
3252 setDirtyFileInfo.insert(nFile);
3257 return AbortNode(state,
"Disk space is too low!",
_(
"Disk space is too low!"));
3260 fCheckForPruning =
true;
3293 if (fCheckMerkleRoot) {
3317 if (block.
vtx.empty() || !block.
vtx[0]->IsCoinBase())
3319 for (
unsigned int i = 1; i < block.
vtx.size(); i++)
3320 if (block.
vtx[i]->IsCoinBase())
3325 for (
const auto& tx : block.
vtx) {
3335 unsigned int nSigOps = 0;
3336 for (
const auto& tx : block.
vtx)
3343 if (fCheckPOW && fCheckMerkleRoot)
3351 int height = pindexPrev ==
nullptr ? 0 : pindexPrev->
nHeight + 1;
3358 static const std::vector<unsigned char> nonce(32, 0x00);
3361 tx.
vin[0].scriptWitness.stack.resize(1);
3362 tx.
vin[0].scriptWitness.stack[0] = nonce;
3369 std::vector<unsigned char> commitment;
3371 std::vector<unsigned char> ret(32, 0x00);
3372 if (consensusParams.
SegwitHeight != std::numeric_limits<int>::max()) {
3388 tx.vout.push_back(out);
3401 for (
const MapCheckpoints::value_type& i :
reverse_iterate(checkpoints))
3403 const uint256& hash = i.second;
3423 assert(pindexPrev !=
nullptr);
3424 const int nHeight = pindexPrev->nHeight + 1;
3437 if (pcheckpoint && nHeight < pcheckpoint->nHeight) {
3438 LogPrintf(
"ERROR: %s: forked chain older than last checkpoint (height %d)\n", __func__, nHeight);
3444 if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
3453 if((block.nVersion < 2 && nHeight >= consensusParams.
BIP34Height) ||
3454 (block.nVersion < 3 && nHeight >= consensusParams.
BIP66Height) ||
3455 (block.nVersion < 4 && nHeight >= consensusParams.
BIP65Height))
3457 strprintf(
"rejected nVersion=0x%08x block", block.nVersion));
3470 const int nHeight = pindexPrev ==
nullptr ? 0 : pindexPrev->
nHeight + 1;
3473 int nLockTimeFlags = 0;
3474 if (nHeight >= consensusParams.
CSVHeight) {
3475 assert(pindexPrev !=
nullptr);
3484 for (
const auto& tx : block.
vtx) {
3485 if (!
IsFinalTx(*tx, nHeight, nLockTimeCutoff)) {
3494 if (block.
vtx[0]->vin[0].scriptSig.size() < expect.
size() ||
3495 !std::equal(expect.
begin(), expect.
end(), block.
vtx[0]->vin[0].scriptSig.begin())) {
3508 bool fHaveWitness =
false;
3512 bool malleated =
false;
3517 if (block.
vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.
vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
3521 if (memcmp(hashWitness.
begin(), &block.
vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
3524 fHaveWitness =
true;
3529 if (!fHaveWitness) {
3530 for (
const auto& tx : block.
vtx) {
3555 BlockMap::iterator miSelf = m_block_index.find(hash);
3558 if (miSelf != m_block_index.end()) {
3560 pindex = miSelf->second;
3564 LogPrintf(
"ERROR: %s: block %s is marked invalid\n", __func__, hash.
ToString());
3577 BlockMap::iterator mi = m_block_index.find(block.
hashPrevBlock);
3578 if (mi == m_block_index.end()) {
3579 LogPrintf(
"ERROR: %s: prev block not found\n", __func__);
3582 pindexPrev = (*mi).second;
3584 LogPrintf(
"ERROR: %s: prev block invalid\n", __func__);
3588 return error(
"%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.
ToString(), state.
ToString());
3614 for (
const CBlockIndex* failedit : m_failed_blocks) {
3615 if (pindexPrev->
GetAncestor(failedit->nHeight) == failedit) {
3618 while (invalid_walk != failedit) {
3620 setDirtyBlockIndex.insert(invalid_walk);
3621 invalid_walk = invalid_walk->
pprev;
3623 LogPrintf(
"ERROR: %s: prev block invalid\n", __func__);
3629 if (pindex ==
nullptr)
3630 pindex = AddToBlockIndex(block);
3647 header, state, chainparams, &pindex);
3673 error(
"%s: FindBlockPos failed", __func__);
3676 if (dbp ==
nullptr) {
3688 const CBlock& block = *pblock;
3690 if (fNewBlock) *fNewBlock =
false;
3694 CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
3699 if (!accepted_header)
3721 if (fAlreadyHave)
return true;
3723 if (pindex->
nTx != 0)
return true;
3724 if (!fHasMoreOrSameWork)
return true;
3725 if (fTooFarAhead)
return true;
3731 if (pindex->
nChainWork < nMinimumChainWork)
return true;
3738 setDirtyBlockIndex.insert(pindex);
3749 if (fNewBlock) *fNewBlock =
true;
3753 state.
Error(
strprintf(
"%s: Failed to find position to write new block to disk", __func__));
3757 }
catch (
const std::runtime_error& e) {
3758 return AbortNode(state, std::string(
"System error: ") + e.what());
3774 if (fNewBlock) *fNewBlock =
false;
3790 return error(
"%s: AcceptBlock FAILED (%s)", __func__, state.
ToString());
3798 return error(
"%s: ActivateBestChain failed (%s)", __func__, state.
ToString());
3810 indexDummy.pprev = pindexPrev;
3812 indexDummy.phashBlock = &block_hash;
3816 return error(
"%s: Consensus::ContextualCheckBlockHeader: %s", __func__, state.
ToString());
3818 return error(
"%s: Consensus::CheckBlock: %s", __func__, state.
ToString());
3820 return error(
"%s: Consensus::ContextualCheckBlock: %s", __func__, state.
ToString());
3835 LOCK(cs_LastBlockFile);
3837 uint64_t retval = 0;
3839 retval += file.nSize + file.nUndoSize;
3847 LOCK(cs_LastBlockFile);
3849 for (
const auto& entry : m_block_index) {
3851 if (pindex->
nFile == fileNumber) {
3857 setDirtyBlockIndex.insert(pindex);
3863 auto range = m_blocks_unlinked.equal_range(pindex->
pprev);
3864 while (range.first != range.second) {
3865 std::multimap<CBlockIndex *, CBlockIndex *>::iterator _it = range.first;
3867 if (_it->second == pindex) {
3868 m_blocks_unlinked.erase(_it);
3874 vinfoBlockFile[fileNumber].SetNull();
3875 setDirtyFileInfo.insert(fileNumber);
3881 for (std::set<int>::iterator
it = setFilesToPrune.begin();
it != setFilesToPrune.end(); ++
it) {
3885 LogPrintf(
"Prune: %s deleted blk/rev (%05u)\n", __func__, *
it);
3893 LOCK2(cs_main, cs_LastBlockFile);
3894 if (chain_tip_height < 0) {
3899 unsigned int nLastBlockWeCanPrune = std::min((
unsigned)nManualPruneHeight, chain_tip_height -
MIN_BLOCKS_TO_KEEP);
3901 for (
int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) {
3902 if (vinfoBlockFile[fileNumber].nSize == 0 || vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune) {
3905 PruneOneBlockFile(fileNumber);
3906 setFilesToPrune.insert(fileNumber);
3909 LogPrintf(
"Prune (Manual): prune_height=%d removed %d blk/rev pairs\n", nLastBlockWeCanPrune, count);
3925 LOCK2(cs_main, cs_LastBlockFile);
3929 if ((uint64_t)chain_tip_height <= nPruneAfterHeight) {
3939 uint64_t nBytesToPrune;
3952 for (
int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) {
3953 nBytesToPrune = vinfoBlockFile[fileNumber].nSize + vinfoBlockFile[fileNumber].nUndoSize;
3955 if (vinfoBlockFile[fileNumber].nSize == 0) {
3964 if (vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune) {
3968 PruneOneBlockFile(fileNumber);
3970 setFilesToPrune.insert(fileNumber);
3971 nCurrentUsage -= nBytesToPrune;
3976 LogPrint(
BCLog::PRUNE,
"Prune: target=%dMiB actual=%dMiB diff=%dMiB max_prune_height=%d removed %d blk/rev pairs\n",
3978 ((int64_t)
nPruneTarget - (int64_t)nCurrentUsage)/1024/1024,
3979 nLastBlockWeCanPrune, count);
4014 BlockMap::iterator mi = m_block_index.find(hash);
4015 if (mi != m_block_index.end())
4016 return (*mi).second;
4020 mi = m_block_index.insert(std::make_pair(hash, pindexNew)).first;
4029 std::set<CBlockIndex*, CBlockIndexWorkComparator>& block_index_candidates)
4035 std::vector<std::pair<int, CBlockIndex*> > vSortedByHeight;
4036 vSortedByHeight.reserve(m_block_index.size());
4037 for (
const std::pair<const uint256, CBlockIndex*>& item : m_block_index)
4040 vSortedByHeight.push_back(std::make_pair(pindex->
nHeight, pindex));
4042 sort(vSortedByHeight.begin(), vSortedByHeight.end());
4043 for (
const std::pair<int, CBlockIndex*>& item : vSortedByHeight)
4051 if (pindex->
nTx > 0) {
4052 if (pindex->
pprev) {
4057 m_blocks_unlinked.insert(std::make_pair(pindex->
pprev, pindex));
4065 setDirtyBlockIndex.insert(pindex);
4068 block_index_candidates.insert(pindex);
4071 pindexBestInvalid = pindex;
4075 pindexBestHeader = pindex;
4082 m_failed_blocks.clear();
4083 m_blocks_unlinked.clear();
4085 for (
const BlockMap::value_type& entry : m_block_index) {
4086 delete entry.second;
4089 m_block_index.clear();
4094 if (!chainman.m_blockman.LoadBlockIndex(
4101 pblocktree->ReadLastBlockFile(nLastBlockFile);
4102 vinfoBlockFile.resize(nLastBlockFile + 1);
4103 LogPrintf(
"%s: last block file = %i\n", __func__, nLastBlockFile);
4104 for (
int nFile = 0; nFile <= nLastBlockFile; nFile++) {
4105 pblocktree->ReadBlockFileInfo(nFile, vinfoBlockFile[nFile]);
4107 LogPrintf(
"%s: last block file info: %s\n", __func__, vinfoBlockFile[nLastBlockFile].
ToString());
4108 for (
int nFile = nLastBlockFile + 1;
true; nFile++) {
4110 if (
pblocktree->ReadBlockFileInfo(nFile, info)) {
4111 vinfoBlockFile.push_back(info);
4118 LogPrintf(
"Checking all blk files are present...\n");
4119 std::set<int> setBlkDataFiles;
4120 for (
const std::pair<const uint256, CBlockIndex*>& item : chainman.BlockIndex()) {
4123 setBlkDataFiles.insert(pindex->
nFile);
4126 for (std::set<int>::iterator
it = setBlkDataFiles.begin();
it != setBlkDataFiles.end();
it++)
4137 LogPrintf(
"LoadBlockIndexDB(): Block files have previously been pruned\n");
4140 bool fReindexing =
false;
4162 if (tip && tip->GetBlockHash() == coins_cache.
GetBestBlock()) {
4175 LogPrintf(
"Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n",
4176 tip->GetBlockHash().ToString(),
4185 uiInterface.ShowProgress(
_(
"Verifying blocks...").translated, 0,
false);
4202 nCheckLevel = std::max(0, std::min(4, nCheckLevel));
4203 LogPrintf(
"Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
4207 int nGoodTransactions = 0;
4212 const int percentageDone = std::max(1, std::min(99, (
int)(((
double)(::
ChainActive().Height() - pindex->
nHeight)) / (
double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
4213 if (reportDone < percentageDone/10) {
4216 reportDone = percentageDone/10;
4218 uiInterface.ShowProgress(
_(
"Verifying blocks...").translated, percentageDone,
false);
4223 LogPrintf(
"VerifyDB(): block verification stopping at height %d (pruning, no data)\n", pindex->
nHeight);
4232 return error(
"%s: *** found bad block at %d, hash=%s (%s)\n", __func__,
4235 if (nCheckLevel >= 2 && pindex) {
4251 nGoodTransactions = 0;
4252 pindexFailure = pindex;
4254 nGoodTransactions += block.
vtx.size();
4260 return error(
"VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", ::
ChainActive().Height() - pindexFailure->
nHeight + 1, nGoodTransactions);
4266 if (nCheckLevel >= 4) {
4268 const int percentageDone = std::max(1, std::min(99, 100 - (
int)(((
double)(::
ChainActive().Height() - pindex->
nHeight)) / (
double)nCheckDepth * 50)));
4269 if (reportDone < percentageDone/10) {
4272 reportDone = percentageDone/10;
4274 uiInterface.ShowProgress(
_(
"Verifying blocks...").translated, percentageDone,
false);
4286 LogPrintf(
"No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions);
4301 if (!tx->IsCoinBase()) {
4302 for (
const CTxIn &txin : tx->vin) {
4320 if (hashHeads.empty())
return true;
4321 if (hashHeads.size() != 2)
return error(
"ReplayBlocks(): unknown inconsistent state");
4323 uiInterface.ShowProgress(
_(
"Replaying blocks...").translated, 0,
false);
4330 if (
m_blockman.m_block_index.count(hashHeads[0]) == 0) {
4331 return error(
"ReplayBlocks(): reorganization to unknown block requested");
4333 pindexNew =
m_blockman.m_block_index[hashHeads[0]];
4335 if (!hashHeads[1].IsNull()) {
4336 if (
m_blockman.m_block_index.count(hashHeads[1]) == 0) {
4337 return error(
"ReplayBlocks(): reorganization from unknown block requested");
4339 pindexOld =
m_blockman.m_block_index[hashHeads[1]];
4341 assert(pindexFork !=
nullptr);
4345 while (pindexOld != pindexFork) {
4361 pindexOld = pindexOld->
pprev;
4365 int nForkHeight = pindexFork ? pindexFork->
nHeight : 0;
4369 uiInterface.ShowProgress(
_(
"Replaying blocks...").translated, (
int) ((
nHeight - nForkHeight) * 100.0 / (pindexNew->
nHeight - nForkHeight)) ,
false);
4398 setDirtyBlockIndex.insert(index);
4402 while (ret.first != ret.second) {
4403 if (ret.first->second == index) {
4424 for (
const auto& entry :
m_blockman.m_block_index) {
4458 if (tip ==
nullptr || tip->
nHeight < nHeight)
break;
4470 return error(
"RewindBlockIndex: unable to disconnect block at height %i (%s)", tip->
nHeight, state.
ToString());
4490 LogPrintf(
"RewindBlockIndex: unable to flush state to disk (%s)\n", state.
ToString());
4509 LogPrintf(
"RewindBlockIndex: unable to flush state to disk (%s)\n", state.ToString());
4530 pindexBestInvalid =
nullptr;
4531 pindexBestHeader =
nullptr;
4532 if (mempool) mempool->
clear();
4533 vinfoBlockFile.clear();
4535 setDirtyBlockIndex.clear();
4536 setDirtyFileInfo.clear();
4539 warningcache[b].clear();
4551 if (!ret)
return false;
4552 needs_init =
m_blockman.m_block_index.empty();
4562 LogPrintf(
"Initializing databases...\n");
4582 return error(
"%s: writing genesis block to disk failed", __func__);
4585 }
catch (
const std::runtime_error& e) {
4586 return error(
"%s: failed to write genesis block: %s", __func__, e.what());
4600 static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
4607 uint64_t nRewind = blkdat.
GetPos();
4608 while (!blkdat.
eof()) {
4614 unsigned int nSize = 0;
4619 nRewind = blkdat.
GetPos()+1;
4627 }
catch (
const std::exception&) {
4633 uint64_t nBlockPos = blkdat.
GetPos();
4635 dbp->
nPos = nBlockPos;
4636 blkdat.
SetLimit(nBlockPos + nSize);
4637 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4640 nRewind = blkdat.
GetPos();
4642 uint256 hash = block.GetHash();
4648 block.hashPrevBlock.ToString());
4650 mapBlocksUnknownParent.insert(std::make_pair(block.hashPrevBlock, *dbp));
4680 std::deque<uint256> queue;
4681 queue.push_back(hash);
4682 while (!queue.empty()) {
4685 std::pair<std::multimap<uint256, FlatFilePos>::iterator, std::multimap<uint256, FlatFilePos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
4686 while (range.first != range.second) {
4687 std::multimap<uint256, FlatFilePos>::iterator
it = range.first;
4688 std::shared_ptr<CBlock> pblockrecursive = std::make_shared<CBlock>();
4691 LogPrint(
BCLog::REINDEX,
"%s: Processing out of order child %s of %s\n", __func__, pblockrecursive->GetHash().ToString(),
4698 queue.push_back(pblockrecursive->GetHash());
4702 mapBlocksUnknownParent.erase(it);
4706 }
catch (
const std::exception& e) {
4707 LogPrintf(
"%s: Deserialize or I/O error - %s\n", __func__, e.what());
4710 }
catch (
const std::runtime_error& e) {
4711 AbortNode(std::string(
"System error: ") + e.what());
4733 std::multimap<CBlockIndex*,CBlockIndex*> forward;
4734 for (
const std::pair<const uint256, CBlockIndex*>& entry :
m_blockman.m_block_index) {
4735 forward.insert(std::make_pair(entry.second->pprev, entry.second));
4740 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeGenesis = forward.equal_range(
nullptr);
4742 rangeGenesis.first++;
4743 assert(rangeGenesis.first == rangeGenesis.second);
4754 CBlockIndex* pindexFirstNotTransactionsValid =
nullptr;
4756 CBlockIndex* pindexFirstNotScriptsValid =
nullptr;
4757 while (pindex !=
nullptr) {
4761 if (pindexFirstNeverProcessed ==
nullptr && pindex->
nTx == 0) pindexFirstNeverProcessed = pindex;
4768 if (pindex->
pprev ==
nullptr) {
4779 assert(pindexFirstMissing == pindexFirstNeverProcessed);
4792 assert(pindexFirstNotTreeValid ==
nullptr);
4796 if (pindexFirstInvalid ==
nullptr) {
4801 if (pindexFirstInvalid ==
nullptr) {
4806 if (pindexFirstMissing ==
nullptr || pindex ==
m_chain.
Tip()) {
4817 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeUnlinked =
m_blockman.
m_blocks_unlinked.equal_range(pindex->
pprev);
4818 bool foundInUnlinked =
false;
4819 while (rangeUnlinked.first != rangeUnlinked.second) {
4820 assert(rangeUnlinked.first->first == pindex->
pprev);
4821 if (rangeUnlinked.first->second == pindex) {
4822 foundInUnlinked =
true;
4825 rangeUnlinked.first++;
4827 if (pindex->
pprev && (pindex->
nStatus &
BLOCK_HAVE_DATA) && pindexFirstNeverProcessed !=
nullptr && pindexFirstInvalid ==
nullptr) {
4832 if (pindexFirstMissing ==
nullptr)
assert(!foundInUnlinked);
4833 if (pindex->
pprev && (pindex->
nStatus &
BLOCK_HAVE_DATA) && pindexFirstNeverProcessed ==
nullptr && pindexFirstMissing !=
nullptr) {
4845 if (pindexFirstInvalid ==
nullptr) {
4854 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> range = forward.equal_range(pindex);
4855 if (range.first != range.second) {
4857 pindex = range.first->second;
4866 if (pindex == pindexFirstInvalid) pindexFirstInvalid =
nullptr;
4867 if (pindex == pindexFirstMissing) pindexFirstMissing =
nullptr;
4868 if (pindex == pindexFirstNeverProcessed) pindexFirstNeverProcessed =
nullptr;
4869 if (pindex == pindexFirstNotTreeValid) pindexFirstNotTreeValid =
nullptr;
4870 if (pindex == pindexFirstNotTransactionsValid) pindexFirstNotTransactionsValid =
nullptr;
4871 if (pindex == pindexFirstNotChainValid) pindexFirstNotChainValid =
nullptr;
4872 if (pindex == pindexFirstNotScriptsValid) pindexFirstNotScriptsValid =
nullptr;
4876 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangePar = forward.equal_range(pindexPar);
4877 while (rangePar.first->second != pindex) {
4878 assert(rangePar.first != rangePar.second);
4883 if (rangePar.first != rangePar.second) {
4885 pindex = rangePar.first->second;
4897 assert(nNodes == forward.size());
4903 return strprintf(
"Chainstate [%s] @ height %d (%s)",
4908 bool CChainState::ResizeCoinsCaches(
size_t coinstip_size,
size_t coinsdb_size)
4920 LogPrintf(
"[%s] resized coinsdb cache to %.1f MiB\n",
4921 this->
ToString(), coinsdb_size * (1.0 / 1024 / 1024));
4922 LogPrintf(
"[%s] resized coinstip cache to %.1f MiB\n",
4923 this->
ToString(), coinstip_size * (1.0 / 1024 / 1024));
4930 if (coinstip_size > old_coinstip_size) {
4948 LOCK(cs_LastBlockFile);
4950 return &vinfoBlockFile.at(n);
4980 LogPrintf(
"Failed to open mempool file from disk. Continuing anyway.\n");
4985 int64_t expired = 0;
4987 int64_t already_there = 0;
4988 int64_t unbroadcast = 0;
4994 if (version != MEMPOOL_DUMP_VERSION) {
5007 CAmount amountdelta = nFeeDelta;
5012 if (nTime > nNow - nExpiryTimeout) {
5024 if (pool.
exists(tx->GetHash())) {
5036 std::map<uint256, CAmount> mapDeltas;
5039 for (
const auto& i : mapDeltas) {
5043 std::set<uint256> unbroadcast_txids;
5044 file >> unbroadcast_txids;
5045 unbroadcast = unbroadcast_txids.size();
5046 for (
const auto& txid : unbroadcast_txids) {
5051 }
catch (
const std::exception& e) {
5052 LogPrintf(
"Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
5056 LogPrintf(
"Imported mempool transactions from disk: %i succeeded, %i failed, %i expired, %i already there, %i waiting for initial broadcast\n", count, failed, expired, already_there, unbroadcast);
5064 std::map<uint256, CAmount> mapDeltas;
5065 std::vector<TxMempoolInfo> vinfo;
5066 std::set<uint256> unbroadcast_txids;
5068 static Mutex dump_mutex;
5074 mapDeltas[i.first] = i.second;
5093 file << (uint64_t)vinfo.size();
5094 for (
const auto& i : vinfo) {
5097 file << int64_t{i.nFeeDelta};
5098 mapDeltas.erase(i.tx->GetHash());
5103 LogPrintf(
"Writing %d unbroadcast transactions to disk.\n", unbroadcast_txids.size());
5104 file << unbroadcast_txids;
5107 throw std::runtime_error(
"FileCommit failed");
5110 throw std::runtime_error(
"Rename failed");
5113 LogPrintf(
"Dumped mempool: %gs to copy, %gs to dump\n", (mid-start)*
MICRO, (last-mid)*MICRO);
5114 }
catch (
const std::exception& e) {
5115 LogPrintf(
"Failed to dump mempool: %s. Continuing anyway.\n", e.what());
5124 if (pindex ==
nullptr)
5127 int64_t nNow = time(
nullptr);
5137 return std::min<double>(pindex->
nChainTx / fTxTot