58 #include <boost/algorithm/string/replace.hpp>
83 #define MICRO 0.000001
91 "level 0 reads the blocks from disk",
92 "level 1 verifies block validity",
93 "level 2 verifies undo data",
94 "level 3 checks disconnection of tip blocks",
95 "level 4 tries to reconnect the blocks",
96 "each level includes the checks of the previous levels",
127 : excessiveBlockSize(config.GetMaxBlockSize()), checkPoW(true),
128 checkMerkleRoot(true) {}
155 bool useExistingLockPoints) {
167 std::pair<int, int64_t> lockPair;
168 if (useExistingLockPoints) {
171 lockPair.second =
lp->
time;
173 std::vector<int> prevheights;
174 prevheights.resize(tx.
vin.size());
175 for (
size_t txinIndex = 0; txinIndex < tx.
vin.size(); txinIndex++) {
176 const CTxIn &txin = tx.
vin[txinIndex];
179 return error(
"%s: Missing input", __func__);
183 prevheights[txinIndex] = tip->
nHeight + 1;
185 prevheights[txinIndex] = coin.
GetHeight();
192 lp->
time = lockPair.second;
206 int maxInputHeight = 0;
207 for (
const int height : prevheights) {
210 if (height != tip->
nHeight + 1) {
211 maxInputHeight = std::max(maxInputHeight, height);
225 int64_t nMedianTimePast) {
226 return nMedianTimePast >=
gArgs.
GetIntArg(
"-replayprotectionactivationtime",
232 if (pindexPrev ==
nullptr) {
273 const Coin &coinFromUTXOSet = coins_tip.AccessCoin(txin.
prevout);
282 true, txdata, nSigChecksOut);
287 class MemPoolAccept {
290 : m_pool(mempool), m_view(&m_dummy),
291 m_viewmempool(&active_chainstate.CoinsTip(), m_pool),
292 m_active_chainstate(active_chainstate),
295 m_limit_ancestor_size(
gArgs.GetIntArg(
"-limitancestorsize",
298 m_limit_descendants(
gArgs.GetIntArg(
"-limitdescendantcount",
300 m_limit_descendant_size(
301 gArgs.GetIntArg(
"-limitdescendantsize",
309 const int64_t m_accept_time;
310 const bool m_bypass_limits;
318 std::vector<COutPoint> &m_coins_to_uncache;
319 const bool m_test_accept;
325 const bool m_package_submission;
328 static ATMPArgs SingleAccept(
const Config &config, int64_t accept_time,
330 std::vector<COutPoint> &coins_to_uncache,
332 return ATMPArgs{config,
345 PackageTestAccept(
const Config &config, int64_t accept_time,
346 std::vector<COutPoint> &coins_to_uncache) {
347 return ATMPArgs{config, accept_time,
348 false, coins_to_uncache,
356 PackageChildWithParents(
const Config &config, int64_t accept_time,
357 std::vector<COutPoint> &coins_to_uncache) {
358 return ATMPArgs{config,
383 AcceptMultipleTransactions(
const std::vector<CTransactionRef> &txns,
401 const uint32_t next_block_script_verify_flags)
403 m_next_block_script_verify_flags(next_block_script_verify_flags) {
412 std::unique_ptr<CTxMemPoolEntry> m_entry;
442 const uint32_t m_next_block_script_verify_flags;
443 int m_sig_checks_standard;
451 bool PreChecks(ATMPArgs &args, Workspace &ws)
456 bool PackageMempoolChecks(
const std::vector<CTransactionRef> &txns,
464 bool ConsensusScriptChecks(
const ATMPArgs &args, Workspace &ws)
470 bool Finalize(
const ATMPArgs &args, Workspace &ws)
479 bool SubmitPackage(
const ATMPArgs &args, std::vector<Workspace> &workspaces,
481 std::map<const TxId, const MempoolAcceptResult> &results)
493 const size_t m_limit_ancestors;
494 const size_t m_limit_ancestor_size;
497 size_t m_limit_descendants;
498 size_t m_limit_descendant_size;
501 bool MemPoolAccept::PreChecks(ATMPArgs &args, Workspace &ws) {
506 const TxId &txid = ws.m_ptx->GetId();
509 const int64_t nAcceptTime = args.m_accept_time;
510 const bool bypass_limits = args.m_bypass_limits;
511 std::vector<COutPoint> &coins_to_uncache = args.m_coins_to_uncache;
515 std::unique_ptr<CTxMemPoolEntry> &entry = ws.m_entry;
533 m_active_chainstate.m_chain.Tip(),
534 args.m_config.GetChainParams().GetConsensus(), tx, ctxState)) {
543 if (m_pool.exists(txid)) {
545 "txn-already-in-mempool");
550 auto itConflicting = m_pool.mapNextTx.find(txin.
prevout);
551 if (itConflicting != m_pool.mapNextTx.end()) {
554 "txn-mempool-conflict");
559 m_view.SetBackend(m_viewmempool);
565 coins_to_uncache.push_back(txin.
prevout);
572 if (!m_view.HaveCoin(txin.
prevout)) {
574 for (
size_t out = 0; out < tx.
vout.size(); out++) {
579 "txn-already-known");
586 "bad-txns-inputs-missingorspent");
591 if (!m_view.HaveInputs(tx)) {
593 "bad-txns-inputs-spent");
597 m_view.GetBestBlock();
602 m_view.SetBackend(m_dummy);
604 assert(m_active_chainstate.m_blockman.LookupBlockIndex(
605 m_view.GetBestBlock()) == m_active_chainstate.m_chain.Tip());
622 m_active_chainstate.m_chain.Height() + 1,
632 "bad-txns-nonstandard-inputs");
636 ws.m_modified_fees = ws.m_base_fees;
637 m_pool.ApplyDelta(txid, ws.m_modified_fees);
641 bool fSpendsCoinbase =
false;
643 const Coin &coin = m_view.AccessCoin(txin.
prevout);
645 fSpendsCoinbase =
true;
658 "min relay fee not met",
664 const uint32_t scriptVerifyFlags =
668 ws.m_precomputed_txdata, ws.m_sig_checks_standard)) {
674 ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(),
675 fSpendsCoinbase, ws.m_sig_checks_standard,
lp));
677 ws.m_vsize = entry->GetTxVirtualSize();
685 if (!bypass_limits && mempoolRejectFee >
Amount::zero() &&
686 ws.m_modified_fees < mempoolRejectFee) {
689 strprintf(
"%d < %d", ws.m_modified_fees, mempoolRejectFee));
693 std::string errString;
694 if (!m_pool.CalculateMemPoolAncestors(
695 *entry, ws.m_ancestors, m_limit_ancestors, m_limit_ancestor_size,
696 m_limit_descendants, m_limit_descendant_size, errString)) {
698 "too-long-mempool-chain", errString);
703 bool MemPoolAccept::PackageMempoolChecks(
704 const std::vector<CTransactionRef> &txns,
711 assert(std::all_of(txns.cbegin(), txns.cend(), [
this](
const auto &tx) {
712 return !m_pool.exists(tx->GetId());
715 std::string err_string;
716 if (!m_pool.CheckPackageLimits(txns, m_limit_ancestors,
717 m_limit_ancestor_size, m_limit_descendants,
718 m_limit_descendant_size, err_string)) {
722 "package-mempool-limits", err_string);
727 bool MemPoolAccept::ConsensusScriptChecks(
const ATMPArgs &args, Workspace &ws) {
745 int nSigChecksConsensus;
747 tx, state, m_view, m_pool, ws.m_next_block_script_verify_flags,
748 ws.m_precomputed_txdata, nSigChecksConsensus,
749 m_active_chainstate.CoinsTip())) {
753 LogPrintf(
"BUG! PLEASE REPORT THIS! CheckInputScripts failed against "
754 "latest-block but not STANDARD flags %s, %s\n",
759 if (ws.m_sig_checks_standard != nSigChecksConsensus) {
764 "%s: BUG! PLEASE REPORT THIS! SigChecks count differed between "
765 "standard and consensus flags in %s",
771 bool MemPoolAccept::Finalize(
const ATMPArgs &args, Workspace &ws) {
774 const TxId &txid = ws.m_ptx->GetId();
776 const bool bypass_limits = args.m_bypass_limits;
778 std::unique_ptr<CTxMemPoolEntry> &entry = ws.m_entry;
781 m_pool.addUnchecked(*entry, ws.m_ancestors);
788 if (!args.m_package_submission && !bypass_limits) {
790 m_active_chainstate.CoinsTip(),
793 gArgs.GetIntArg(
"-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
794 if (!m_pool.exists(txid)) {
802 bool MemPoolAccept::SubmitPackage(
803 const ATMPArgs &args, std::vector<Workspace> &workspaces,
805 std::map<const TxId, const MempoolAcceptResult> &results) {
810 workspaces.cbegin(), workspaces.cend(),
811 [
this](
const auto &ws) { return !m_pool.exists(ws.m_ptx->GetId()); }));
813 bool all_submitted =
true;
820 for (Workspace &ws : workspaces) {
821 if (!ConsensusScriptChecks(args, ws)) {
822 results.emplace(ws.m_ptx->GetId(),
825 all_submitted =
Assume(
false);
831 std::string unused_err_string;
832 if (!m_pool.CalculateMemPoolAncestors(
833 *ws.m_entry, ws.m_ancestors, m_limit_ancestors,
834 m_limit_ancestor_size, m_limit_descendants,
835 m_limit_descendant_size, unused_err_string)) {
836 results.emplace(ws.m_ptx->GetId(),
840 all_submitted =
Assume(
false);
849 if (!Finalize(args, ws)) {
850 results.emplace(ws.m_ptx->GetId(),
853 all_submitted =
Assume(
false);
860 m_active_chainstate.CoinsTip(),
863 gArgs.GetIntArg(
"-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
864 if (!all_submitted) {
871 for (Workspace &ws : workspaces) {
872 if (m_pool.exists(ws.m_ptx->GetId())) {
874 ws.m_vsize, ws.m_base_fees));
876 ws.m_ptx, m_pool.GetAndIncrementSequence());
878 all_submitted =
false;
881 results.emplace(ws.m_ptx->GetId(),
885 return all_submitted;
897 args.m_config.GetChainParams().GetConsensus(),
898 m_active_chainstate.m_chain.Tip()));
903 if (!PreChecks(args, ws)) {
907 if (!ConsensusScriptChecks(args, ws)) {
912 if (args.m_test_accept) {
916 if (!Finalize(args, ws)) {
921 ptx, m_pool.GetAndIncrementSequence());
927 const std::vector<CTransactionRef> &txns, ATMPArgs &args) {
937 std::vector<Workspace> workspaces{};
938 workspaces.reserve(txns.size());
939 std::transform(txns.cbegin(), txns.cend(), std::back_inserter(workspaces),
940 [&args,
this](
const auto &tx) {
943 GetNextBlockScriptFlags(
944 args.m_config.GetChainParams().GetConsensus(),
945 m_active_chainstate.m_chain.Tip()));
947 std::map<const TxId, const MempoolAcceptResult> results;
953 for (Workspace &ws : workspaces) {
954 if (!PreChecks(args, ws)) {
956 "transaction failed");
959 results.emplace(ws.m_ptx->GetId(),
966 m_viewmempool.PackageAddTransaction(ws.m_ptx);
967 if (args.m_test_accept) {
972 ws.m_vsize, ws.m_base_fees));
980 std::string err_string;
981 if (txns.size() > 1 && !PackageMempoolChecks(txns, package_state)) {
985 if (args.m_test_accept) {
989 if (!SubmitPackage(args, workspaces, package_state, results)) {
991 "submission failed");
1017 "package-not-child-with-parents");
1022 assert(package.size() > 1);
1025 const auto &child = package.back();
1026 std::unordered_set<TxId, SaltedTxIdHasher> unconfirmed_parent_txids;
1028 package.cbegin(), package.cend() - 1,
1029 std::inserter(unconfirmed_parent_txids, unconfirmed_parent_txids.end()),
1030 [](
const auto &tx) { return tx->GetId(); });
1039 const CCoinsViewCache &coins_tip_cache = m_active_chainstate.CoinsTip();
1040 for (
const auto &input : child->vin) {
1042 args.m_coins_to_uncache.push_back(input.prevout);
1049 m_view.
SetBackend(m_active_chainstate.CoinsTip());
1050 const auto package_or_confirmed = [
this, &unconfirmed_parent_txids](
1051 const auto &input) {
1052 return unconfirmed_parent_txids.count(input.prevout.GetTxId()) > 0 ||
1053 m_view.HaveCoin(input.prevout);
1055 if (!std::all_of(child->vin.cbegin(), child->vin.cend(),
1056 package_or_confirmed)) {
1058 "package-not-child-with-unconfirmed-parents");
1064 m_view.SetBackend(m_dummy);
1067 std::map<const TxId, const MempoolAcceptResult> results;
1079 std::vector<CTransactionRef> txns_new;
1080 for (
const auto &tx : package) {
1081 const auto &txid = tx->
GetId();
1084 if (m_pool.exists(txid)) {
1086 auto iter = m_pool.GetIter(txid);
1087 assert(iter != std::nullopt);
1090 iter.value()->GetFee()));
1093 txns_new.push_back(tx);
1098 if (txns_new.empty()) {
1102 auto submission_result = AcceptMultipleTransactions(txns_new, args);
1104 for (
const auto &[txid, mempoolaccept_res] : results) {
1105 submission_result.m_tx_results.emplace(txid, mempoolaccept_res);
1107 return submission_result;
1114 int64_t accept_time,
bool bypass_limits,
1120 std::vector<COutPoint> coins_to_uncache;
1121 auto args = MemPoolAccept::ATMPArgs::SingleAccept(
1122 config, accept_time, bypass_limits, coins_to_uncache, test_accept);
1124 .AcceptSingleTransaction(tx, args);
1132 for (
const COutPoint &outpoint : coins_to_uncache) {
1148 assert(!package.empty());
1149 assert(std::all_of(package.cbegin(), package.cend(),
1150 [](
const auto &tx) { return tx != nullptr; }));
1152 std::vector<COutPoint> coins_to_uncache;
1156 auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(
1157 config,
GetTime(), coins_to_uncache);
1158 return MemPoolAccept(pool, active_chainstate)
1159 .AcceptMultipleTransactions(package, args);
1161 auto args = MemPoolAccept::ATMPArgs::PackageChildWithParents(
1162 config,
GetTime(), coins_to_uncache);
1163 return MemPoolAccept(pool, active_chainstate)
1164 .AcceptPackage(package, args);
1170 if (test_accept || result.m_state.IsInvalid()) {
1171 for (
const COutPoint &hashTx : coins_to_uncache) {
1184 if (halvings >= 64) {
1195 bool in_memory,
bool should_wipe)
1196 : m_dbview(
gArgs.GetDataDirNet() / ldb_name, cache_size_bytes, in_memory,
1198 m_catcherview(&m_dbview) {}
1200 void CoinsViews::InitCache() {
1202 m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview);
1207 std::optional<BlockHash> from_snapshot_blockhash)
1208 : m_mempool(mempool), m_blockman(blockman),
m_params(::
Params()),
1209 m_chainman(chainman), m_from_snapshot_blockhash(from_snapshot_blockhash) {
1213 bool should_wipe, std::string leveldb_name) {
1217 m_coins_views = std::make_unique<CoinsViews>(leveldb_name, cache_size_bytes,
1218 in_memory, should_wipe);
1221 void CChainState::InitCoinsCache(
size_t cache_size_bytes) {
1255 LogPrintf(
"Leaving InitialBlockDownload (latching to false)\n");
1262 #if defined(HAVE_SYSTEM)
1263 std::string strCmd =
gArgs.
GetArg(
"-alertnotify",
"");
1264 if (strCmd.empty()) {
1271 std::string singleQuote(
"'");
1273 safeStatus = singleQuote + safeStatus + singleQuote;
1274 boost::replace_all(strCmd,
"%s", safeStatus);
1276 std::thread t(runCommand, strCmd);
1303 std::string warning =
1304 std::string(
"'Warning: Large-work fork detected, forking after "
1311 LogPrintf(
"%s: Warning: Large fork found\n forking the "
1312 "chain at height %d (%s)\n lasting to height %d "
1313 "(%s).\nChain state database corruption likely.\n",
1320 LogPrintf(
"%s: Warning: Found invalid chain at least ~6 blocks "
1321 "longer than our best chain.\nChain state database "
1322 "corruption likely.\n",
1377 m_avalancheFinalizedBlockIndex = pindexNew->
pprev;
1380 LogPrintf(
"%s: invalid block=%s height=%d log2_work=%f date=%s\n",
1387 LogPrintf(
"%s: current best=%s height=%d log2_work=%f date=%s\n",
1399 pindex->nStatus = pindex->nStatus.withFailed();
1450 bool sigCacheStore,
bool scriptCacheStore,
1454 std::vector<CScriptCheck> *pvChecks) {
1459 pvChecks->reserve(tx.
vin.size());
1469 (pBlockLimitSigChecks &&
1472 "too-many-sigchecks");
1477 int nSigChecksTotal = 0;
1479 for (
size_t i = 0; i < tx.
vin.size(); i++) {
1492 &txLimitSigChecks, pBlockLimitSigChecks);
1496 pvChecks->push_back(std::move(check));
1506 uint32_t mandatoryFlags =
1508 if (
flags != mandatoryFlags) {
1515 sigCacheStore, txdata);
1519 strprintf(
"non-mandatory-script-verify-flag (%s)",
1535 strprintf(
"mandatory-script-verify-flag-failed (%s)",
1542 nSigChecksOut = nSigChecksTotal;
1544 if (scriptCacheStore && !pvChecks) {
1556 return state.
Error(strMessage);
1592 view.
AddCoin(out, std::move(undo), !fClean);
1607 error(
"DisconnectBlock(): failure reading undo data");
1619 if (blockUndo.
vtxundo.size() + 1 != block.
vtx.size()) {
1620 error(
"DisconnectBlock(): block and undo data inconsistent");
1625 for (
size_t i = 1; i < block.
vtx.size(); i++) {
1629 error(
"DisconnectBlock(): transaction and undo data inconsistent");
1633 for (
size_t j = 0; j < tx.
vin.size(); j++) {
1645 for (
const auto &ptx : block.
vtx) {
1652 for (
size_t o = 0; o < tx.
vout.size(); o++) {
1653 if (tx.
vout[o].scriptPubKey.IsUnspendable()) {
1659 bool is_spent = view.
SpendCoin(out, &coin);
1793 if (!
CheckBlock(block, state, consensusParams,
1800 return AbortNode(state,
"Corrupt block found indicating potential "
1801 "hardware failure; shutting down");
1803 return error(
"%s: Consensus::CheckBlock: %s", __func__,
1824 bool fScriptChecks =
true;
1833 BlockMap::const_iterator it =
1836 if (it->second.GetAncestor(pindex->
nHeight) == pindex &&
1862 consensusParams) <= 60 * 60 * 24 * 7 * 2);
1884 bool fEnforceBIP30 = !((pindex->
nHeight == 91842 &&
1886 uint256S(
"0x00000000000a4d0a398161ffc163c503763"
1887 "b1f4360639393e0e4c8e300e0caec")) ||
1890 uint256S(
"0x00000000000743f190a18c5577a3c2d2a1f"
1891 "610ae9601ac046a38084ccb7cd721")));
1922 static constexpr
int BIP34_IMPLIES_BIP30_LIMIT = 1983702;
1959 (!pindexBIP34height ||
1965 if (fEnforceBIP30 || pindex->
nHeight >= BIP34_IMPLIES_BIP30_LIMIT) {
1966 for (
const auto &tx : block.
vtx) {
1967 for (
size_t o = 0; o < tx->
vout.size(); o++) {
1969 LogPrintf(
"ERROR: ConnectBlock(): tried to overwrite "
1979 int nLockTimeFlags = 0;
1985 const uint32_t
flags =
1994 std::vector<int> prevheights;
2006 std::vector<TxSigCheckLimiter> nSigChecksTxLimiters;
2007 nSigChecksTxLimiters.resize(block.
vtx.size() - 1);
2010 blockundo.
vtxundo.resize(block.
vtx.size() - 1);
2017 for (
const auto &ptx : block.
vtx) {
2020 }
catch (
const std::logic_error &e) {
2029 LogPrintf(
"ERROR: ConnectBlock(): tried to overwrite transaction\n");
2038 for (
const auto &ptx : block.
vtx) {
2041 nInputs += tx.
vin.size();
2055 return error(
"%s: Consensus::CheckTxInputs: %s, %s", __func__,
2062 LogPrintf(
"ERROR: %s: accumulated fee in the block out of range.\n",
2065 "bad-txns-accumulated-fee-outofrange");
2076 prevheights.resize(tx.
vin.size());
2077 for (
size_t j = 0; j < tx.
vin.size(); j++) {
2081 if (!
SequenceLocks(tx, nLockTimeFlags, prevheights, *pindex)) {
2082 LogPrintf(
"ERROR: %s: contains a non-BIP68-final transaction\n",
2085 "bad-txns-nonfinal");
2090 bool fCacheResults = fJustCheck;
2093 if (!fEnforceSigCheck) {
2100 std::vector<CScriptCheck> vChecks;
2102 if (fScriptChecks &&
2105 nSigChecksRet, nSigChecksTxLimiters[txIndex],
2106 &nSigChecksBlockLimiter, &vChecks)) {
2113 "ConnectBlock(): CheckInputScripts on %s failed with %s",
2117 control.
Add(vChecks);
2131 " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) "
2132 "[%.2fs (%.2fms/blk)]\n",
2133 (
unsigned)block.
vtx.size(),
MILLI * (nTime3 - nTime2),
2134 MILLI * (nTime3 - nTime2) / block.
vtx.size(),
2135 nInputs <= 1 ? 0 :
MILLI * (nTime3 - nTime2) / (nInputs - 1),
2138 const Amount blockReward =
2140 if (block.
vtx[0]->GetValueOut() > blockReward) {
2141 LogPrintf(
"ERROR: ConnectBlock(): coinbase pays too much (actual=%d vs "
2143 block.
vtx[0]->GetValueOut(), blockReward);
2148 const std::vector<CTxDestination> whitelist =
2150 if (!whitelist.empty()) {
2153 for (
auto &o : block.
vtx[0]->vout) {
2154 if (o.nValue < required) {
2165 if (std::find(whitelist.begin(), whitelist.end(), address) !=
2167 goto MinerFundSuccess;
2173 "bad-cb-minerfund");
2178 if (!control.
Wait()) {
2180 "blk-bad-inputs",
"parallel script check failed");
2187 " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs (%.2fms/blk)]\n",
2188 nInputs - 1,
MILLI * (nTime4 - nTime2),
2189 nInputs <= 1 ? 0 :
MILLI * (nTime4 - nTime2) / (nInputs - 1),
2215 TRACE6(validation, block_connected, block_hash.data(), pindex->
nHeight,
2216 block.
vtx.size(), nInputs, nSigChecksRet,
2218 nTime5 - nTimeStart);
2225 return this->GetCoinsCacheSizeState(
2231 CChainState::GetCoinsCacheSizeState(
size_t max_coins_cache_size_bytes,
2232 size_t max_mempool_size_bytes) {
2236 int64_t nTotalSpace =
2237 max_coins_cache_size_bytes +
2238 std::max<int64_t>(int64_t(max_mempool_size_bytes) - nMempoolUsage, 0);
2241 static constexpr int64_t MAX_BLOCK_COINSDB_USAGE_BYTES =
2243 int64_t large_threshold = std::max(
2244 (9 * nTotalSpace) / 10, nTotalSpace - MAX_BLOCK_COINSDB_USAGE_BYTES);
2246 if (cacheSize > nTotalSpace) {
2247 LogPrintf(
"Cache size (%s) exceeds total space (%s)\n", cacheSize,
2250 }
else if (cacheSize > large_threshold) {
2258 int nManualPruneHeight) {
2260 assert(this->CanFlushToDisk());
2261 static std::chrono::microseconds nLastWrite{0};
2262 static std::chrono::microseconds nLastFlush{0};
2263 std::set<int> setFilesToPrune;
2264 bool full_flush_completed =
false;
2271 bool fFlushForPrune =
false;
2272 bool fDoFullFlush =
false;
2283 last_prune = std::max(
2284 1, std::min(last_prune,
2288 if (nManualPruneHeight > 0) {
2293 std::min(last_prune, nManualPruneHeight),
2303 if (!setFilesToPrune.empty()) {
2304 fFlushForPrune =
true;
2307 "prunedblockfiles",
true);
2312 const auto nNow = GetTime<std::chrono::microseconds>();
2314 if (nLastWrite.count() == 0) {
2317 if (nLastFlush.count() == 0) {
2337 fCacheCritical || fPeriodicFlush || fFlushForPrune;
2339 if (fDoFullFlush || fPeriodicWrite) {
2342 return AbortNode(state,
"Disk space is too low!",
2343 _(
"Disk space is too low!"));
2362 state,
"Failed to write to block index database");
2367 if (fFlushForPrune) {
2377 if (fDoFullFlush && !
CoinsTip().GetBestBlock().IsNull()) {
2379 strprintf(
"write coins cache to disk (%d coins, %.2fkB)",
2380 coins_count, coins_mem_usage / 1000),
2390 48 * 2 * 2 *
CoinsTip().GetCacheSize())) {
2391 return AbortNode(state,
"Disk space is too low!",
2392 _(
"Disk space is too low!"));
2398 return AbortNode(state,
"Failed to write to coin database");
2401 full_flush_completed =
true;
2406 GetTimeMicros() - nNow.count(), uint32_t(mode), coins_count,
2407 uint64_t(coins_mem_usage), fFlushForPrune);
2410 if (full_flush_completed) {
2414 }
catch (
const std::runtime_error &e) {
2415 return AbortNode(state, std::string(
"System error while flushing: ") +
2424 LogPrintf(
"%s: failed to flush state (%s)\n", __func__,
2433 LogPrintf(
"%s: failed to flush state (%s)\n", __func__,
2440 const std::string &func_name,
2441 const std::string &
prefix)
2444 LogPrintf(
"%s%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%ld "
2445 "date='%s' progress=%f cache=%.1fMiB(%utxo)\n",
2446 prefix, func_name, tip->GetBlockHash().ToString(), tip->nHeight,
2447 tip->nVersion, log(tip->nChainWork.getdouble()) / log(2.0),
2448 tip->GetChainTxCount(),
2451 coins_tip.DynamicMemoryUsage() * (1.0 / (1 << 20)),
2452 coins_tip.GetCacheSize());
2455 void CChainState::UpdateTip(
const CBlockIndex *pindexNew) {
2457 const auto &coins_tip =
CoinsTip();
2464 constexpr
int BACKGROUND_LOG_INTERVAL = 2000;
2465 if (pindexNew->
nHeight % BACKGROUND_LOG_INTERVAL == 0) {
2467 "[background validation] ");
2510 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
2513 return error(
"DisconnectTip(): Failed to read block");
2521 if (DisconnectBlock(block, pindexDelete, view) !=
2523 return error(
"DisconnectTip(): DisconnectBlock %s failed",
2527 bool flushed = view.
Flush();
2543 if (pindexDelete->
pprev !=
nullptr &&
2547 "Disconnecting mempool due to rewind of upgrade block\n");
2548 if (disconnectpool) {
2554 if (disconnectpool) {
2561 UpdateTip(pindexDelete->
pprev);
2595 std::shared_ptr<const CBlock> pblock) {
2626 const std::shared_ptr<const CBlock> &pblock,
2639 std::shared_ptr<const CBlock> pthisBlock;
2641 std::shared_ptr<CBlock> pblockNew = std::make_shared<CBlock>();
2643 return AbortNode(state,
"Failed to read block");
2645 pthisBlock = pblockNew;
2647 pthisBlock = pblock;
2650 const CBlock &blockConnecting = *pthisBlock;
2660 bool rv =
ConnectBlock(blockConnecting, state, pindexNew, view,
2668 return error(
"%s: ConnectBlock %s failed, %s", __func__,
2677 " - Connect total: %.2fms [%.2fs (%.2fms/blk)]\n",
2680 bool flushed = view.
Flush();
2698 " - Writing chainstate: %.2fms [%.2fs (%.2fms/blk)]\n",
2710 if (pindexNew->
pprev !=
nullptr &&
2715 "Disconnecting mempool due to acceptance of upgrade block\n");
2722 UpdateTip(pindexNew);
2728 " - Connect postprocess: %.2fms [%.2fs (%.2fms/blk)]\n",
2744 std::vector<const CBlockIndex *> &blocksToReconcile) {
2751 std::set<CBlockIndex *, CBlockIndexWorkComparator>::reverse_iterator
2763 if (m_avalancheFinalizedBlockIndex &&
2765 LogPrintf(
"Park block %s because it forks prior to the "
2766 "avalanche finalized chaintip.\n",
2768 pindexNew->nStatus = pindexNew->nStatus.withParked();
2774 const bool fAutoUnpark =
2783 bool hasValidAncestor =
true;
2784 while (hasValidAncestor && pindexTest && pindexTest != pindexFork) {
2789 bool fParkedChain = pindexTest->nStatus.isOnParkedChain();
2790 if (fAutoUnpark && fParkedChain) {
2796 if (!pindexTip || !pindexFork) {
2810 pindexExtraPow = pindexExtraPow->
pprev;
2815 requiredWork += (deltaWork >> 1);
2826 LogPrintf(
"Unpark chain up to block %s as it has "
2827 "accumulated enough PoW.\n",
2829 fParkedChain =
false;
2838 bool fInvalidChain = pindexTest->nStatus.isInvalid();
2839 bool fMissingData = !pindexTest->nStatus.hasData();
2840 if (!(fInvalidChain || fParkedChain || fMissingData)) {
2843 pindexTest = pindexTest->
pprev;
2849 hasValidAncestor =
false;
2852 if (fInvalidChain && (
m_chainman.m_best_invalid ==
nullptr ||
2858 if (fParkedChain && (
m_chainman.m_best_parked ==
nullptr ||
2864 LogPrintf(
"Considered switching to better tip %s but that chain "
2865 "contains a%s%s%s block.\n",
2867 fInvalidChain ?
"n invalid" :
"",
2868 fParkedChain ?
" parked" :
"",
2869 fMissingData ?
" missing-data" :
"");
2873 while (pindexTest != pindexFailed) {
2874 if (fInvalidChain || fParkedChain) {
2875 pindexFailed->nStatus =
2876 pindexFailed->nStatus.withFailedParent(fInvalidChain)
2877 .withParkedParent(fParkedChain);
2878 }
else if (fMissingData) {
2884 std::make_pair(pindexFailed->
pprev, pindexFailed));
2887 pindexFailed = pindexFailed->
pprev;
2890 if (fInvalidChain || fParkedChain) {
2898 blocksToReconcile.push_back(pindexNew);
2902 if (hasValidAncestor) {
2935 CBlockIndex *pindexMostWork,
const std::shared_ptr<const CBlock> &pblock,
2946 bool fBlocksDisconnected =
false;
2961 "Failed to disconnect block; see debug.log for details");
2965 fBlocksDisconnected =
true;
2969 std::vector<CBlockIndex *> vpindexToConnect;
2970 bool fContinue =
true;
2975 int nTargetHeight = std::min(
nHeight + 32, pindexMostWork->
nHeight);
2976 vpindexToConnect.clear();
2977 vpindexToConnect.reserve(nTargetHeight -
nHeight);
2980 vpindexToConnect.push_back(pindexIter);
2981 pindexIter = pindexIter->
pprev;
2988 if (!
ConnectTip(config, state, pindexConnect,
2989 pindexConnect == pindexMostWork
2991 : std::shared_ptr<const CBlock>(),
2992 connectTrace, disconnectpool)) {
3000 fInvalidFound =
true;
3015 if (!pindexOldTip ||
3027 if (fBlocksDisconnected || !disconnectpool.
isEmpty()) {
3033 "Updating mempool due to reorganization or "
3034 "rules upgrade/downgrade\n");
3043 if (fInvalidFound) {
3063 bool fNotify =
false;
3064 bool fInitialBlockDownload =
false;
3069 pindexHeader = chainstate.m_chainman.m_best_header;
3071 if (pindexHeader != pindexHeaderOld) {
3073 fInitialBlockDownload = chainstate.IsInitialBlockDownload();
3074 pindexHeaderOld = pindexHeader;
3096 std::shared_ptr<const CBlock> pblock) {
3125 std::vector<const CBlockIndex *> blocksToReconcile;
3126 bool blocks_connected =
false;
3142 if (pindexMostWork ==
nullptr) {
3147 if (pindexMostWork ==
nullptr ||
3152 bool fInvalidFound =
false;
3153 std::shared_ptr<const CBlock> nullBlockPtr;
3155 config, state, pindexMostWork,
3156 pblock && pblock->GetHash() ==
3160 fInvalidFound, connectTrace)) {
3164 blocks_connected =
true;
3166 if (fInvalidFound) {
3168 pindexMostWork =
nullptr;
3174 assert(trace.pblock && trace.pindex);
3187 if (blocks_connected) {
3194 if (pindexFork != pindexNewTip) {
3209 for (
const CBlockIndex *pindex : blocksToReconcile) {
3213 if (!blocks_connected) {
3217 if (nStopAtHeight && pindexNewTip &&
3218 pindexNewTip->
nHeight >= nStopAtHeight) {
3230 }
while (pindexNewTip != pindexMostWork);
3290 bool pindex_was_in_chain =
false;
3291 int disconnected = 0;
3307 std::multimap<const arith_uint256, CBlockIndex *> candidate_blocks_by_work;
3311 for (
auto &entry :
m_blockman.m_block_index) {
3322 candidate_blocks_by_work.insert(
3323 std::make_pair(candidate->
nChainWork, candidate));
3347 pindex_was_in_chain =
true;
3365 (++disconnected <= 10) && ret,
3381 invalid_walk_tip->nStatus =
3382 invalidate ? invalid_walk_tip->nStatus.withFailed()
3383 : invalid_walk_tip->nStatus.withParked();
3388 if (invalid_walk_tip == to_mark_failed_or_parked->
pprev &&
3389 (invalidate ? to_mark_failed_or_parked->nStatus.hasFailed()
3390 : to_mark_failed_or_parked->nStatus.isParked())) {
3394 to_mark_failed_or_parked->nStatus =
3396 ? to_mark_failed_or_parked->nStatus.withFailed(
false)
3398 : to_mark_failed_or_parked->nStatus.withParked(
false)
3399 .withParkedParent());
3405 auto candidate_it = candidate_blocks_by_work.lower_bound(
3407 while (candidate_it != candidate_blocks_by_work.end()) {
3409 invalid_walk_tip->
pprev)) {
3411 candidate_it = candidate_blocks_by_work.erase(candidate_it);
3420 to_mark_failed_or_parked = invalid_walk_tip;
3435 to_mark_failed_or_parked->nStatus =
3436 invalidate ? to_mark_failed_or_parked->nStatus.withFailed()
3437 : to_mark_failed_or_parked->nStatus.withParked();
3450 for (
auto &[
_, block_index] :
m_blockman.m_block_index) {
3452 block_index.HaveTxsDownloaded() &&
3465 if (pindex_was_in_chain) {
3468 to_mark_failed_or_parked->
pprev);
3494 template <
typename F>
3498 if (pindex->nStatus != newStatus &&
3501 pindex->nStatus = newStatus;
3517 template <
typename F,
typename C,
typename AC>
3519 F f, C fChild, AC fAncestorWasChanged) {
3525 for (
auto pindexAncestor = pindex; pindexAncestor !=
nullptr;
3526 pindexAncestor = pindexAncestor->
pprev) {
3528 pindexDeepestChanged = pindexAncestor;
3534 pindexDeepestChanged) {
3536 pindexReset =
nullptr;
3540 for (
auto &[
_, block_index] :
m_blockman.m_block_index) {
3543 fAncestorWasChanged);
3553 return status.withClearedFailureFlags();
3556 return status.withClearedFailureFlags();
3559 return status.withFailedParent(false);
3569 return status.withClearedParkedFlags();
3572 return fClearChildren ? status.withClearedParkedFlags()
3573 : status.withParkedParent(false);
3576 return status.withParkedParent(false);
3595 "The block to mark finalized by avalanche is not on the "
3596 "active chain: %s\n",
3606 m_avalancheFinalizedBlockIndex = pindex;
3615 m_avalancheFinalizedBlockIndex =
nullptr;
3620 return pindex && m_avalancheFinalizedBlockIndex &&
3632 pindexNew->
nTx = block.
vtx.size();
3634 pindexNew->nFile = pos.
nFile;
3635 pindexNew->nDataPos = pos.
nPos;
3636 pindexNew->nUndoPos = 0;
3637 pindexNew->nStatus = pindexNew->nStatus.withData();
3644 std::deque<CBlockIndex *> queue;
3645 queue.push_back(pindexNew);
3649 while (!queue.empty()) {
3667 std::pair<std::multimap<CBlockIndex *, CBlockIndex *>::iterator,
3668 std::multimap<CBlockIndex *, CBlockIndex *>::iterator>
3670 while (range.first != range.second) {
3671 std::multimap<CBlockIndex *, CBlockIndex *>::iterator it =
3673 queue.push_back(it->second);
3678 }
else if (pindexNew->
pprev &&
3681 std::make_pair(pindexNew->
pprev, pindexNew));
3701 "high-hash",
"proof of work failed");
3727 "bad-txnmrklroot",
"hashMerkleRoot mismatch");
3735 "bad-txns-duplicate",
"duplicate transaction");
3744 if (block.
vtx.empty()) {
3746 "bad-cb-missing",
"first tx is not coinbase");
3755 "bad-blk-length",
"size limits failed");
3759 if (currentBlockSize > nMaxBlockSize) {
3761 "bad-blk-length",
"size limits failed");
3769 strprintf(
"Coinbase check failed (txid %s) %s",
3770 block.
vtx[0]->GetId().ToString(),
3776 for (
size_t i = 1; i < block.
vtx.size(); i++) {
3777 auto *tx = block.
vtx[i].get();
3782 strprintf(
"Transaction check failed (txid %s) %s",
3809 const CBlockIndex *pindexPrev, int64_t nAdjustedTime)
3812 assert(pindexPrev !=
nullptr);
3813 const int nHeight = pindexPrev->nHeight + 1;
3817 LogPrintf(
"bad bits after height: %d\n", pindexPrev->nHeight);
3819 "bad-diffbits",
"incorrect proof of work");
3830 "ERROR: %s: rejected by checkpoint lock-in at %d\n",
3833 "checkpoint mismatch");
3841 blockman.GetLastCheckpoint(checkpoints);
3842 if (pcheckpoint && nHeight < pcheckpoint->
nHeight) {
3844 "ERROR: %s: forked chain older than last checkpoint "
3848 "bad-fork-prior-to-checkpoint");
3853 if (block.
GetBlockTime() <= pindexPrev->GetMedianTimePast()) {
3855 "time-too-old",
"block's timestamp is too early");
3862 "block timestamp too far in the future");
3890 assert(active_chain_tip);
3899 const int nBlockHeight = active_chain_tip->
nHeight + 1;
3923 const int nHeight = pindexPrev ==
nullptr ? 0 : pindexPrev->
nHeight + 1;
3926 int nLockTimeFlags = 0;
3928 assert(pindexPrev !=
nullptr);
3932 const int64_t nMedianTimePast =
3939 const bool fIsMagneticAnomalyEnabled =
3947 for (
const auto &ptx : block.
vtx) {
3949 if (fIsMagneticAnomalyEnabled) {
3950 if (prevTx && (tx.
GetId() <= prevTx->
GetId())) {
3960 strprintf(
"Transaction order is invalid (%s < %s)",
3983 if (block.
vtx[0]->vin[0].scriptSig.size() <
expect.size() ||
3985 block.
vtx[0]->vin[0].scriptSig.begin())) {
3988 "block height mismatch in coinbase");
4009 BlockMap::iterator miSelf{
m_blockman.m_block_index.find(hash)};
4011 if (miSelf !=
m_blockman.m_block_index.end()) {
4018 if (pindex->nStatus.isInvalid()) {
4031 "%s: Consensus::CheckBlockHeader: %s, %s\n", __func__,
4037 BlockMap::iterator mi{
4041 "header %s has prev block not found: %s\n",
4044 "prev-blk-not-found");
4049 if (pindexPrev->nStatus.isInvalid()) {
4051 "header %s has prev block invalid: %s\n", hash.
ToString(),
4060 "%s: Consensus::ContextualCheckBlockHeader: %s, %s\n",
4091 if (pindexPrev->
GetAncestor(failedit->nHeight) == failedit) {
4092 assert(failedit->nStatus.hasFailed());
4094 while (invalid_walk != failedit) {
4095 invalid_walk->nStatus =
4096 invalid_walk->nStatus.withFailedParent();
4098 invalid_walk = invalid_walk->
pprev;
4101 "header %s has prev block invalid: %s\n",
4122 const Config &config,
const std::vector<CBlockHeader> &headers,
4147 const int64_t blocks_left{
4148 (
GetTime() - last_accepted.GetBlockTime()) /
4150 const double progress{100.0 * last_accepted.nHeight /
4151 (last_accepted.nHeight + blocks_left)};
4152 LogPrintf(
"Synchronizing blockheaders, height: %d (~%.2f%%)\n",
4153 last_accepted.nHeight, progress);
4171 const std::shared_ptr<const CBlock> &pblock,
4176 const CBlock &block = *pblock;
4183 bool accepted_header{
4187 if (!accepted_header) {
4194 bool fAlreadyHave = pindex->nStatus.hasData();
4206 int64_t chainTipTimeDiff =
4212 LogPrintf(
"Chain tip timestamp-to-received-time difference: hash=%s, "
4215 LogPrintf(
"New block timestamp-to-received-time difference: hash=%s, "
4220 bool fHasMoreOrSameWork =
4229 bool fTooFarAhead{pindex->
nHeight >
4242 if (pindex->
nTx != 0) {
4247 if (!fHasMoreOrSameWork) {
4267 if (!
CheckBlock(block, state, consensusParams,
4272 pindex->nStatus = pindex->nStatus.withFailed();
4276 return error(
"%s: %s (block %s)", __func__, state.
ToString(),
4289 LogPrintf(
"Park block %s as it would cause a deep reorg.\n",
4291 pindex->nStatus = pindex->nStatus.withParked();
4310 if (blockPos.IsNull()) {
4312 "%s: Failed to find position to write new block to disk",
4317 }
catch (
const std::runtime_error &e) {
4318 return AbortNode(state, std::string(
"System error: ") + e.what());
4329 const Config &config,
const std::shared_ptr<const CBlock> &block,
4330 bool force_processing,
bool *new_block) {
4360 config, block, state, force_processing,
nullptr, new_block);
4365 return error(
"%s: AcceptBlock FAILED (%s)", __func__,
4375 return error(
"%s: ActivateBestChain failed (%s)", __func__,
4398 false, test_accept);
4413 indexDummy.
pprev = pindexPrev;
4420 return error(
"%s: Consensus::ContextualCheckBlockHeader: %s", __func__,
4425 return error(
"%s: Consensus::CheckBlock: %s", __func__,
4431 return error(
"%s: Consensus::ContextualCheckBlock: %s", __func__,
4435 if (!chainstate.
ConnectBlock(block, state, &indexDummy, viewNew,
4436 validationOptions,
true)) {
4446 int nManualPruneHeight) {
4449 nManualPruneHeight)) {
4450 LogPrintf(
"%s: failed to flush state (%s)\n", __func__,
4487 "Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n",
4495 uiInterface.ShowProgress(
_(
"Verifying blocks...").translated, 0,
false);
4516 if (nCheckDepth <= 0 || nCheckDepth > chainstate.
m_chain.
Height()) {
4520 nCheckLevel = std::max(0, std::min(4, nCheckLevel));
4521 LogPrintf(
"Verifying last %i blocks at level %i\n", nCheckDepth,
4527 int nGoodTransactions = 0;
4535 pindex = pindex->
pprev) {
4536 const int percentageDone = std::max(
4537 1, std::min(99, (
int)(((
double)(chainstate.
m_chain.
Height() -
4539 (
double)nCheckDepth *
4540 (nCheckLevel >= 4 ? 50 : 100))));
4541 if (reportDone < percentageDone / 10) {
4544 reportDone = percentageDone / 10;
4547 uiInterface.ShowProgress(
_(
"Verifying blocks...").translated,
4548 percentageDone,
false);
4553 if ((
fPruneMode || is_snapshot_cs) && !pindex->nStatus.hasData()) {
4556 LogPrintf(
"VerifyDB(): block verification stopping at height %d "
4557 "(pruning, no data)\n",
4567 "VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s",
4572 if (nCheckLevel >= 1 && !
CheckBlock(block, state, consensusParams,
4574 return error(
"%s: *** found bad block at %d, hash=%s (%s)\n",
4580 if (nCheckLevel >= 2 && pindex) {
4585 "VerifyDB(): *** found bad undo data at %d, hash=%s\n",
4595 if (nCheckLevel >= 3 &&
4599 chainstate.DisconnectBlock(block, pindex, coins);
4601 return error(
"VerifyDB(): *** irrecoverable inconsistency in "
4602 "block data at %d, hash=%s",
4608 nGoodTransactions = 0;
4609 pindexFailure = pindex;
4611 nGoodTransactions += block.
vtx.size();
4620 if (pindexFailure) {
4621 return error(
"VerifyDB(): *** coin database inconsistencies found "
4622 "(last %i blocks, %i good transactions before that)\n",
4631 if (nCheckLevel >= 4) {
4633 const int percentageDone = std::max(
4634 1, std::min(99, 100 -
int(
double(chainstate.
m_chain.
Height() -
4636 double(nCheckDepth) * 50)));
4637 if (reportDone < percentageDone / 10) {
4640 reportDone = percentageDone / 10;
4642 uiInterface.ShowProgress(
_(
"Verifying blocks...").translated,
4643 percentageDone,
false);
4648 "VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s",
4651 if (!chainstate.
ConnectBlock(block, state, pindex, coins,
4653 return error(
"VerifyDB(): *** found unconnectable block at %d, "
4665 LogPrintf(
"No coin database inconsistencies in last %i blocks (%i "
4667 block_count, nGoodTransactions);
4682 return error(
"ReplayBlock(): ReadBlockFromDisk failed at %d, hash=%s",
4692 if (tx->IsCoinBase()) {
4696 for (
const CTxIn &txin : tx->vin) {
4710 std::vector<BlockHash> hashHeads =
db.GetHeadBlocks();
4711 if (hashHeads.empty()) {
4715 if (hashHeads.size() != 2) {
4716 return error(
"ReplayBlocks(): unknown inconsistent state");
4719 uiInterface.ShowProgress(
_(
"Replaying blocks...").translated, 0,
false);
4729 if (
m_blockman.m_block_index.count(hashHeads[0]) == 0) {
4731 "ReplayBlocks(): reorganization to unknown block requested");
4734 pindexNew = &(
m_blockman.m_block_index[hashHeads[0]]);
4736 if (!hashHeads[1].IsNull()) {
4738 if (
m_blockman.m_block_index.count(hashHeads[1]) == 0) {
4740 "ReplayBlocks(): reorganization from unknown block requested");
4743 pindexOld = &(
m_blockman.m_block_index[hashHeads[1]]);
4745 assert(pindexFork !=
nullptr);
4749 while (pindexOld != pindexFork) {
4754 return error(
"RollbackBlock(): ReadBlockFromDisk() failed at "
4765 "RollbackBlock(): DisconnectBlock failed at %d, hash=%s",
4777 pindexOld = pindexOld->
pprev;
4781 int nForkHeight = pindexFork ? pindexFork->
nHeight : 0;
4787 uiInterface.ShowProgress(
_(
"Replaying blocks...").translated,
4788 (
int)((
nHeight - nForkHeight) * 100.0 /
4789 (pindexNew->
nHeight - nForkHeight)),
4822 std::vector<CBlockIndex *> vSortedByHeight{
4824 std::sort(vSortedByHeight.begin(), vSortedByHeight.end(),
4828 int first_assumed_valid_height = std::numeric_limits<int>::max();
4830 for (
const CBlockIndex *block : vSortedByHeight) {
4831 if (block->IsAssumedValid()) {
4832 auto chainstates =
GetAll();
4839 auto any_chain = [&](
auto fnc) {
4840 return std::any_of(chainstates.cbegin(), chainstates.cend(),
4843 assert(any_chain([](
auto chainstate) {
4844 return chainstate->reliesOnAssumedValid();
4846 assert(any_chain([](
auto chainstate) {
4847 return !chainstate->reliesOnAssumedValid();
4850 first_assumed_valid_height = block->nHeight;
4888 if (chainstate->reliesOnAssumedValid() ||
4889 pindex->
nHeight < first_assumed_valid_height) {
4890 chainstate->setBlockIndexCandidates.insert(pindex);
4895 if (pindex->nStatus.isInvalid() &&
4897 pindex->
nChainWork > m_best_invalid->nChainWork)) {
4898 m_best_invalid = pindex;
4901 if (pindex->nStatus.isOnParkedChain() &&
4903 pindex->
nChainWork > m_best_parked->nChainWork)) {
4904 m_best_parked = pindex;
4914 needs_init =
m_blockman.m_block_index.empty();
4924 LogPrintf(
"Initializing databases...\n");
4944 if (blockPos.IsNull()) {
4945 return error(
"%s: writing genesis block to disk failed", __func__);
4950 }
catch (
const std::runtime_error &e) {
4951 return error(
"%s: failed to write genesis block: %s", __func__,
4958 void CChainState::LoadExternalBlockFile(
const Config &config, FILE *fileIn,
4963 static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
4973 uint64_t nRewind = blkdat.GetPos();
4974 while (!blkdat.eof()) {
4979 blkdat.SetPos(nRewind);
4984 unsigned int nSize = 0;
4989 nRewind = blkdat.GetPos() + 1;
5001 }
catch (
const std::exception &) {
5008 uint64_t nBlockPos = blkdat.GetPos();
5010 dbp->
nPos = nBlockPos;
5012 blkdat.SetLimit(nBlockPos + nSize);
5013 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
5016 nRewind = blkdat.GetPos();
5026 "%s: Out of order block %s, parent %s not known\n",
5030 mapBlocksUnknownParent.insert(
5039 if (!pindex || !pindex->nStatus.hasData()) {
5050 pindex->
nHeight % 1000 == 0) {
5053 "Block Import: already had block %s at height %d\n",
5071 std::deque<uint256> queue;
5072 queue.push_back(hash);
5073 while (!queue.empty()) {
5076 std::pair<std::multimap<uint256, FlatFilePos>::iterator,
5077 std::multimap<uint256, FlatFilePos>::iterator>
5078 range = mapBlocksUnknownParent.equal_range(head);
5079 while (range.first != range.second) {
5080 std::multimap<uint256, FlatFilePos>::iterator it =
5082 std::shared_ptr<CBlock> pblockrecursive =
5083 std::make_shared<CBlock>();
5088 "%s: Processing out of order child %s of %s\n",
5089 __func__, pblockrecursive->GetHash().ToString(),
5094 true, &it->second,
nullptr)) {
5096 queue.push_back(pblockrecursive->GetHash());
5100 mapBlocksUnknownParent.erase(it);
5104 }
catch (
const std::exception &e) {
5105 LogPrintf(
"%s: Deserialize or I/O error - %s\n", __func__,
5109 }
catch (
const std::runtime_error &e) {
5110 AbortNode(std::string(
"System error: ") + e.what());
5113 LogPrintf(
"Loaded %i blocks from external file in %dms\n", nLoaded,
5134 std::multimap<CBlockIndex *, CBlockIndex *> forward;
5135 for (
auto &[
_, block_index] :
m_blockman.m_block_index) {
5136 forward.emplace(block_index.pprev, &block_index);
5141 std::pair<std::multimap<CBlockIndex *, CBlockIndex *>::iterator,
5142 std::multimap<CBlockIndex *, CBlockIndex *>::iterator>
5143 rangeGenesis = forward.equal_range(
nullptr);
5145 rangeGenesis.first++;
5147 assert(rangeGenesis.first == rangeGenesis.second);
5167 CBlockIndex *pindexFirstNotTransactionsValid =
nullptr;
5173 CBlockIndex *pindexFirstNotScriptsValid =
nullptr;
5174 while (pindex !=
nullptr) {
5176 if (pindexFirstInvalid ==
nullptr && pindex->nStatus.hasFailed()) {
5177 pindexFirstInvalid = pindex;
5179 if (pindexFirstParked ==
nullptr && pindex->nStatus.isParked()) {
5180 pindexFirstParked = pindex;
5184 if (pindexFirstMissing ==
nullptr && !pindex->nStatus.hasData() &&
5186 pindexFirstMissing = pindex;
5188 if (pindexFirstNeverProcessed ==
nullptr && pindex->
nTx == 0) {
5189 pindexFirstNeverProcessed = pindex;
5191 if (pindex->
pprev !=
nullptr && pindexFirstNotTreeValid ==
nullptr &&
5193 pindexFirstNotTreeValid = pindex;
5196 if (pindexFirstNotTransactionsValid ==
nullptr &&
5198 pindexFirstNotTransactionsValid = pindex;
5200 if (pindexFirstNotChainValid ==
nullptr &&
5202 pindexFirstNotChainValid = pindex;
5204 if (pindexFirstNotScriptsValid ==
nullptr &&
5206 pindexFirstNotScriptsValid = pindex;
5211 if (pindex->
pprev ==
nullptr) {
5232 assert(pindex->nStatus.hasData() == (pindex->
nTx > 0));
5233 assert(pindexFirstMissing == pindexFirstNeverProcessed);
5234 }
else if (pindex->nStatus.hasData()) {
5239 if (pindex->nStatus.hasUndo()) {
5240 assert(pindex->nStatus.hasData());
5251 assert((pindex->nStatus.getValidity() >=
5259 assert((pindexFirstNeverProcessed ==
nullptr) ==
5261 assert((pindexFirstNotTransactionsValid ==
nullptr) ==
5273 assert(pindexFirstNotTreeValid ==
nullptr);
5276 assert(pindexFirstNotTreeValid ==
nullptr);
5280 assert(pindexFirstNotChainValid ==
nullptr);
5284 assert(pindexFirstNotScriptsValid ==
nullptr);
5286 if (pindexFirstInvalid ==
nullptr) {
5289 assert(!pindex->nStatus.isInvalid());
5291 if (pindexFirstParked ==
nullptr) {
5295 assert(!pindex->nStatus.isOnParkedChain());
5298 pindexFirstNeverProcessed ==
nullptr) {
5299 if (pindexFirstInvalid ==
nullptr) {
5308 if (pindexFirstMissing ==
nullptr) {
5309 assert(pindex->nStatus.isOnParkedChain() ||
5330 std::pair<std::multimap<CBlockIndex *, CBlockIndex *>::iterator,
5331 std::multimap<CBlockIndex *, CBlockIndex *>::iterator>
5334 bool foundInUnlinked =
false;
5335 while (rangeUnlinked.first != rangeUnlinked.second) {
5336 assert(rangeUnlinked.first->first == pindex->
pprev);
5337 if (rangeUnlinked.first->second == pindex) {
5338 foundInUnlinked =
true;
5341 rangeUnlinked.first++;
5343 if (pindex->
pprev && pindex->nStatus.hasData() &&
5344 pindexFirstNeverProcessed !=
nullptr &&
5345 pindexFirstInvalid ==
nullptr) {
5351 if (!pindex->nStatus.hasData()) {
5353 assert(!foundInUnlinked);
5355 if (pindexFirstMissing ==
nullptr) {
5358 assert(!foundInUnlinked);
5360 if (pindex->
pprev && pindex->nStatus.hasData() &&
5361 pindexFirstNeverProcessed ==
nullptr &&
5362 pindexFirstMissing !=
nullptr) {
5378 if (pindexFirstInvalid ==
nullptr) {
5388 std::pair<std::multimap<CBlockIndex *, CBlockIndex *>::iterator,
5389 std::multimap<CBlockIndex *, CBlockIndex *>::iterator>
5390 range = forward.equal_range(pindex);
5391 if (range.first != range.second) {
5393 pindex = range.first->second;
5403 if (pindex == pindexFirstInvalid) {
5404 pindexFirstInvalid =
nullptr;
5406 if (pindex == pindexFirstParked) {
5407 pindexFirstParked =
nullptr;
5409 if (pindex == pindexFirstMissing) {
5410 pindexFirstMissing =
nullptr;
5412 if (pindex == pindexFirstNeverProcessed) {
5413 pindexFirstNeverProcessed =
nullptr;
5415 if (pindex == pindexFirstNotTreeValid) {
5416 pindexFirstNotTreeValid =
nullptr;
5418 if (pindex == pindexFirstNotTransactionsValid) {
5419 pindexFirstNotTransactionsValid =
nullptr;
5421 if (pindex == pindexFirstNotChainValid) {
5422 pindexFirstNotChainValid =
nullptr;
5424 if (pindex == pindexFirstNotScriptsValid) {
5425 pindexFirstNotScriptsValid =
nullptr;
5430 std::pair<std::multimap<CBlockIndex *, CBlockIndex *>::iterator,
5431 std::multimap<CBlockIndex *, CBlockIndex *>::iterator>
5432 rangePar = forward.equal_range(pindexPar);
5433 while (rangePar.first->second != pindex) {
5436 assert(rangePar.first != rangePar.second);
5441 if (rangePar.first != rangePar.second) {
5443 pindex = rangePar.first->second;
5455 assert(nNodes == forward.size());
5461 return strprintf(
"Chainstate [%s] @ height %d (%s)",
5467 bool CChainState::ResizeCoinsCaches(
size_t coinstip_size,
size_t coinsdb_size) {
5480 coinsdb_size * (1.0 / 1024 / 1024));
5482 coinstip_size * (1.0 / 1024 / 1024));
5487 if (coinstip_size > old_coinstip_size) {
5503 int64_t nExpiryTimeout =
5510 "Failed to open mempool file from disk. Continuing anyway.\n");
5515 int64_t expired = 0;
5517 int64_t already_there = 0;
5518 int64_t unbroadcast = 0;
5543 if (nTime > nNow - nExpiryTimeout) {
5545 const auto &accepted =
5549 if (accepted.m_result_type ==
5557 if (pool.
exists(tx->GetId())) {
5571 std::map<TxId, Amount> mapDeltas;
5574 for (
const auto &i : mapDeltas) {
5578 std::set<TxId> unbroadcast_txids;
5579 file >> unbroadcast_txids;
5580 unbroadcast = unbroadcast_txids.size();
5581 for (
const auto &txid : unbroadcast_txids) {
5584 if (pool.
get(txid) !=
nullptr) {
5588 }
catch (
const std::exception &e) {
5589 LogPrintf(
"Failed to deserialize mempool data on disk: %s. Continuing "
5595 LogPrintf(
"Imported mempool transactions from disk: %i succeeded, %i "
5596 "failed, %i expired, %i already there, %i waiting for initial "
5598 count, failed, expired, already_there, unbroadcast);