92 #define MICRO 0.000001
100 "level 0 reads the blocks from disk",
101 "level 1 verifies block validity",
102 "level 2 verifies undo data",
103 "level 3 checks disconnection of tip blocks",
104 "level 4 tries to reconnect the blocks",
105 "each level includes the checks of the previous levels",
113 : excessiveBlockSize(config.GetMaxBlockSize()), checkPoW(true),
114 checkMerkleRoot(true) {}
141 bool useExistingLockPoints) {
153 std::pair<int, int64_t> lockPair;
154 if (useExistingLockPoints) {
157 lockPair.second =
lp->
time;
159 std::vector<int> prevheights;
160 prevheights.resize(tx.
vin.size());
161 for (
size_t txinIndex = 0; txinIndex < tx.
vin.size(); txinIndex++) {
162 const CTxIn &txin = tx.
vin[txinIndex];
165 return error(
"%s: Missing input", __func__);
169 prevheights[txinIndex] = tip->
nHeight + 1;
171 prevheights[txinIndex] = coin.
GetHeight();
178 lp->
time = lockPair.second;
189 int64_t nMedianTimePast) {
190 return nMedianTimePast >=
gArgs.
GetIntArg(
"-replayprotectionactivationtime",
196 if (pindexPrev ==
nullptr) {
237 const Coin &coinFromUTXOSet = coins_tip.AccessCoin(txin.
prevout);
246 true, txdata, nSigChecksOut);
251 class MemPoolAccept {
254 : m_pool(mempool), m_view(&m_dummy),
255 m_viewmempool(&active_chainstate.CoinsTip(), m_pool),
256 m_active_chainstate(active_chainstate) {}
262 const int64_t m_accept_time;
263 const bool m_bypass_limits;
271 std::vector<COutPoint> &m_coins_to_uncache;
272 const bool m_test_accept;
273 const unsigned int m_heightOverride;
279 const bool m_package_submission;
282 static ATMPArgs SingleAccept(
const Config &config, int64_t accept_time,
284 std::vector<COutPoint> &coins_to_uncache,
286 unsigned int heightOverride) {
287 return ATMPArgs{config,
301 PackageTestAccept(
const Config &config, int64_t accept_time,
302 std::vector<COutPoint> &coins_to_uncache) {
303 return ATMPArgs{config, accept_time,
304 false, coins_to_uncache,
313 PackageChildWithParents(
const Config &config, int64_t accept_time,
314 std::vector<COutPoint> &coins_to_uncache) {
315 return ATMPArgs{config,
328 ATMPArgs(
const Config &config, int64_t accept_time,
bool bypass_limits,
329 std::vector<COutPoint> &coins_to_uncache,
bool test_accept,
330 unsigned int height_override,
bool package_submission)
331 : m_config{config}, m_accept_time{accept_time},
332 m_bypass_limits{bypass_limits},
333 m_coins_to_uncache{coins_to_uncache}, m_test_accept{test_accept},
334 m_heightOverride{height_override}, m_package_submission{
335 package_submission} {}
350 AcceptMultipleTransactions(
const std::vector<CTransactionRef> &txns,
368 const uint32_t next_block_script_verify_flags)
370 m_next_block_script_verify_flags(next_block_script_verify_flags) {
377 std::unique_ptr<CTxMemPoolEntry> m_entry;
407 const uint32_t m_next_block_script_verify_flags;
408 int m_sig_checks_standard;
416 bool PreChecks(ATMPArgs &args, Workspace &ws)
423 bool ConsensusScriptChecks(
const ATMPArgs &args, Workspace &ws)
429 bool Finalize(
const ATMPArgs &args, Workspace &ws)
438 bool SubmitPackage(
const ATMPArgs &args, std::vector<Workspace> &workspaces,
440 std::map<const TxId, const MempoolAcceptResult> &results)
452 bool MemPoolAccept::PreChecks(ATMPArgs &args, Workspace &ws) {
457 const TxId &txid = ws.m_ptx->GetId();
460 const int64_t nAcceptTime = args.m_accept_time;
461 const bool bypass_limits = args.m_bypass_limits;
462 std::vector<COutPoint> &coins_to_uncache = args.m_coins_to_uncache;
463 const unsigned int heightOverride = args.m_heightOverride;
475 if (m_pool.m_require_standard &&
477 m_pool.m_permit_bare_multisig,
478 m_pool.m_dust_relay_feerate, reason)) {
487 m_active_chainstate.m_chain.Tip(),
488 args.m_config.GetChainParams().GetConsensus(), tx, ctxState)) {
497 if (m_pool.exists(txid)) {
499 "txn-already-in-mempool");
505 if (ptxConflicting) {
508 "txn-mempool-conflict");
513 m_view.SetBackend(m_viewmempool);
519 coins_to_uncache.push_back(txin.
prevout);
526 if (!m_view.HaveCoin(txin.
prevout)) {
528 for (
size_t out = 0; out < tx.
vout.size(); out++) {
533 "txn-already-known");
540 "bad-txns-inputs-missingorspent");
545 if (!m_view.HaveInputs(tx)) {
547 "bad-txns-inputs-spent");
551 m_view.GetBestBlock();
556 m_view.SetBackend(m_dummy);
558 assert(m_active_chainstate.m_blockman.LookupBlockIndex(
559 m_view.GetBestBlock()) == m_active_chainstate.m_chain.Tip());
576 m_active_chainstate.m_chain.Height() + 1,
583 if (m_pool.m_require_standard &&
586 "bad-txns-nonstandard-inputs");
590 ws.m_modified_fees = ws.m_base_fees;
591 m_pool.ApplyDelta(txid, ws.m_modified_fees);
599 if (!bypass_limits &&
600 ws.m_modified_fees < m_pool.m_min_relay_feerate.GetFee(nSize)) {
604 m_pool.m_min_relay_feerate.GetFee(nSize)));
608 const uint32_t scriptVerifyFlags =
612 ws.m_precomputed_txdata, ws.m_sig_checks_standard)) {
617 ws.m_entry = std::make_unique<CTxMemPoolEntry>(
618 ptx, ws.m_base_fees, nAcceptTime,
619 heightOverride ? heightOverride : m_active_chainstate.m_chain.Height(),
620 ws.m_sig_checks_standard,
lp);
622 ws.m_vsize = ws.m_entry->GetTxVirtualSize();
624 Amount mempoolRejectFee = m_pool.GetMinFee().GetFee(ws.m_vsize);
625 if (!bypass_limits && mempoolRejectFee >
Amount::zero() &&
626 ws.m_modified_fees < mempoolRejectFee) {
629 strprintf(
"%d < %d", ws.m_modified_fees, mempoolRejectFee));
635 bool MemPoolAccept::ConsensusScriptChecks(
const ATMPArgs &args, Workspace &ws) {
653 int nSigChecksConsensus;
655 tx, state, m_view, m_pool, ws.m_next_block_script_verify_flags,
656 ws.m_precomputed_txdata, nSigChecksConsensus,
657 m_active_chainstate.CoinsTip())) {
661 LogPrintf(
"BUG! PLEASE REPORT THIS! CheckInputScripts failed against "
662 "latest-block but not STANDARD flags %s, %s\n",
667 if (ws.m_sig_checks_standard != nSigChecksConsensus) {
672 "%s: BUG! PLEASE REPORT THIS! SigChecks count differed between "
673 "standard and consensus flags in %s",
679 bool MemPoolAccept::Finalize(
const ATMPArgs &args, Workspace &ws) {
682 const TxId &txid = ws.m_ptx->GetId();
684 const bool bypass_limits = args.m_bypass_limits;
689 m_pool.addUnchecked(entry);
696 if (!args.m_package_submission && !bypass_limits) {
697 m_pool.LimitSize(m_active_chainstate.CoinsTip());
698 if (!m_pool.exists(txid)) {
709 std::vector<Coin> spent_coins;
710 spent_coins.reserve(ptx->vin.size());
711 for (
const CTxIn &input : ptx->vin) {
715 spent_coins.push_back(std::move(coin));
720 bool MemPoolAccept::SubmitPackage(
721 const ATMPArgs &args, std::vector<Workspace> &workspaces,
723 std::map<const TxId, const MempoolAcceptResult> &results) {
728 workspaces.cbegin(), workspaces.cend(),
729 [
this](
const auto &ws) { return !m_pool.exists(ws.m_ptx->GetId()); }));
731 bool all_submitted =
true;
738 for (Workspace &ws : workspaces) {
739 if (!ConsensusScriptChecks(args, ws)) {
740 results.emplace(ws.m_ptx->GetId(),
743 all_submitted =
Assume(
false);
753 if (!Finalize(args, ws)) {
754 results.emplace(ws.m_ptx->GetId(),
757 all_submitted =
Assume(
false);
763 m_pool.LimitSize(m_active_chainstate.CoinsTip());
764 if (!all_submitted) {
771 for (Workspace &ws : workspaces) {
772 if (m_pool.exists(ws.m_ptx->GetId())) {
774 ws.m_vsize, ws.m_base_fees));
777 std::make_shared<
const std::vector<Coin>>(
778 getSpentCoins(ws.m_ptx, m_view)),
779 m_pool.GetAndIncrementSequence());
781 all_submitted =
false;
784 results.emplace(ws.m_ptx->GetId(),
788 return all_submitted;
799 const CBlockIndex *tip = m_active_chainstate.m_chain.Tip();
807 if (!PreChecks(args, ws)) {
811 if (!ConsensusScriptChecks(args, ws)) {
815 const TxId txid = ptx->GetId();
825 if (
auto it = m_pool.mapNextTx.lower_bound(
COutPoint{txid, 0});
826 it != m_pool.mapNextTx.end() && it->first->GetTxId() == txid) {
827 LogPrintf(
"%s: BUG! PLEASE REPORT THIS! Attempt to add txid %s, but "
828 "its outputs are already spent in the "
832 "txn-child-before-parent");
837 if (args.m_test_accept) {
841 if (!Finalize(args, ws)) {
847 std::make_shared<
const std::vector<Coin>>(getSpentCoins(ptx, m_view)),
848 m_pool.GetAndIncrementSequence());
854 const std::vector<CTransactionRef> &txns, ATMPArgs &args) {
864 std::vector<Workspace> workspaces{};
865 workspaces.reserve(txns.size());
867 txns.cbegin(), txns.cend(), std::back_inserter(workspaces),
868 [
this](
const auto &tx) {
870 tx, GetNextBlockScriptFlags(m_active_chainstate.m_chain.Tip(),
871 m_active_chainstate.m_chainman));
873 std::map<const TxId, const MempoolAcceptResult> results;
879 for (Workspace &ws : workspaces) {
880 if (!PreChecks(args, ws)) {
882 "transaction failed");
885 results.emplace(ws.m_ptx->GetId(),
892 m_viewmempool.PackageAddTransaction(ws.m_ptx);
893 if (args.m_test_accept) {
898 ws.m_vsize, ws.m_base_fees));
902 if (args.m_test_accept) {
906 if (!SubmitPackage(args, workspaces, package_state, results)) {
908 "submission failed");
934 "package-not-child-with-parents");
939 assert(package.size() > 1);
942 const auto &child = package.back();
943 std::unordered_set<TxId, SaltedTxIdHasher> unconfirmed_parent_txids;
945 package.cbegin(), package.cend() - 1,
946 std::inserter(unconfirmed_parent_txids, unconfirmed_parent_txids.end()),
947 [](
const auto &tx) { return tx->GetId(); });
956 const CCoinsViewCache &coins_tip_cache = m_active_chainstate.CoinsTip();
957 for (
const auto &input : child->vin) {
959 args.m_coins_to_uncache.push_back(input.
prevout);
966 m_view.
SetBackend(m_active_chainstate.CoinsTip());
967 const auto package_or_confirmed = [
this, &unconfirmed_parent_txids](
969 return unconfirmed_parent_txids.count(input.
prevout.
GetTxId()) > 0 ||
970 m_view.HaveCoin(input.
prevout);
972 if (!std::all_of(child->vin.cbegin(), child->vin.cend(),
973 package_or_confirmed)) {
975 "package-not-child-with-unconfirmed-parents");
981 m_view.SetBackend(m_dummy);
984 std::map<const TxId, const MempoolAcceptResult> results;
996 std::vector<CTransactionRef> txns_new;
997 for (
const auto &tx : package) {
998 const auto &txid = tx->
GetId();
1001 if (m_pool.exists(txid)) {
1003 auto iter = m_pool.GetIter(txid);
1004 assert(iter != std::nullopt);
1006 (*iter.value())->GetTxSize(),
1007 (*iter.value())->GetFee()));
1010 txns_new.push_back(tx);
1015 if (txns_new.empty()) {
1019 auto submission_result = AcceptMultipleTransactions(txns_new, args);
1021 for (
const auto &[txid, mempoolaccept_res] : results) {
1022 submission_result.m_tx_results.emplace(txid, mempoolaccept_res);
1024 return submission_result;
1030 int64_t accept_time,
bool bypass_limits,
1032 unsigned int heightOverride) {
1037 std::vector<COutPoint> coins_to_uncache;
1038 auto args = MemPoolAccept::ATMPArgs::SingleAccept(
1040 coins_to_uncache, test_accept, heightOverride);
1042 .AcceptSingleTransaction(tx, args);
1050 for (
const COutPoint &outpoint : coins_to_uncache) {
1067 assert(!package.empty());
1068 assert(std::all_of(package.cbegin(), package.cend(),
1069 [](
const auto &tx) { return tx != nullptr; }));
1073 std::vector<COutPoint> coins_to_uncache;
1077 auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(
1078 config,
GetTime(), coins_to_uncache);
1079 return MemPoolAccept(pool, active_chainstate)
1080 .AcceptMultipleTransactions(package, args);
1082 auto args = MemPoolAccept::ATMPArgs::PackageChildWithParents(
1083 config,
GetTime(), coins_to_uncache);
1084 return MemPoolAccept(pool, active_chainstate)
1085 .AcceptPackage(package, args);
1091 if (test_accept || result.m_state.IsInvalid()) {
1092 for (
const COutPoint &hashTx : coins_to_uncache) {
1105 if (halvings >= 64) {
1116 bool in_memory,
bool should_wipe)
1117 : m_dbview(
gArgs.GetDataDirNet() / ldb_name, cache_size_bytes, in_memory,
1119 m_catcherview(&m_dbview) {}
1121 void CoinsViews::InitCache() {
1123 m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview);
1128 std::optional<BlockHash> from_snapshot_blockhash)
1129 : m_mempool(mempool), m_blockman(blockman), m_chainman(chainman),
1130 m_from_snapshot_blockhash(from_snapshot_blockhash) {}
1133 bool should_wipe, std::string leveldb_name) {
1137 m_coins_views = std::make_unique<CoinsViews>(leveldb_name, cache_size_bytes,
1138 in_memory, should_wipe);
1141 void Chainstate::InitCoinsCache(
size_t cache_size_bytes) {
1176 LogPrintf(
"Leaving InitialBlockDownload (latching to false)\n");
1183 #if defined(HAVE_SYSTEM)
1184 std::string strCmd =
gArgs.
GetArg(
"-alertnotify",
"");
1185 if (strCmd.empty()) {
1192 std::string singleQuote(
"'");
1194 safeStatus = singleQuote + safeStatus + singleQuote;
1197 std::thread t(runCommand, strCmd);
1225 std::string warning =
1226 std::string(
"'Warning: Large-work fork detected, forking after "
1233 LogPrintf(
"%s: Warning: Large fork found\n forking the "
1234 "chain at height %d (%s)\n lasting to height %d "
1235 "(%s).\nChain state database corruption likely.\n",
1242 LogPrintf(
"%s: Warning: Found invalid chain at least ~6 blocks "
1243 "longer than our best chain.\nChain state database "
1244 "corruption likely.\n",
1299 m_avalancheFinalizedBlockIndex = pindexNew->
pprev;
1302 LogPrintf(
"%s: invalid block=%s height=%d log2_work=%f date=%s\n",
1309 LogPrintf(
"%s: current best=%s height=%d log2_work=%f date=%s\n",
1321 pindex->nStatus = pindex->nStatus.withFailed();
1372 bool sigCacheStore,
bool scriptCacheStore,
1376 std::vector<CScriptCheck> *pvChecks) {
1381 pvChecks->reserve(tx.
vin.size());
1391 (pBlockLimitSigChecks &&
1394 "too-many-sigchecks");
1399 int nSigChecksTotal = 0;
1401 for (
size_t i = 0; i < tx.
vin.size(); i++) {
1414 &txLimitSigChecks, pBlockLimitSigChecks);
1418 pvChecks->push_back(std::move(check));
1428 uint32_t mandatoryFlags =
1430 if (
flags != mandatoryFlags) {
1437 sigCacheStore, txdata);
1441 strprintf(
"non-mandatory-script-verify-flag (%s)",
1457 strprintf(
"mandatory-script-verify-flag-failed (%s)",
1464 nSigChecksOut = nSigChecksTotal;
1466 if (scriptCacheStore && !pvChecks) {
1478 return state.
Error(strMessage);
1491 if (undo.GetHeight() == 0) {
1514 view.
AddCoin(out, std::move(undo), !fClean);
1529 error(
"DisconnectBlock(): failure reading undo data");
1533 return ApplyBlockUndo(std::move(blockUndo), block, pindex, view);
1541 if (blockUndo.
vtxundo.size() + 1 != block.
vtx.size()) {
1542 error(
"DisconnectBlock(): block and undo data inconsistent");
1547 for (
size_t i = 1; i < block.
vtx.size(); i++) {
1551 error(
"DisconnectBlock(): transaction and undo data inconsistent");
1555 for (
size_t j = 0; j < tx.
vin.size(); j++) {
1568 for (
const auto &ptx : block.
vtx) {
1575 for (
size_t o = 0; o < tx.
vout.size(); o++) {
1576 if (tx.
vout[o].scriptPubKey.IsUnspendable()) {
1582 bool is_spent = view.
SpendCoin(out, &coin);
1719 if (!
CheckBlock(block, state, consensusParams,
1726 return AbortNode(state,
"Corrupt block found indicating potential "
1727 "hardware failure; shutting down");
1729 return error(
"%s: Consensus::CheckBlock: %s", __func__,
1750 bool fScriptChecks =
true;
1759 BlockMap::const_iterator it{
1762 if (it->second.GetAncestor(pindex->
nHeight) == pindex &&
1790 consensusParams) <= 60 * 60 * 24 * 7 * 2);
1812 bool fEnforceBIP30 = !((pindex->
nHeight == 91842 &&
1814 uint256S(
"0x00000000000a4d0a398161ffc163c503763"
1815 "b1f4360639393e0e4c8e300e0caec")) ||
1818 uint256S(
"0x00000000000743f190a18c5577a3c2d2a1f"
1819 "610ae9601ac046a38084ccb7cd721")));
1850 static constexpr
int BIP34_IMPLIES_BIP30_LIMIT = 1983702;
1887 (!pindexBIP34height ||
1893 if (fEnforceBIP30 || pindex->
nHeight >= BIP34_IMPLIES_BIP30_LIMIT) {
1894 for (
const auto &tx : block.
vtx) {
1895 for (
size_t o = 0; o < tx->
vout.size(); o++) {
1897 LogPrintf(
"ERROR: ConnectBlock(): tried to overwrite "
1907 int nLockTimeFlags = 0;
1921 std::vector<int> prevheights;
1933 std::vector<TxSigCheckLimiter> nSigChecksTxLimiters;
1934 nSigChecksTxLimiters.resize(block.
vtx.size() - 1);
1937 blockundo.
vtxundo.resize(block.
vtx.size() - 1);
1944 for (
const auto &ptx : block.
vtx) {
1947 }
catch (
const std::logic_error &e) {
1956 LogPrintf(
"ERROR: ConnectBlock(): tried to overwrite transaction\n");
1965 for (
const auto &ptx : block.
vtx) {
1968 nInputs += tx.
vin.size();
1982 return error(
"%s: Consensus::CheckTxInputs: %s, %s", __func__,
1989 LogPrintf(
"ERROR: %s: accumulated fee in the block out of range.\n",
1992 "bad-txns-accumulated-fee-outofrange");
2003 prevheights.resize(tx.
vin.size());
2004 for (
size_t j = 0; j < tx.
vin.size(); j++) {
2008 if (!
SequenceLocks(tx, nLockTimeFlags, prevheights, *pindex)) {
2009 LogPrintf(
"ERROR: %s: contains a non-BIP68-final transaction\n",
2012 "bad-txns-nonfinal");
2017 bool fCacheResults = fJustCheck;
2020 if (!fEnforceSigCheck) {
2027 std::vector<CScriptCheck> vChecks;
2029 if (fScriptChecks &&
2032 nSigChecksRet, nSigChecksTxLimiters[txIndex],
2033 &nSigChecksBlockLimiter, &vChecks)) {
2040 "ConnectBlock(): CheckInputScripts on %s failed with %s",
2044 control.
Add(vChecks);
2058 " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) "
2059 "[%.2fs (%.2fms/blk)]\n",
2060 (
unsigned)block.
vtx.size(),
MILLI * (nTime3 - nTime2),
2061 MILLI * (nTime3 - nTime2) / block.
vtx.size(),
2062 nInputs <= 1 ? 0 :
MILLI * (nTime3 - nTime2) / (nInputs - 1),
2065 const Amount blockReward =
2067 if (block.
vtx[0]->GetValueOut() > blockReward) {
2068 LogPrintf(
"ERROR: ConnectBlock(): coinbase pays too much (actual=%d vs "
2070 block.
vtx[0]->GetValueOut(), blockReward);
2079 if (!control.
Wait()) {
2081 "blk-bad-inputs",
"parallel script check failed");
2088 " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs (%.2fms/blk)]\n",
2089 nInputs - 1,
MILLI * (nTime4 - nTime2),
2090 nInputs <= 1 ? 0 :
MILLI * (nTime4 - nTime2) / (nInputs - 1),
2097 if (!
m_blockman.WriteUndoDataForBlock(blockundo, state, *pindex)) {
2116 TRACE6(validation, block_connected, block_hash.data(), pindex->
nHeight,
2117 block.
vtx.size(), nInputs, nSigChecksRet,
2119 nTime5 - nTimeStart);
2132 Chainstate::GetCoinsCacheSizeState(
size_t max_coins_cache_size_bytes,
2133 size_t max_mempool_size_bytes) {
2137 int64_t nTotalSpace =
2138 max_coins_cache_size_bytes +
2139 std::max<int64_t>(int64_t(max_mempool_size_bytes) - nMempoolUsage, 0);
2142 static constexpr int64_t MAX_BLOCK_COINSDB_USAGE_BYTES =
2144 int64_t large_threshold = std::max(
2145 (9 * nTotalSpace) / 10, nTotalSpace - MAX_BLOCK_COINSDB_USAGE_BYTES);
2147 if (cacheSize > nTotalSpace) {
2148 LogPrintf(
"Cache size (%s) exceeds total space (%s)\n", cacheSize,
2151 }
else if (cacheSize > large_threshold) {
2160 assert(this->CanFlushToDisk());
2161 std::set<int> setFilesToPrune;
2162 bool full_flush_completed =
false;
2169 bool fFlushForPrune =
false;
2170 bool fDoFullFlush =
false;
2181 last_prune = std::max(
2182 1, std::min(last_prune,
2186 if (nManualPruneHeight > 0) {
2191 std::min(last_prune, nManualPruneHeight),
2202 if (!setFilesToPrune.empty()) {
2203 fFlushForPrune =
true;
2206 "prunedblockfiles",
true);
2211 const auto nNow = GetTime<std::chrono::microseconds>();
2236 fCacheCritical || fPeriodicFlush || fFlushForPrune;
2238 if (fDoFullFlush || fPeriodicWrite) {
2241 return AbortNode(state,
"Disk space is too low!",
2242 _(
"Disk space is too low!"));
2261 state,
"Failed to write to block index database");
2266 if (fFlushForPrune) {
2276 if (fDoFullFlush && !
CoinsTip().GetBestBlock().IsNull()) {
2278 strprintf(
"write coins cache to disk (%d coins, %.2fkB)",
2279 coins_count, coins_mem_usage / 1000),
2289 48 * 2 * 2 *
CoinsTip().GetCacheSize())) {
2290 return AbortNode(state,
"Disk space is too low!",
2291 _(
"Disk space is too low!"));
2297 return AbortNode(state,
"Failed to write to coin database");
2300 full_flush_completed =
true;
2305 GetTimeMicros() - nNow.count(), uint32_t(mode), coins_count,
2306 uint64_t(coins_mem_usage), fFlushForPrune);
2309 if (full_flush_completed) {
2313 }
catch (
const std::runtime_error &e) {
2314 return AbortNode(state, std::string(
"System error while flushing: ") +
2323 LogPrintf(
"%s: failed to flush state (%s)\n", __func__,
2332 LogPrintf(
"%s: failed to flush state (%s)\n", __func__,
2339 const std::string &func_name,
2340 const std::string &
prefix)
2343 LogPrintf(
"%s%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%ld "
2344 "date='%s' progress=%f cache=%.1fMiB(%utxo)\n",
2350 coins_tip.DynamicMemoryUsage() * (1.0 / (1 << 20)),
2351 coins_tip.GetCacheSize());
2354 void Chainstate::UpdateTip(
const CBlockIndex *pindexNew) {
2356 const auto &coins_tip =
CoinsTip();
2362 if (
this != &
m_chainman.ActiveChainstate()) {
2365 constexpr
int BACKGROUND_LOG_INTERVAL = 2000;
2366 if (pindexNew->
nHeight % BACKGROUND_LOG_INTERVAL == 0) {
2368 "[background validation] ");
2384 UpdateTipLog(coins_tip, pindexNew, params, __func__,
"");
2411 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
2414 return error(
"DisconnectTip(): Failed to read block");
2422 if (DisconnectBlock(block, pindexDelete, view) !=
2424 return error(
"DisconnectTip(): DisconnectBlock %s failed",
2428 bool flushed = view.
Flush();
2444 if (pindexDelete->
pprev !=
nullptr &&
2448 "Disconnecting mempool due to rewind of upgrade block\n");
2449 if (disconnectpool) {
2455 if (disconnectpool) {
2462 UpdateTip(pindexDelete->
pprev);
2496 std::shared_ptr<const CBlock> pblock) {
2526 const std::shared_ptr<const CBlock> &pblock,
2539 std::shared_ptr<const CBlock> pthisBlock;
2541 std::shared_ptr<CBlock> pblockNew = std::make_shared<CBlock>();
2543 return AbortNode(state,
"Failed to read block");
2545 pthisBlock = pblockNew;
2547 pthisBlock = pblock;
2550 const CBlock &blockConnecting = *pthisBlock;
2561 bool rv =
ConnectBlock(blockConnecting, state, pindexNew, view,
2570 return error(
"%s: ConnectBlock %s failed, %s", __func__,
2591 const Amount blockReward =
2595 std::vector<std::unique_ptr<ParkingPolicy>> parkingPolicies;
2596 parkingPolicies.emplace_back(std::make_unique<MinerFundPolicy>(
2597 consensusParams, *pindexNew, blockConnecting, blockReward));
2600 parkingPolicies.emplace_back(
2601 std::make_unique<StakingRewardsPolicy>(
2602 consensusParams, *pindexNew, blockConnecting,
2606 parkingPolicies.emplace_back(
2607 std::make_unique<PreConsensusPolicy>(
2608 *pindexNew, blockConnecting,
m_mempool));
2613 if (std::find_if_not(parkingPolicies.begin(), parkingPolicies.end(),
2614 [&](
const auto &policy) {
2615 bool ret = (*policy)(blockPolicyState);
2618 "Park block because it "
2619 "violated a block policy: %s\n",
2620 blockPolicyState.ToString());
2623 }) != parkingPolicies.end()) {
2624 pindexNew->nStatus = pindexNew->nStatus.withParked();
2634 " - Connect total: %.2fms [%.2fs (%.2fms/blk)]\n",
2637 bool flushed = view.
Flush();
2655 " - Writing chainstate: %.2fms [%.2fs (%.2fms/blk)]\n",
2661 disconnectpool.removeForBlock(blockConnecting.vtx, *m_mempool);
2666 if (pindexNew->
pprev !=
nullptr &&
2671 "Disconnecting mempool due to acceptance of upgrade block\n");
2672 disconnectpool.importMempool(*m_mempool);
2677 m_chain.SetTip(pindexNew);
2678 UpdateTip(pindexNew);
2684 " - Connect postprocess: %.2fms [%.2fs (%.2fms/blk)]\n",
2694 if (
this != &m_chainman.ActiveChainstate()) {
2698 m_chainman.MaybeCompleteSnapshotValidation();
2701 connectTrace.BlockConnected(pindexNew, std::move(pthisBlock));
2710 std::vector<const CBlockIndex *> &blocksToReconcile) {
2717 std::set<CBlockIndex *, CBlockIndexWorkComparator>::reverse_iterator
2729 if (m_avalancheFinalizedBlockIndex &&
2731 LogPrintf(
"Park block %s because it forks prior to the "
2732 "avalanche finalized chaintip.\n",
2734 pindexNew->nStatus = pindexNew->nStatus.withParked();
2740 const bool fAutoUnpark =
2749 bool hasValidAncestor =
true;
2750 while (hasValidAncestor && pindexTest && pindexTest != pindexFork) {
2755 bool fParkedChain = pindexTest->nStatus.isOnParkedChain();
2756 if (fAutoUnpark && fParkedChain) {
2762 if (!pindexTip || !pindexFork) {
2776 pindexExtraPow = pindexExtraPow->
pprev;
2781 requiredWork += (deltaWork >> 1);
2792 LogPrintf(
"Unpark chain up to block %s as it has "
2793 "accumulated enough PoW.\n",
2795 fParkedChain =
false;
2804 bool fInvalidChain = pindexTest->nStatus.isInvalid();
2805 bool fMissingData = !pindexTest->nStatus.hasData();
2806 if (!(fInvalidChain || fParkedChain || fMissingData)) {
2809 pindexTest = pindexTest->
pprev;
2815 hasValidAncestor =
false;
2818 if (fInvalidChain && (
m_chainman.m_best_invalid ==
nullptr ||
2824 if (fParkedChain && (
m_chainman.m_best_parked ==
nullptr ||
2830 LogPrintf(
"Considered switching to better tip %s but that chain "
2831 "contains a%s%s%s block.\n",
2833 fInvalidChain ?
"n invalid" :
"",
2834 fParkedChain ?
" parked" :
"",
2835 fMissingData ?
" missing-data" :
"");
2839 while (pindexTest != pindexFailed) {
2840 if (fInvalidChain || fParkedChain) {
2841 pindexFailed->nStatus =
2842 pindexFailed->nStatus.withFailedParent(fInvalidChain)
2843 .withParkedParent(fParkedChain);
2844 }
else if (fMissingData) {
2850 std::make_pair(pindexFailed->
pprev, pindexFailed));
2853 pindexFailed = pindexFailed->
pprev;
2856 if (fInvalidChain || fParkedChain) {
2864 blocksToReconcile.push_back(pindexNew);
2868 if (hasValidAncestor) {
2901 const std::shared_ptr<const CBlock> &pblock,
bool &fInvalidFound,
2912 bool fBlocksDisconnected =
false;
2915 if (!fBlocksDisconnected) {
2934 "Failed to disconnect block; see debug.log for details");
2938 fBlocksDisconnected =
true;
2942 std::vector<CBlockIndex *> vpindexToConnect;
2943 bool fContinue =
true;
2948 int nTargetHeight = std::min(
nHeight + 32, pindexMostWork->
nHeight);
2949 vpindexToConnect.clear();
2950 vpindexToConnect.reserve(nTargetHeight -
nHeight);
2953 vpindexToConnect.push_back(pindexIter);
2954 pindexIter = pindexIter->
pprev;
2962 if (!
ConnectTip(state, blockPolicyState, pindexConnect,
2963 pindexConnect == pindexMostWork
2965 : std::shared_ptr<const CBlock>(),
2966 connectTrace, disconnectpool)) {
2974 fInvalidFound =
true;
2995 if (!pindexOldTip ||
3007 if (fBlocksDisconnected || !disconnectpool.
isEmpty()) {
3013 "Updating mempool due to reorganization or "
3014 "rules upgrade/downgrade\n");
3022 if (fInvalidFound) {
3042 bool fNotify =
false;
3043 bool fInitialBlockDownload =
false;
3048 pindexHeader = chainstate.m_chainman.m_best_header;
3050 if (pindexHeader != pindexHeaderOld) {
3052 fInitialBlockDownload = chainstate.IsInitialBlockDownload();
3053 pindexHeaderOld = pindexHeader;
3075 std::shared_ptr<const CBlock> pblock,
3076 bool skip_checkblockindex) {
3096 LogPrintf(
"m_disabled is set - this chainstate should not be in "
3097 "operation. Please report this as a bug. %s\n",
3114 std::vector<const CBlockIndex *> blocksToReconcile;
3115 bool blocks_connected =
false;
3121 LOCK(MempoolMutex());
3131 if (pindexMostWork ==
nullptr) {
3136 if (pindexMostWork ==
nullptr ||
3141 bool fInvalidFound =
false;
3142 std::shared_ptr<const CBlock> nullBlockPtr;
3144 state, pindexMostWork,
3145 pblock && pblock->GetHash() ==
3149 fInvalidFound, connectTrace)) {
3153 blocks_connected =
true;
3155 if (fInvalidFound ||
3156 (pindexMostWork && pindexMostWork->nStatus.isParked())) {
3158 pindexMostWork =
nullptr;
3164 assert(trace.pblock && trace.pindex);
3186 if (!skip_checkblockindex) {
3190 if (blocks_connected) {
3197 if (pindexFork != pindexNewTip) {
3212 for (
const CBlockIndex *pindex : blocksToReconcile) {
3218 if (!blocks_connected) {
3222 if (nStopAtHeight && pindexNewTip &&
3223 pindexNewTip->
nHeight >= nStopAtHeight) {
3241 }
while (pindexNewTip != pindexMostWork);
3293 template <
typename Func>
struct Defer {
3295 Defer(
Func &&f) : func(
std::move(f)) {}
3296 ~Defer() { func(); }
3309 bool pindex_was_in_chain =
false;
3310 int disconnected = 0;
3326 std::multimap<const arith_uint256, CBlockIndex *> candidate_blocks_by_work;
3330 for (
auto &entry :
m_blockman.m_block_index) {
3341 candidate_blocks_by_work.insert(
3342 std::make_pair(candidate->
nChainWork, candidate));
3352 LOCK(MempoolMutex());
3354 constexpr
int maxDisconnectPoolBlocks = 10;
3406 pindex_was_in_chain =
true;
3415 if (optDisconnectPool && disconnected > maxDisconnectPoolBlocks) {
3420 optDisconnectPool =
nullptr;
3436 invalid_walk_tip->nStatus =
3437 invalidate ? invalid_walk_tip->nStatus.withFailed()
3438 : invalid_walk_tip->nStatus.withParked();
3443 if (invalid_walk_tip == to_mark_failed_or_parked->
pprev &&
3444 (invalidate ? to_mark_failed_or_parked->nStatus.hasFailed()
3445 : to_mark_failed_or_parked->nStatus.isParked())) {
3449 to_mark_failed_or_parked->nStatus =
3451 ? to_mark_failed_or_parked->nStatus.withFailed(
false)
3453 : to_mark_failed_or_parked->nStatus.withParked(
false)
3454 .withParkedParent());
3460 auto candidate_it = candidate_blocks_by_work.lower_bound(
3462 while (candidate_it != candidate_blocks_by_work.end()) {
3464 invalid_walk_tip->
pprev)) {
3466 candidate_it = candidate_blocks_by_work.erase(candidate_it);
3475 to_mark_failed_or_parked = invalid_walk_tip;
3491 to_mark_failed_or_parked->nStatus =
3492 invalidate ? to_mark_failed_or_parked->nStatus.withFailed()
3493 : to_mark_failed_or_parked->nStatus.withParked();
3506 for (
auto &[
_, block_index] :
m_blockman.m_block_index) {
3508 block_index.HaveTxsDownloaded() &&
3521 if (pindex_was_in_chain) {
3524 to_mark_failed_or_parked->
pprev);
3548 template <
typename F>
3552 if (pindex->nStatus != newStatus &&
3555 pindex->nStatus = newStatus;
3571 template <
typename F,
typename C,
typename AC>
3573 F f, C fChild, AC fAncestorWasChanged) {
3579 for (
auto pindexAncestor = pindex; pindexAncestor !=
nullptr;
3580 pindexAncestor = pindexAncestor->
pprev) {
3582 pindexDeepestChanged = pindexAncestor;
3588 pindexDeepestChanged) {
3590 pindexReset =
nullptr;
3594 for (
auto &[
_, block_index] :
m_blockman.m_block_index) {
3597 fAncestorWasChanged);
3607 return status.withClearedFailureFlags();
3610 return status.withClearedFailureFlags();
3613 return status.withFailedParent(false);
3623 return status.withClearedParkedFlags();
3626 return fClearChildren ? status.withClearedParkedFlags()
3627 : status.withParkedParent(false);
3630 return status.withParkedParent(false);
3649 "The block to mark finalized by avalanche is not on the "
3650 "active chain: %s\n",
3665 m_avalancheFinalizedBlockIndex = pindex;
3675 m_avalancheFinalizedBlockIndex =
nullptr;
3680 return pindex && m_avalancheFinalizedBlockIndex &&
3692 pindexNew->
nTx = block.
vtx.size();
3694 pindexNew->nFile = pos.
nFile;
3695 pindexNew->nDataPos = pos.
nPos;
3696 pindexNew->nUndoPos = 0;
3697 pindexNew->nStatus = pindexNew->nStatus.withData();
3704 std::deque<CBlockIndex *> queue;
3705 queue.push_back(pindexNew);
3709 while (!queue.empty()) {
3727 std::pair<std::multimap<CBlockIndex *, CBlockIndex *>::iterator,
3728 std::multimap<CBlockIndex *, CBlockIndex *>::iterator>
3730 while (range.first != range.second) {
3731 std::multimap<CBlockIndex *, CBlockIndex *>::iterator it =
3733 queue.push_back(it->second);
3738 }
else if (pindexNew->
pprev &&
3741 std::make_pair(pindexNew->
pprev, pindexNew));
3761 "high-hash",
"proof of work failed");
3787 "bad-txnmrklroot",
"hashMerkleRoot mismatch");
3795 "bad-txns-duplicate",
"duplicate transaction");
3804 if (block.
vtx.empty()) {
3806 "bad-cb-missing",
"first tx is not coinbase");
3815 "bad-blk-length",
"size limits failed");
3819 if (currentBlockSize > nMaxBlockSize) {
3821 "bad-blk-length",
"size limits failed");
3829 strprintf(
"Coinbase check failed (txid %s) %s",
3830 block.
vtx[0]->GetId().ToString(),
3836 for (
size_t i = 1; i < block.
vtx.size(); i++) {
3837 auto *tx = block.
vtx[i].get();
3842 strprintf(
"Transaction check failed (txid %s) %s",
3857 return std::all_of(headers.cbegin(), headers.cend(),
3858 [&](
const auto &header) {
3859 return CheckProofOfWork(
3860 header.GetHash(), header.nBits, consensusParams);
3887 const std::optional<CCheckpointData> &test_checkpoints = std::nullopt)
3890 assert(pindexPrev !=
nullptr);
3891 const int nHeight = pindexPrev->nHeight + 1;
3897 LogPrintf(
"bad bits after height: %d\n", pindexPrev->nHeight);
3899 "bad-diffbits",
"incorrect proof of work");
3903 if (chainman.m_options.checkpoints_enabled) {
3905 test_checkpoints ? test_checkpoints.value() : params.
Checkpoints();
3911 "ERROR: %s: rejected by checkpoint lock-in at %d\n",
3914 "checkpoint mismatch");
3922 blockman.GetLastCheckpoint(checkpoints);
3923 if (pcheckpoint && nHeight < pcheckpoint->
nHeight) {
3925 "ERROR: %s: forked chain older than last checkpoint "
3929 "bad-fork-prior-to-checkpoint");
3934 if (block.
GetBlockTime() <= pindexPrev->GetMedianTimePast()) {
3936 "time-too-old",
"block's timestamp is too early");
3940 if (block.
Time() > now + std::chrono::seconds{MAX_FUTURE_BLOCK_TIME}) {
3943 "block timestamp too far in the future");
3970 assert(active_chain_tip);
3979 const int nBlockHeight = active_chain_tip->
nHeight + 1;
4004 const int nHeight = pindexPrev ==
nullptr ? 0 : pindexPrev->
nHeight + 1;
4007 bool enforce_locktime_median_time_past{
false};
4010 assert(pindexPrev !=
nullptr);
4011 enforce_locktime_median_time_past =
true;
4014 const int64_t nMedianTimePast =
4017 const int64_t nLockTimeCutoff{enforce_locktime_median_time_past
4022 const bool fIsMagneticAnomalyEnabled =
4030 for (
const auto &ptx : block.
vtx) {
4032 if (fIsMagneticAnomalyEnabled) {
4033 if (prevTx && (tx.
GetId() <= prevTx->
GetId())) {
4043 strprintf(
"Transaction order is invalid (%s < %s)",
4066 if (block.
vtx[0]->vin[0].scriptSig.size() <
expect.size() ||
4068 block.
vtx[0]->vin[0].scriptSig.begin())) {
4071 "block height mismatch in coinbase");
4086 const std::optional<CCheckpointData> &test_checkpoints) {
4093 BlockMap::iterator miSelf{
m_blockman.m_block_index.find(hash)};
4095 if (miSelf !=
m_blockman.m_block_index.end()) {
4102 if (pindex->nStatus.isInvalid()) {
4115 "%s: Consensus::CheckBlockHeader: %s, %s\n", __func__,
4121 BlockMap::iterator mi{
4125 "header %s has prev block not found: %s\n",
4128 "prev-blk-not-found");
4133 if (pindexPrev->nStatus.isInvalid()) {
4135 "header %s has prev block invalid: %s\n", hash.
ToString(),
4145 "%s: Consensus::ContextualCheckBlockHeader: %s, %s\n",
4176 if (pindexPrev->
GetAncestor(failedit->nHeight) == failedit) {
4177 assert(failedit->nStatus.hasFailed());
4179 while (invalid_walk != failedit) {
4180 invalid_walk->nStatus =
4181 invalid_walk->nStatus.withFailedParent();
4183 invalid_walk = invalid_walk->
pprev;
4186 "header %s has prev block invalid: %s\n",
4195 if (!min_pow_checked) {
4197 "%s: not adding new block header %s, missing anti-dos "
4198 "proof-of-work validation\n",
4201 "too-little-chainwork");
4214 const std::vector<CBlockHeader> &headers,
bool min_pow_checked,
4216 const std::optional<CCheckpointData> &test_checkpoints) {
4224 header, state, &pindex, min_pow_checked, test_checkpoints);
4225 ActiveChainstate().CheckBlockIndex();
4238 if (ActiveChainstate().IsInitialBlockDownload() && ppindex &&
4241 const int64_t blocks_left{
4242 (
GetTime() - last_accepted.GetBlockTime()) /
4244 const double progress{100.0 * last_accepted.nHeight /
4245 (last_accepted.nHeight + blocks_left)};
4246 LogPrintf(
"Synchronizing blockheaders, height: %d (~%.2f%%)\n",
4247 last_accepted.nHeight, progress);
4253 void ChainstateManager::ReportHeadersPresync(
const arith_uint256 &work,
4255 int64_t timestamp) {
4257 const auto &chainstate = ActiveChainstate();
4265 if (m_best_header->nChainWork >=
4271 auto now = Now<SteadyMilliseconds>();
4272 if (now < m_last_presync_update + 250ms) {
4275 m_last_presync_update = now;
4277 bool initial_download = chainstate.IsInitialBlockDownload();
4279 height, timestamp,
true);
4280 if (initial_download) {
4281 const int64_t blocks_left{(
GetTime() - timestamp) /
4283 const double progress{100.0 * height / (height + blocks_left)};
4284 LogPrintf(
"Pre-synchronizing blockheaders, height: %d (~%.2f%%)\n",
4304 bool min_pow_checked) {
4307 const CBlock &block = *pblock;
4314 bool accepted_header{
4318 if (!accepted_header) {
4325 bool fAlreadyHave = pindex->nStatus.hasData();
4337 int64_t chainTipTimeDiff =
4343 LogPrintf(
"Chain tip timestamp-to-received-time difference: hash=%s, "
4346 LogPrintf(
"New block timestamp-to-received-time difference: hash=%s, "
4351 bool fHasMoreOrSameWork =
4360 bool fTooFarAhead{pindex->
nHeight >
4373 if (pindex->
nTx != 0) {
4378 if (!fHasMoreOrSameWork) {
4399 if (!
CheckBlock(block, state, consensusParams,
4404 pindex->nStatus = pindex->nStatus.withFailed();
4408 return error(
"%s: %s (block %s)", __func__, state.
ToString(),
4421 LogPrintf(
"Park block %s as it would cause a deep reorg.\n",
4423 pindex->nStatus = pindex->nStatus.withParked();
4442 if (blockPos.IsNull()) {
4444 "%s: Failed to find position to write new block to disk",
4449 }
catch (
const std::runtime_error &e) {
4450 return AbortNode(state, std::string(
"System error: ") + e.what());
4461 const std::shared_ptr<const CBlock> &block,
bool force_processing,
4462 bool min_pow_checked,
bool *new_block) {
4490 ret = ActiveChainstate().AcceptBlock(block, state, force_processing,
4497 return error(
"%s: AcceptBlock FAILED (%s)", __func__,
4506 if (!ActiveChainstate().ActivateBestChain(state, block)) {
4507 return error(
"%s: ActivateBestChain failed (%s)", __func__,
4518 Chainstate &active_chainstate = ActiveChainstate();
4525 false, test_accept);
4541 indexDummy.
pprev = pindexPrev;
4548 adjusted_time_callback())) {
4549 return error(
"%s: Consensus::ContextualCheckBlockHeader: %s", __func__,
4554 return error(
"%s: Consensus::CheckBlock: %s", __func__,
4560 return error(
"%s: Consensus::ContextualCheckBlock: %s", __func__,
4564 if (!chainstate.
ConnectBlock(block, state, &indexDummy, viewNew,
4565 validationOptions,
nullptr,
true)) {
4575 int nManualPruneHeight) {
4578 nManualPruneHeight)) {
4579 LogPrintf(
"%s: failed to flush state (%s)\n", __func__,
4585 FopenFn mockable_fopen_function) {
4615 "Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n",
4623 uiInterface.ShowProgress(
_(
"Verifying blocks...").translated, 0,
false);
4645 if (nCheckDepth <= 0 || nCheckDepth > chainstate.
m_chain.
Height()) {
4649 nCheckLevel = std::max(0, std::min(4, nCheckLevel));
4650 LogPrintf(
"Verifying last %i blocks at level %i\n", nCheckDepth,
4656 int nGoodTransactions = 0;
4659 bool skipped_no_block_data{
false};
4660 bool skipped_l3_checks{
false};
4661 LogPrintf(
"Verification progress: 0%%\n");
4666 pindex = pindex->
pprev) {
4667 const int percentageDone = std::max(
4668 1, std::min(99, (
int)(((
double)(chainstate.
m_chain.
Height() -
4670 (
double)nCheckDepth *
4671 (nCheckLevel >= 4 ? 50 : 100))));
4672 if (reportDone < percentageDone / 10) {
4674 LogPrintf(
"Verification progress: %d%%\n", percentageDone);
4675 reportDone = percentageDone / 10;
4678 uiInterface.ShowProgress(
_(
"Verifying blocks...").translated,
4679 percentageDone,
false);
4685 !pindex->nStatus.hasData()) {
4688 LogPrintf(
"VerifyDB(): block verification stopping at height %d "
4689 "(no data). This could be due to pruning or use of an "
4690 "assumeutxo snapshot.\n",
4692 skipped_no_block_data =
true;
4701 "Verification error: ReadBlockFromDisk failed at %d, hash=%s\n",
4707 if (nCheckLevel >= 1 && !
CheckBlock(block, state, consensusParams,
4710 "Verification error: found bad block at %d, hash=%s (%s)\n",
4717 if (nCheckLevel >= 2 && pindex) {
4721 LogPrintf(
"Verification error: found bad undo data at %d, "
4734 if (nCheckLevel >= 3) {
4738 chainstate.DisconnectBlock(block, pindex, coins);
4740 LogPrintf(
"Verification error: irrecoverable inconsistency "
4741 "in block data at %d, hash=%s\n",
4747 nGoodTransactions = 0;
4748 pindexFailure = pindex;
4750 nGoodTransactions += block.
vtx.size();
4753 skipped_l3_checks =
true;
4762 if (pindexFailure) {
4763 LogPrintf(
"Verification error: coin database inconsistencies found "
4764 "(last %i blocks, %i good transactions before that)\n",
4769 if (skipped_l3_checks) {
4770 LogPrintf(
"Skipped verification of level >=3 (insufficient database "
4771 "cache size). Consider increasing -dbcache.\n");
4778 if (nCheckLevel >= 4 && !skipped_l3_checks) {
4780 const int percentageDone = std::max(
4781 1, std::min(99, 100 -
int(
double(chainstate.
m_chain.
Height() -
4783 double(nCheckDepth) * 50)));
4784 if (reportDone < percentageDone / 10) {
4786 LogPrintf(
"Verification progress: %d%%\n", percentageDone);
4787 reportDone = percentageDone / 10;
4789 uiInterface.ShowProgress(
_(
"Verifying blocks...").translated,
4790 percentageDone,
false);
4794 LogPrintf(
"Verification error: ReadBlockFromDisk failed at %d, "
4799 if (!chainstate.
ConnectBlock(block, state, pindex, coins,
4801 LogPrintf(
"Verification error: found unconnectable block at "
4802 "%d, hash=%s (%s)\n",
4813 LogPrintf(
"Verification: No coin database inconsistencies in last %i "
4814 "blocks (%i transactions)\n",
4815 block_count, nGoodTransactions);
4817 if (skipped_l3_checks) {
4820 if (skipped_no_block_data) {
4836 return error(
"ReplayBlock(): ReadBlockFromDisk failed at %d, hash=%s",
4846 if (tx->IsCoinBase()) {
4850 for (
const CTxIn &txin : tx->vin) {
4864 std::vector<BlockHash> hashHeads =
db.GetHeadBlocks();
4865 if (hashHeads.empty()) {
4869 if (hashHeads.size() != 2) {
4870 return error(
"ReplayBlocks(): unknown inconsistent state");
4873 uiInterface.ShowProgress(
_(
"Replaying blocks...").translated, 0,
false);
4883 if (
m_blockman.m_block_index.count(hashHeads[0]) == 0) {
4885 "ReplayBlocks(): reorganization to unknown block requested");
4888 pindexNew = &(
m_blockman.m_block_index[hashHeads[0]]);
4890 if (!hashHeads[1].IsNull()) {
4892 if (
m_blockman.m_block_index.count(hashHeads[1]) == 0) {
4894 "ReplayBlocks(): reorganization from unknown block requested");
4897 pindexOld = &(
m_blockman.m_block_index[hashHeads[1]]);
4899 assert(pindexFork !=
nullptr);
4903 while (pindexOld != pindexFork) {
4909 return error(
"RollbackBlock(): ReadBlockFromDisk() failed at "
4920 "RollbackBlock(): DisconnectBlock failed at %d, hash=%s",
4932 pindexOld = pindexOld->
pprev;
4936 int nForkHeight = pindexFork ? pindexFork->
nHeight : 0;
4942 uiInterface.ShowProgress(
_(
"Replaying blocks...").translated,
4943 (
int)((
nHeight - nForkHeight) * 100.0 /
4944 (pindexNew->
nHeight - nForkHeight)),
4977 std::vector<CBlockIndex *> vSortedByHeight{
4979 std::sort(vSortedByHeight.begin(), vSortedByHeight.end(),
4983 int first_assumed_valid_height = std::numeric_limits<int>::max();
4985 for (
const CBlockIndex *block : vSortedByHeight) {
4986 if (block->IsAssumedValid()) {
4987 auto chainstates =
GetAll();
4994 auto any_chain = [&](
auto fnc) {
4995 return std::any_of(chainstates.cbegin(), chainstates.cend(),
4998 assert(any_chain([](
auto chainstate) {
5001 assert(any_chain([](
auto chainstate) {
5005 first_assumed_valid_height = block->nHeight;
5006 LogPrintf(
"Saw first assumedvalid block at height %d (%s)\n",
5007 first_assumed_valid_height, block->
ToString());
5046 pindex->
nHeight < first_assumed_valid_height) {
5052 if (pindex->nStatus.isInvalid() &&
5054 pindex->
nChainWork > m_best_invalid->nChainWork)) {
5055 m_best_invalid = pindex;
5058 if (pindex->nStatus.isOnParkedChain() &&
5060 pindex->
nChainWork > m_best_parked->nChainWork)) {
5061 m_best_parked = pindex;
5065 (m_best_header ==
nullptr ||
5067 m_best_header = pindex;
5071 needs_init =
m_blockman.m_block_index.empty();
5081 LogPrintf(
"Initializing databases...\n");
5103 if (blockPos.IsNull()) {
5104 return error(
"%s: writing genesis block to disk failed", __func__);
5109 }
catch (
const std::runtime_error &e) {
5110 return error(
"%s: failed to write genesis block: %s", __func__,
5119 std::multimap<BlockHash, FlatFilePos> *blocks_with_unknown_parent) {
5123 assert(!dbp == !blocks_with_unknown_parent);
5137 uint64_t nRewind = blkdat.GetPos();
5138 while (!blkdat.eof()) {
5143 blkdat.SetPos(nRewind);
5148 unsigned int nSize = 0;
5153 nRewind = blkdat.GetPos() + 1;
5155 if (memcmp(buf, params.
DiskMagic().data(),
5165 }
catch (
const std::exception &) {
5173 const uint64_t nBlockPos{blkdat.GetPos()};
5175 dbp->
nPos = nBlockPos;
5177 blkdat.SetLimit(nBlockPos + nSize);
5185 nRewind = nBlockPos + nSize;
5186 blkdat.SkipTo(nRewind);
5190 std::shared_ptr<CBlock> pblock{};
5199 "%s: Out of order block %s, parent %s not known\n",
5200 __func__, hash.ToString(),
5202 if (dbp && blocks_with_unknown_parent) {
5203 blocks_with_unknown_parent->emplace(
5212 if (!pindex || !pindex->nStatus.hasData()) {
5215 blkdat.SetPos(nBlockPos);
5216 pblock = std::make_shared<CBlock>();
5218 nRewind = blkdat.GetPos();
5221 if (
AcceptBlock(pblock, state,
true, dbp,
nullptr,
5229 pindex->
nHeight % 1000 == 0) {
5232 "Block Import: already had block %s at height %d\n",
5233 hash.ToString(), pindex->
nHeight);
5258 "failed to activate chain (%s)\n",
5266 if (!blocks_with_unknown_parent) {
5272 std::deque<BlockHash> queue;
5273 queue.push_back(hash);
5274 while (!queue.empty()) {
5277 auto range = blocks_with_unknown_parent->equal_range(head);
5278 while (range.first != range.second) {
5279 std::multimap<BlockHash, FlatFilePos>::iterator it =
5281 std::shared_ptr<CBlock> pblockrecursive =
5282 std::make_shared<CBlock>();
5287 "%s: Processing out of order child %s of %s\n",
5288 __func__, pblockrecursive->GetHash().ToString(),
5293 &it->second,
nullptr,
true)) {
5295 queue.push_back(pblockrecursive->GetHash());
5299 blocks_with_unknown_parent->erase(it);
5303 }
catch (
const std::exception &e) {
5324 "%s: unexpected data at file offset 0x%x - %s. "
5326 __func__, (nRewind - 1), e.what());
5329 }
catch (
const std::runtime_error &e) {
5330 AbortNode(std::string(
"System error: ") + e.what());
5333 LogPrintf(
"Loaded %i blocks from external file in %dms\n", nLoaded,
5354 std::multimap<CBlockIndex *, CBlockIndex *> forward;
5355 for (
auto &[
_, block_index] :
m_blockman.m_block_index) {
5356 forward.emplace(block_index.pprev, &block_index);
5361 std::pair<std::multimap<CBlockIndex *, CBlockIndex *>::iterator,
5362 std::multimap<CBlockIndex *, CBlockIndex *>::iterator>
5363 rangeGenesis = forward.equal_range(
nullptr);
5365 rangeGenesis.first++;
5367 assert(rangeGenesis.first == rangeGenesis.second);
5387 CBlockIndex *pindexFirstNotTransactionsValid =
nullptr;
5393 CBlockIndex *pindexFirstNotScriptsValid =
nullptr;
5394 while (pindex !=
nullptr) {
5396 if (pindexFirstInvalid ==
nullptr && pindex->nStatus.hasFailed()) {
5397 pindexFirstInvalid = pindex;
5399 if (pindexFirstParked ==
nullptr && pindex->nStatus.isParked()) {
5400 pindexFirstParked = pindex;
5404 if (pindexFirstMissing ==
nullptr && !pindex->nStatus.hasData() &&
5406 pindexFirstMissing = pindex;
5408 if (pindexFirstNeverProcessed ==
nullptr && pindex->
nTx == 0) {
5409 pindexFirstNeverProcessed = pindex;
5411 if (pindex->
pprev !=
nullptr && pindexFirstNotTreeValid ==
nullptr &&
5413 pindexFirstNotTreeValid = pindex;
5416 if (pindexFirstNotTransactionsValid ==
nullptr &&
5418 pindexFirstNotTransactionsValid = pindex;
5420 if (pindexFirstNotChainValid ==
nullptr &&
5422 pindexFirstNotChainValid = pindex;
5424 if (pindexFirstNotScriptsValid ==
nullptr &&
5426 pindexFirstNotScriptsValid = pindex;
5431 if (pindex->
pprev ==
nullptr) {
5452 assert(pindex->nStatus.hasData() == (pindex->
nTx > 0));
5453 assert(pindexFirstMissing == pindexFirstNeverProcessed);
5454 }
else if (pindex->nStatus.hasData()) {
5459 if (pindex->nStatus.hasUndo()) {
5460 assert(pindex->nStatus.hasData());
5471 assert((pindex->nStatus.getValidity() >=
5479 assert((pindexFirstNeverProcessed ==
nullptr) ==
5481 assert((pindexFirstNotTransactionsValid ==
nullptr) ==
5493 assert(pindexFirstNotTreeValid ==
nullptr);
5496 assert(pindexFirstNotTreeValid ==
nullptr);
5500 assert(pindexFirstNotChainValid ==
nullptr);
5504 assert(pindexFirstNotScriptsValid ==
nullptr);
5506 if (pindexFirstInvalid ==
nullptr) {
5509 assert(!pindex->nStatus.isInvalid());
5511 if (pindexFirstParked ==
nullptr) {
5515 assert(!pindex->nStatus.isOnParkedChain());
5518 pindexFirstNeverProcessed ==
nullptr) {
5519 if (pindexFirstInvalid ==
nullptr) {
5524 if (
this == &
m_chainman.ActiveChainstate()) {
5528 if (pindexFirstMissing ==
nullptr) {
5529 assert(pindex->nStatus.isOnParkedChain() ||
5550 std::pair<std::multimap<CBlockIndex *, CBlockIndex *>::iterator,
5551 std::multimap<CBlockIndex *, CBlockIndex *>::iterator>
5554 bool foundInUnlinked =
false;
5555 while (rangeUnlinked.first != rangeUnlinked.second) {
5556 assert(rangeUnlinked.first->first == pindex->
pprev);
5557 if (rangeUnlinked.first->second == pindex) {
5558 foundInUnlinked =
true;
5561 rangeUnlinked.first++;
5563 if (pindex->
pprev && pindex->nStatus.hasData() &&
5564 pindexFirstNeverProcessed !=
nullptr &&
5565 pindexFirstInvalid ==
nullptr) {
5571 if (!pindex->nStatus.hasData()) {
5573 assert(!foundInUnlinked);
5575 if (pindexFirstMissing ==
nullptr) {
5578 assert(!foundInUnlinked);
5580 if (pindex->
pprev && pindex->nStatus.hasData() &&
5581 pindexFirstNeverProcessed ==
nullptr &&
5582 pindexFirstMissing !=
nullptr) {
5598 if (pindexFirstInvalid ==
nullptr) {
5608 std::pair<std::multimap<CBlockIndex *, CBlockIndex *>::iterator,
5609 std::multimap<CBlockIndex *, CBlockIndex *>::iterator>
5610 range = forward.equal_range(pindex);
5611 if (range.first != range.second) {
5613 pindex = range.first->second;
5623 if (pindex == pindexFirstInvalid) {
5624 pindexFirstInvalid =
nullptr;
5626 if (pindex == pindexFirstParked) {
5627 pindexFirstParked =
nullptr;
5629 if (pindex == pindexFirstMissing) {
5630 pindexFirstMissing =
nullptr;
5632 if (pindex == pindexFirstNeverProcessed) {
5633 pindexFirstNeverProcessed =
nullptr;
5635 if (pindex == pindexFirstNotTreeValid) {
5636 pindexFirstNotTreeValid =
nullptr;
5638 if (pindex == pindexFirstNotTransactionsValid) {
5639 pindexFirstNotTransactionsValid =
nullptr;
5641 if (pindex == pindexFirstNotChainValid) {
5642 pindexFirstNotChainValid =
nullptr;
5644 if (pindex == pindexFirstNotScriptsValid) {
5645 pindexFirstNotScriptsValid =
nullptr;
5650 std::pair<std::multimap<CBlockIndex *, CBlockIndex *>::iterator,
5651 std::multimap<CBlockIndex *, CBlockIndex *>::iterator>
5652 rangePar = forward.equal_range(pindexPar);
5653 while (rangePar.first->second != pindex) {
5656 assert(rangePar.first != rangePar.second);
5661 if (rangePar.first != rangePar.second) {
5663 pindex = rangePar.first->second;
5675 assert(nNodes == forward.size());
5681 return strprintf(
"Chainstate [%s] @ height %d (%s)",
5687 bool Chainstate::ResizeCoinsCaches(
size_t coinstip_size,
size_t coinsdb_size) {
5700 coinsdb_size * (1.0 / 1024 / 1024));
5702 coinstip_size * (1.0 / 1024 / 1024));
5707 if (coinstip_size > old_coinstip_size) {
5725 if (pindex ==
nullptr) {
5729 int64_t nNow = time(
nullptr);
5744 if (m_active_chainstate && m_active_chainstate->m_from_snapshot_blockhash) {
5746 return m_active_chainstate->m_from_snapshot_blockhash;
5748 return std::nullopt;
5753 std::vector<Chainstate *> out;
5756 {m_ibd_chainstate.get(), m_snapshot_chainstate.get()}) {
5757 if (this->IsUsable(pchainstate)) {
5758 out.push_back(pchainstate);
5767 assert(!m_ibd_chainstate);
5768 assert(!m_active_chainstate);
5770 m_ibd_chainstate = std::make_unique<Chainstate>(mempool,
m_blockman, *
this);
5771 m_active_chainstate = m_ibd_chainstate.get();
5772 return *m_active_chainstate;
5778 const auto assumeutxo_found = valid_assumeutxos_map.find(height);
5780 if (assumeutxo_found != valid_assumeutxos_map.end()) {
5781 return &assumeutxo_found->second;
5795 const bool existed{fs::remove(base_blockhash_path)};
5797 LogPrintf(
"[snapshot] snapshot chainstate dir being removed "
5801 }
catch (
const fs::filesystem_error &e) {
5802 LogPrintf(
"[snapshot] failed to remove file %s: %s\n",
5809 LogPrintf(
"Removing leveldb dir at %s\n", path_str);
5813 const bool destroyed = dbwrapper::DestroyDB(path_str, {}).ok();
5816 LogPrintf(
"error: leveldb DestroyDB call failed on %s\n", path_str);
5834 LogPrintf(
"[snapshot] can't activate a snapshot-based chainstate more "
5839 int64_t current_coinsdb_cache_size{0};
5840 int64_t current_coinstip_cache_size{0};
5849 static constexpr
double IBD_CACHE_PERC = 0.01;
5850 static constexpr
double SNAPSHOT_CACHE_PERC = 0.99;
5863 current_coinsdb_cache_size =
5864 this->ActiveChainstate().m_coinsdb_cache_size_bytes;
5865 current_coinstip_cache_size =
5866 this->ActiveChainstate().m_coinstip_cache_size_bytes;
5870 this->ActiveChainstate().ResizeCoinsCaches(
5871 static_cast<size_t>(current_coinstip_cache_size * IBD_CACHE_PERC),
5872 static_cast<size_t>(current_coinsdb_cache_size * IBD_CACHE_PERC));
5875 auto snapshot_chainstate =
5882 snapshot_chainstate->InitCoinsDB(
5883 static_cast<size_t>(current_coinsdb_cache_size *
5884 SNAPSHOT_CACHE_PERC),
5885 in_memory,
false,
"chainstate");
5886 snapshot_chainstate->InitCoinsCache(
static_cast<size_t>(
5887 current_coinstip_cache_size * SNAPSHOT_CACHE_PERC));
5891 coins_file, metadata);
5898 snapshot_ok =
false;
5903 this->MaybeRebalanceCaches();
5912 snapshot_chainstate.reset();
5917 strprintf(
"Failed to remove snapshot chainstate dir (%s). "
5918 "Manually remove it before restarting.\n",
5927 assert(!m_snapshot_chainstate);
5928 m_snapshot_chainstate.swap(snapshot_chainstate);
5929 const bool chaintip_loaded = m_snapshot_chainstate->LoadChainTip();
5932 m_active_chainstate = m_snapshot_chainstate.get();
5934 LogPrintf(
"[snapshot] successfully activated snapshot %s\n",
5937 m_snapshot_chainstate->CoinsTip().DynamicMemoryUsage() /
5940 this->MaybeRebalanceCaches();
5946 bool snapshot_loaded) {
5949 snapshot_loaded ?
"saving snapshot chainstate"
5950 :
"flushing coins cache",
5952 BCLog::LogFlags::ALL);
5954 coins_cache.
Flush();
5958 const char *
what()
const throw()
override {
5959 return "ComputeUTXOStats interrupted by shutdown.";
5983 if (!snapshot_start_block) {
5986 LogPrintf(
"[snapshot] Did not find snapshot start blockheader %s\n",
5991 int base_height = snapshot_start_block->
nHeight;
5994 if (!maybe_au_data) {
5995 LogPrintf(
"[snapshot] assumeutxo height in snapshot metadata not "
5996 "recognized (%d) - refusing to load snapshot\n",
6008 LogPrintf(
"[snapshot] loading coins from snapshot %s\n",
6010 int64_t coins_processed{0};
6012 while (coins_left > 0) {
6014 coins_file >> outpoint;
6016 }
catch (
const std::ios_base::failure &) {
6017 LogPrintf(
"[snapshot] bad snapshot format or truncated snapshot "
6018 "after deserializing %d coins\n",
6019 coins_count - coins_left);
6022 if (coin.
GetHeight() > uint32_t(base_height) ||
6025 std::numeric_limits<decltype(outpoint.
GetN())>::max()) {
6027 "[snapshot] bad snapshot data after deserializing %d coins\n",
6028 coins_count - coins_left);
6037 if (coins_processed % 1000000 == 0) {
6038 LogPrintf(
"[snapshot] %d coins loaded (%.2f%%, %.2f MB)\n",
6040 static_cast<float>(coins_processed) * 100 /
6041 static_cast<float>(coins_count),
6049 if (coins_processed % 120000 == 0) {
6054 const auto snapshot_cache_state =
WITH_LOCK(
6055 ::
cs_main,
return snapshot_chainstate.GetCoinsCacheSizeState());
6078 bool out_of_coins{
false};
6080 coins_file >> outpoint;
6081 }
catch (
const std::ios_base::failure &) {
6083 out_of_coins =
true;
6085 if (!out_of_coins) {
6086 LogPrintf(
"[snapshot] bad snapshot - coins left over after "
6087 "deserializing %d coins\n",
6092 LogPrintf(
"[snapshot] loaded %d (%.2f MB) coins from snapshot %s\n",
6106 std::optional<CCoinsStats> maybe_stats;
6115 if (!maybe_stats.has_value()) {
6116 LogPrintf(
"[snapshot] failed to generate coins stats\n");
6124 LogPrintf(
"[snapshot] bad snapshot content hash: expected %s, got %s\n",
6126 maybe_stats->hashSerialized.ToString());
6143 constexpr
int AFTER_GENESIS_START{1};
6145 for (
int i = AFTER_GENESIS_START; i <= snapshot_chainstate.
m_chain.
Height();
6147 index = snapshot_chainstate.
m_chain[i];
6162 index->nStatus = index->nStatus.withAssumedValid();
6177 LogPrintf(
"[snapshot] validated snapshot (%.2f MB)\n",
6200 if (m_ibd_chainstate.get() == &this->ActiveChainstate() ||
6201 !this->IsUsable(m_snapshot_chainstate.get()) ||
6202 !this->IsUsable(m_ibd_chainstate.get()) ||
6203 !m_ibd_chainstate->m_chain.Tip()) {
6209 const int snapshot_base_height = *
Assert(this->GetSnapshotBaseHeight());
6212 if (index_new.
nHeight < snapshot_base_height) {
6222 _(
"%s failed to validate the -assumeutxo snapshot state. "
6223 "This indicates a hardware problem, or a bug in the software, or "
6224 "a bad software modification that allowed an invalid snapshot to "
6225 "be loaded. As a result of this, the node will shut down and "
6226 "stop using any state that was built on the snapshot, resetting "
6227 "the chain height from %d to %d. On the next restart, the node "
6228 "will resume syncing from %d without using any snapshot data. "
6229 "Please report this incident to %s, including how you obtained "
6230 "the snapshot. The invalid snapshot chainstate will be left on "
6231 "disk in case it is helpful in diagnosing the issue that caused "
6233 PACKAGE_NAME, snapshot_tip_height, snapshot_base_height,
6234 snapshot_base_height, PACKAGE_BUGREPORT);
6237 LogPrintf(
"[snapshot] deleting snapshot, reverting to validated chain, "
6238 "and stopping node\n");
6240 m_active_chainstate = m_ibd_chainstate.get();
6241 m_snapshot_chainstate->m_disabled =
true;
6242 assert(!this->IsUsable(m_snapshot_chainstate.get()));
6243 assert(this->IsUsable(m_ibd_chainstate.get()));
6245 auto rename_result = m_snapshot_chainstate->InvalidateCoinsDBOnDisk();
6246 if (!rename_result) {
6251 shutdown_fnc(user_error);
6256 "[snapshot] supposed base block %s does not match the "
6257 "snapshot base block %s (height %d). Snapshot is not valid.\n",
6259 snapshot_base_height);
6260 handle_invalid_snapshot();
6266 int curr_height = m_ibd_chainstate->m_chain.Height();
6268 assert(snapshot_base_height == curr_height);
6270 assert(this->IsUsable(m_snapshot_chainstate.get()));
6273 CCoinsViewDB &ibd_coins_db = m_ibd_chainstate->CoinsDB();
6274 m_ibd_chainstate->ForceFlushStateToDisk();
6277 if (!maybe_au_data) {
6278 LogPrintf(
"[snapshot] assumeutxo data not found for height "
6279 "(%d) - refusing to validate snapshot\n",
6281 handle_invalid_snapshot();
6286 std::optional<CCoinsStats> maybe_ibd_stats;
6288 "[snapshot] computing UTXO stats for background chainstate to validate "
6289 "snapshot - this could take a few minutes\n");
6298 if (!maybe_ibd_stats) {
6300 "[snapshot] failed to generate stats for validation coins db\n");
6304 handle_invalid_snapshot();
6307 const auto &ibd_stats = *maybe_ibd_stats;
6316 LogPrintf(
"[snapshot] hash mismatch: actual=%s, expected=%s\n",
6317 ibd_stats.hashSerialized.ToString(),
6319 handle_invalid_snapshot();
6323 LogPrintf(
"[snapshot] snapshot beginning at %s has been fully validated\n",
6326 m_ibd_chainstate->m_disabled =
true;
6327 this->MaybeRebalanceCaches();
6332 Chainstate &ChainstateManager::ActiveChainstate()
const {
6334 assert(m_active_chainstate);
6335 return *m_active_chainstate;
6340 return m_snapshot_chainstate &&
6341 m_active_chainstate == m_snapshot_chainstate.get();
6343 void ChainstateManager::MaybeRebalanceCaches() {
6345 bool ibd_usable = this->IsUsable(m_ibd_chainstate.get());
6346 bool snapshot_usable = this->IsUsable(m_snapshot_chainstate.get());
6347 assert(ibd_usable || snapshot_usable);
6349 if (ibd_usable && !snapshot_usable) {
6350 LogPrintf(
"[snapshot] allocating all cache to the IBD chainstate\n");
6354 }
else if (snapshot_usable && !ibd_usable) {
6358 "[snapshot] allocating all cache to the snapshot chainstate\n");
6362 }
else if (ibd_usable && snapshot_usable) {
6368 if (m_snapshot_chainstate->IsInitialBlockDownload()) {
6371 m_snapshot_chainstate->ResizeCoinsCaches(
6374 m_snapshot_chainstate->ResizeCoinsCaches(
6382 void ChainstateManager::ResetChainstates() {
6383 m_ibd_chainstate.reset();
6384 m_snapshot_chainstate.reset();
6385 m_active_chainstate =
nullptr;
6394 if (!opts.check_block_index.has_value()) {
6396 opts.config.GetChainParams().DefaultConsistencyChecks();
6399 if (!opts.minimum_chain_work.has_value()) {
6401 opts.config.GetChainParams().GetConsensus().nMinimumChainWork);
6403 if (!opts.assumed_valid_block.has_value()) {
6404 opts.assumed_valid_block =
6405 opts.config.GetChainParams().GetConsensus().defaultAssumeValid;
6407 Assert(opts.adjusted_time_callback);
6408 return std::move(opts);
6413 : m_options{
Flatten(
std::move(options))}, m_blockman{
std::move(
6414 blockman_options)} {}
6416 bool ChainstateManager::DetectSnapshotChainstate(
CTxMemPool *mempool) {
6417 assert(!m_snapshot_chainstate);
6422 std::optional<BlockHash> base_blockhash =
6424 if (!base_blockhash) {
6427 LogPrintf(
"[snapshot] detected active snapshot chainstate (%s) - loading\n",
6430 this->ActivateExistingSnapshot(mempool, *base_blockhash);
6435 ChainstateManager::ActivateExistingSnapshot(
CTxMemPool *mempool,
6437 assert(!m_snapshot_chainstate);
6438 m_snapshot_chainstate = std::make_unique<Chainstate>(mempool,
m_blockman,
6439 *
this, base_blockhash);
6440 LogPrintf(
"[snapshot] switching active chainstate to %s\n",
6441 m_snapshot_chainstate->ToString());
6442 m_active_chainstate = m_snapshot_chainstate.get();
6443 return *m_snapshot_chainstate;
6452 assert(storage_path_maybe);
6453 fs::path snapshot_datadir = *storage_path_maybe;
6458 auto invalid_path = snapshot_datadir +
"_INVALID";
6461 LogPrintf(
"[snapshot] renaming snapshot datadir %s to %s\n", dbpath,
6468 fs::rename(snapshot_datadir, invalid_path);
6469 }
catch (
const fs::filesystem_error &e) {
6473 LogPrintf(
"%s: error renaming file '%s' -> '%s': %s\n", __func__,
6474 src_str, dest_str, e.what());
6476 "You should resolve this by manually "
6477 "moving or deleting the invalid "
6478 "snapshot directory %s, otherwise you "
6479 "will encounter the same error again "
6480 "on the next startup."),
6481 src_str, dest_str, src_str)};
6486 const CBlockIndex *ChainstateManager::GetSnapshotBaseBlock()
const {
6488 if (!blockhash_op) {
6494 std::optional<int> ChainstateManager::GetSnapshotBaseHeight()
const {
6495 const CBlockIndex *base = this->GetSnapshotBaseBlock();
6496 return base ? std::make_optional(base->
nHeight) :
std::nullopt;
6499 bool ChainstateManager::ValidatedSnapshotCleanup() {
6502 ::
cs_main) -> std::optional<fs::path> {
6508 std::optional<fs::path> ibd_chainstate_path_maybe =
6509 get_storage_path(m_ibd_chainstate);
6510 std::optional<fs::path> snapshot_chainstate_path_maybe =
6511 get_storage_path(m_snapshot_chainstate);
6520 if (!ibd_chainstate_path_maybe || !snapshot_chainstate_path_maybe) {
6521 LogPrintf(
"[snapshot] snapshot chainstate cleanup cannot happen with "
6522 "in-memory chainstates. You are testing, right?\n");
6526 const auto &snapshot_chainstate_path = *snapshot_chainstate_path_maybe;
6527 const auto &ibd_chainstate_path = *ibd_chainstate_path_maybe;
6535 this->ResetChainstates();
6540 LogPrintf(
"[snapshot] deleting background chainstate directory (now "
6541 "unnecessary) (%s)\n",
6544 fs::path tmp_old{ibd_chainstate_path +
"_todelete"};
6547 const fs::filesystem_error &err) {
6551 "Rename of '%s' -> '%s' failed. "
6552 "Cannot clean up the background chainstate leveldb directory.",
6557 fs::rename(ibd_chainstate_path, tmp_old);
6558 }
catch (
const fs::filesystem_error &e) {
6559 rename_failed_abort(ibd_chainstate_path, tmp_old, e);
6563 LogPrintf(
"[snapshot] moving snapshot chainstate (%s) to "
6564 "default chainstate directory (%s)\n",
6569 fs::rename(snapshot_chainstate_path, ibd_chainstate_path);
6570 }
catch (
const fs::filesystem_error &e) {
6571 rename_failed_abort(snapshot_chainstate_path, ibd_chainstate_path, e);
6578 LogPrintf(
"Deletion of %s failed. Please remove it manually, as the "
6579 "directory is now unnecessary.\n",
6582 LogPrintf(
"[snapshot] deleted background chainstate directory (%s)\n",
bool IsDAAEnabled(const Consensus::Params ¶ms, int nHeight)
bool IsUAHFenabled(const Consensus::Params ¶ms, int nHeight)
static bool IsPhononEnabled(const Consensus::Params ¶ms, int32_t nHeight)
static bool IsGravitonEnabled(const Consensus::Params ¶ms, int32_t nHeight)
bool IsMagneticAnomalyEnabled(const Consensus::Params ¶ms, int32_t nHeight)
Check if Nov 15, 2018 HF has activated using block height.
bool MoneyRange(const Amount nValue)
static constexpr Amount SATOSHI
static constexpr Amount COIN
arith_uint256 UintToArith256(const uint256 &a)
bool isAvalancheEnabled(const ArgsManager &argsman)
std::unique_ptr< avalanche::Processor > g_avalanche
Global avalanche instance.
void ForEachBlockFilterIndex(std::function< void(BlockFilterIndex &)> fn)
Iterate over all running block filter indexes, invoking fn on each.
@ CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends,...
@ TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ SCRIPTS
Scripts & signatures ok.
@ TREE
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
arith_uint256 GetBlockProof(const CBlockIndex &block)
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
bool AreOnTheSameFork(const CBlockIndex *pa, const CBlockIndex *pb)
Check if two block index are on the same fork.
std::map< int, const AssumeutxoData > MapAssumeutxo
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
const fs::path & GetBlocksDirPath() const
Get blocks directory path.
const fs::path & GetDataDirNet() const
Get data directory path with appended network identifier.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Non-refcounted RAII wrapper for FILE*.
std::string ToString() const
IndexSummary GetSummary() const
Get a summary of the index and its state.
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
uint64_t getExcessiveBlockSize() const
BlockValidationOptions withCheckPoW(bool _checkPoW=true) const
BlockValidationOptions withCheckMerkleRoot(bool _checkMerkleRoot=true) const
BlockValidationOptions(const Config &config)
bool shouldValidatePoW() const
bool shouldValidateMerkleRoot() const
std::string ToString() const
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
bool IsValid(enum BlockValidity nUpTo=BlockValidity::TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
std::string ToString() const
CBlockIndex * pprev
pointer to the index of the predecessor of this block
bool IsAssumedValid() const EXCLUSIVE_LOCKS_REQUIRED(
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
const BlockHash * phashBlock
pointer to the hash of the block, if any.
bool HaveTxsDownloaded() const
Check whether this block's and all previous blocks' transactions have been downloaded (and stored to ...
int64_t GetChainTxCount() const
Get the number of transaction in the chain so far.
int32_t nSequenceId
(memory only) Sequential id assigned to distinguish order in which blocks are received.
int64_t GetReceivedTimeDiff() const
int64_t GetBlockTime() const
int64_t GetMedianTimePast() const
FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(
bool UpdateChainStats()
Update chain tx stats.
CBlockIndex * pskip
pointer to the index of some further predecessor of this block
unsigned int nTx
Number of transactions in this block.
bool RaiseValidity(enum BlockValidity nUpTo) EXCLUSIVE_LOCKS_REQUIRED(
Raise the validity level of this block index entry.
int32_t nVersion
block header
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
BlockHash GetBlockHash() const
unsigned int nSize
Size of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
unsigned int nChainTx
(memory only) Number of transactions in the chain up to and including this block.
Undo information for a CBlock.
std::vector< CTxUndo > vtxundo
Non-refcounted RAII wrapper around a FILE* that implements a ring buffer to deserialize from.
CBlockIndex * Genesis() const
Returns the index entry for the genesis block of this chain, or nullptr if none.
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
int Height() const
Return the maximal height in the chain.
const CBlockIndex * FindFork(const CBlockIndex *pindex) const
Find the last common block between this chain and a block index entry.
void SetTip(CBlockIndex *pindex)
Set/initialize a chain with a given tip.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CBlockLocator GetLocator() const
Return a CBlockLocator that refers to the tip of this chain.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const ChainTxData & TxData() const
const CCheckpointData & Checkpoints() const
const MapAssumeutxo & Assumeutxo() const
Get allowed assumeutxo configuration.
const CMessageHeader::MessageMagic & DiskMagic() const
const Consensus::Params & GetConsensus() const
uint64_t PruneAfterHeight() const
const CBlock & GenesisBlock() const
RAII-style controller object for a CCheckQueue that guarantees the passed queue is finished before co...
void Add(std::vector< T > &vChecks)
Queue for verifications that have to be performed.
void SetBackend(CCoinsView &viewIn)
CCoinsView that adds a memory cache for transactions to another CCoinsView.
void AddCoin(const COutPoint &outpoint, Coin coin, bool possible_overwrite)
Add a coin.
BlockHash GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
bool SpendCoin(const COutPoint &outpoint, Coin *moveto=nullptr)
Spend a coin.
void Uncache(const COutPoint &outpoint)
Removes the UTXO with the given outpoint from the cache, if it is not modified.
void SetBestBlock(const BlockHash &hashBlock)
unsigned int GetCacheSize() const
Calculate the size of the cache (in number of transaction outputs)
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
bool HaveCoinInCache(const COutPoint &outpoint) const
Check if we have the given utxo already loaded in this cache.
bool Flush()
Push the modifications applied to this cache to its base.
size_t DynamicMemoryUsage() const
Calculate the size of the cache (in bytes)
void EmplaceCoinInternalDANGER(COutPoint &&outpoint, Coin &&coin)
Emplace a coin into cacheCoins without performing any checks, marking the emplaced coin as dirty.
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or coinEmpty if not found.
void ReallocateCache()
Force a reallocation of the cache map.
CCoinsView backed by the coin database (chainstate/)
std::optional< fs::path > StoragePath()
void ResizeCache(size_t new_cache_size) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Dynamically alter the underlying leveldb cache size.
Abstract view on the open txout dataset.
virtual bool GetCoin(const COutPoint &outpoint, Coin &coin) const
Retrieve the Coin (unspent transaction output) for a given outpoint.
CCoinsView that brings transactions from a mempool into view.
void BlockConnected(const std::shared_ptr< const CBlock > &, const CBlockIndex *pindex)
void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)
void BlockDisconnected(const std::shared_ptr< const CBlock > &, const CBlockIndex *pindex)
void BlockChecked(const CBlock &, const BlockValidationState &)
void BlockFinalized(const CBlockIndex *)
void TransactionAddedToMempool(const CTransactionRef &, std::shared_ptr< const std::vector< Coin >>, uint64_t mempool_sequence)
void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr< const CBlock > &)
void ChainStateFlushed(const CBlockLocator &)
An outpoint - a combination of a transaction hash and an index n into its vout.
const TxId & GetTxId() const
void insert(Span< const uint8_t > vKey)
bool contains(Span< const uint8_t > vKey) const
Closure representing one script verification.
ScriptError GetScriptError() const
ScriptExecutionMetrics GetScriptExecutionMetrics() const
TxSigCheckLimiter * pTxLimitSigChecks
ScriptExecutionMetrics metrics
PrecomputedTransactionData txdata
const CTransaction * ptxTo
CheckInputsLimiter * pBlockLimitSigChecks
Serialized script, used inside transaction inputs and outputs.
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxOut > vout
unsigned int GetTotalSize() const
Get the total transaction size in bytes.
const std::vector< CTxIn > vin
An input of a transaction.
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
void AddTransactionsUpdated(unsigned int n)
const int64_t m_max_size_bytes
size_t DynamicMemoryUsage() const
void SetLoadTried(bool load_tried)
Set whether or not we've made an attempt to load the mempool (regardless of whether the attempt was s...
Restore the UTXO in a Coin at a given COutPoint.
std::vector< Coin > vprevout
VerifyDBResult VerifyDB(Chainstate &chainstate, CCoinsView &coinsview, int nCheckLevel, int nCheckDepth) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Chainstate stores and provides an API to update our local knowledge of the current best chain.
std::set< CBlockIndex *, CBlockIndexWorkComparator > setBlockIndexCandidates
The set of all CBlockIndex entries with either BLOCK_VALID_TRANSACTIONS (for itself and all ancestors...
bool IsBlockAvalancheFinalized(const CBlockIndex *pindex) const EXCLUSIVE_LOCKS_REQUIRED(!cs_avalancheFinalizedBlockIndex)
Checks if a block is finalized by avalanche voting.
const std::optional< BlockHash > m_from_snapshot_blockhash
The blockhash which is the base of the snapshot this chainstate was created from.
CTxMemPool * GetMempool()
void CheckForkWarningConditionsOnNewFork(CBlockIndex *pindexNewForkTip) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Mutex m_chainstate_mutex
The ChainState Mutex.
void UnloadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
void UpdateFlags(CBlockIndex *pindex, CBlockIndex *&pindexReset, F f, C fChild, AC fAncestorWasChanged) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
CBlockIndex * FindMostWorkChain(std::vector< const CBlockIndex * > &blocksToReconcile) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Return the tip of the chain with the most work in it, that isn't known to be invalid (it's however fa...
CChain m_chain
The current chain of blockheaders we consult and build on.
bool HasCoinsViews() const
Does this chainstate have a UTXO set attached?
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network)
bool RollforwardBlock(const CBlockIndex *pindex, CCoinsViewCache &inputs) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Apply the effects of a block on the utxo cache, ignoring that it may already have been applied.
size_t m_coinstip_cache_size_bytes
The cache size of the in-memory coins view.
bool LoadChainTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Update the chain tip based on database information, i.e.
size_t m_coinsdb_cache_size_bytes
The cache size of the on-disk coins view.
int32_t nBlockReverseSequenceId
Decreasing counter (used by subsequent preciousblock calls).
void UnparkBlockImpl(CBlockIndex *pindex, bool fClearChildren) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Chainstate(CTxMemPool *mempool, node::BlockManager &blockman, ChainstateManager &chainman, std::optional< BlockHash > from_snapshot_blockhash=std::nullopt)
CCoinsViewDB & CoinsDB() EXCLUSIVE_LOCKS_REQUIRED(
void InvalidBlockFound(CBlockIndex *pindex, const BlockValidationState &state) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Mutex cs_avalancheFinalizedBlockIndex
void ForceFlushStateToDisk()
Unconditionally flush all changes to disk.
bool AvalancheFinalizeBlock(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs_avalancheFinalizedBlockIndex)
Mark a block as finalized by avalanche.
bool LoadGenesisBlock()
Ensures we have a genesis block in the block tree, possibly writing one to disk.
void UpdateTip(const CBlockIndex *pindexNew) EXCLUSIVE_LOCKS_REQUIRED(std::chrono::microsecond m_last_write)
Check warning conditions and do some notifications on new chain tip set.
void UnparkBlockAndChildren(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Remove parked status from a block and its descendants.
CTxMemPool * m_mempool
Optional mempool that is kept in sync with the chain.
bool reliesOnAssumedValid()
Return true if this chainstate relies on blocks that are assumed-valid.
void LoadMempool(const fs::path &load_path, fsbridge::FopenFn mockable_fopen_function=fsbridge::fopen)
Load the persisted mempool from disk.
arith_uint256 nLastPreciousChainwork
chainwork for the last block that preciousblock has been applied to.
std::chrono::microseconds m_last_flush
bool DisconnectTip(BlockValidationState &state, DisconnectedBlockTransactions *disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Disconnect m_chain's tip.
bool UnwindBlock(BlockValidationState &state, CBlockIndex *pindex, bool invalidate) EXCLUSIVE_LOCKS_REQUIRED(m_chainstate_mutex
bool InvalidateBlock(BlockValidationState &state, CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex
Mark a block as invalid.
ChainstateManager & m_chainman
The chainstate manager that owns this chainstate.
std::unique_ptr< CoinsViews > m_coins_views
Manages the UTXO set, which is a reflection of the contents of m_chain.
CRollingBloomFilter m_filterParkingPoliciesApplied
Filter to prevent parking a block due to block policies more than once.
bool ReplayBlocks()
Replay blocks that aren't fully applied to the database.
void ReceivedBlockTransactions(const CBlock &block, CBlockIndex *pindexNew, const FlatFilePos &pos) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS).
void ResetBlockFailureFlags(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Remove invalidity status from a block and its descendants.
bool ActivateBestChain(BlockValidationState &state, std::shared_ptr< const CBlock > pblock=nullptr, bool skip_checkblockindex=false) EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex
Find the best known block, and make it the tip of the block chain.
bool PreciousBlock(BlockValidationState &state, CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex
Mark a block as precious and reorganize.
void CheckBlockIndex()
Make various assertions about the state of the block index.
void PruneBlockIndexCandidates()
Delete all entries in setBlockIndexCandidates that are worse than the current tip.
DisconnectResult DisconnectBlock(const CBlock &block, const CBlockIndex *pindex, CCoinsViewCache &view) EXCLUSIVE_LOCKS_REQUIRED(boo ConnectBlock)(const CBlock &block, BlockValidationState &state, CBlockIndex *pindex, CCoinsViewCache &view, BlockValidationOptions options, Amount *blockFees=nullptr, bool fJustCheck=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Apply the effects of this block (with given index) on the UTXO set represented by coins.
bool ConnectTip(BlockValidationState &state, BlockPolicyValidationState &blockPolicyState, CBlockIndex *pindexNew, const std::shared_ptr< const CBlock > &pblock, ConnectTrace &connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Connect a new block to m_chain.
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
CBlockIndex const * m_best_fork_tip
void PruneAndFlush()
Prune blockfiles from the disk if necessary and then flush chainstate changes if we pruned.
bool FlushStateToDisk(BlockValidationState &state, FlushStateMode mode, int nManualPruneHeight=0)
Update the on-disk chain state.
node::BlockManager & m_blockman
Reference to a BlockManager instance which itself is shared across all Chainstate instances.
void InitCoinsDB(size_t cache_size_bytes, bool in_memory, bool should_wipe, std::string leveldb_name="chainstate")
Initialize the CoinsViews UTXO set database management data structures.
bool ActivateBestChainStep(BlockValidationState &state, CBlockIndex *pindexMostWork, const std::shared_ptr< const CBlock > &pblock, bool &fInvalidFound, ConnectTrace &connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Try to make some progress towards making pindexMostWork the active block.
CBlockIndex const * m_best_fork_base
void InvalidChainFound(CBlockIndex *pindexNew) EXCLUSIVE_LOCKS_REQUIRED(cs_main
std::atomic< bool > m_cached_finished_ibd
Whether this chainstate is undergoing initial block download.
void UnparkBlock(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Remove parked status from a block.
void ClearAvalancheFinalizedBlock() EXCLUSIVE_LOCKS_REQUIRED(!cs_avalancheFinalizedBlockIndex)
Clear avalanche finalization.
const CBlockIndex * FindForkInGlobalIndex(const CBlockLocator &locator) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Find the last common block of this chain and a locator.
std::atomic< int32_t > nBlockSequenceId
Every received block is assigned a unique and increasing identifier, so we know which one to give pri...
bool UpdateFlagsForBlock(CBlockIndex *pindexBase, CBlockIndex *pindex, F f) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool AcceptBlock(const std::shared_ptr< const CBlock > &pblock, BlockValidationState &state, bool fRequested, const FlatFilePos *dbp, bool *fNewBlock, bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Store a block on disk.
bool ParkBlock(BlockValidationState &state, CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex
Park a block.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
int64_t m_total_coinstip_cache
The total number of bytes available for us to use across all in-memory coins caches.
const CChainParams & GetParams() const
const arith_uint256 & MinimumChainWork() const
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
int64_t m_total_coinsdb_cache
The total number of bytes available for us to use across all leveldb coins databases.
bool AcceptBlockHeader(const CBlockHeader &block, BlockValidationState &state, CBlockIndex **ppindex, bool min_pow_checked, const std::optional< CCheckpointData > &test_checkpoints=std::nullopt) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
If a block header hasn't already been seen, call CheckBlockHeader on it, ensure that it doesn't desce...
bool ShouldCheckBlockIndex() const
const Config & GetConfig() const
const BlockHash & AssumedValidBlock() const
std::optional< BlockHash > SnapshotBlockhash() const
bool IsSnapshotValidated() const EXCLUSIVE_LOCKS_REQUIRED(
Is there a snapshot in use and has it been fully validated?
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
bool PopulateAndValidateSnapshot(Chainstate &snapshot_chainstate, AutoFile &coins_file, const node::SnapshotMetadata &metadata)
Internal helper for ActivateSnapshot().
int ActiveHeight() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
bool ActivateSnapshot(AutoFile &coins_file, const node::SnapshotMetadata &metadata, bool in_memory)
Construct and activate a Chainstate on the basis of UTXO snapshot data.
bool IsSnapshotActive() const
bool ProcessNewBlockHeaders(const std::vector< CBlockHeader > &block, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr, const std::optional< CCheckpointData > &test_checkpoints=std::nullopt) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
bool LoadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Load the block tree and coins database from disk, initializing state if we're running with -reindex.
ChainstateManager(Options options, node::BlockManager::Options blockman_options)
Chainstate &InitializeChainstate(CTxMemPool *mempool) EXCLUSIVE_LOCKS_REQUIRED(std::vector< Chainstate * GetAll)()
Instantiate a new chainstate.
std::set< CBlockIndex * > m_failed_blocks
In order to efficiently track invalidity of headers, we keep the set of blocks which we tried to conn...
const Consensus::Params & GetConsensus() const
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
uint32_t GetHeight() const
CoinsViews(std::string ldb_name, size_t cache_size_bytes, bool in_memory, bool should_wipe)
This constructor initializes CCoinsViewDB and CCoinsViewErrorCatcher instances, but it does not creat...
virtual const CChainParams & GetChainParams() const =0
Used to track blocks whose transactions were applied to the UTXO state as a part of a single Activate...
std::vector< PerBlockConnectTrace > blocksConnected
std::vector< PerBlockConnectTrace > & GetBlocksConnected()
void BlockConnected(CBlockIndex *pindex, std::shared_ptr< const CBlock > pblock)
void updateMempoolForReorg(Chainstate &active_chainstate, bool fAddToMempool, CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Make mempool consistent after a reorg, by re-adding or recursively erasing disconnected block transac...
void addForBlock(const std::vector< CTransactionRef > &vtx, CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
void importMempool(CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
Different type to mark Mutex at global scope.
static RCUPtr acquire(T *&ptrIn)
Acquire ownership of some pointer.
The script cache is a map using a key/value element, that caches the success of executing a specific ...
static TxSigCheckLimiter getDisabled()
std::string GetRejectReason() const
std::string GetDebugMessage() const
bool Error(const std::string &reject_reason)
bool Invalid(Result result, const std::string &reject_reason="", const std::string &debug_message="")
std::string ToString() const
256-bit unsigned big integer.
std::string ToString() const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
RecursiveMutex cs_LastBlockFile
void FindFilesToPrune(std::set< int > &setFilesToPrune, uint64_t nPruneAfterHeight, int chain_tip_height, int prune_height, bool is_ibd)
Prune block and undo files (blk???.dat and undo???.dat) so that the disk space used is less than a us...
void FindFilesToPruneManual(std::set< int > &setFilesToPrune, int nManualPruneHeight, int chain_tip_height)
Calculate the block/rev files to delete based on height specified by user with RPC command pruneblock...
CBlockIndex * LookupBlockIndex(const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool WriteUndoDataForBlock(const CBlockUndo &blockundo, BlockValidationState &state, CBlockIndex &block) EXCLUSIVE_LOCKS_REQUIRED(FlatFilePos SaveBlockToDisk(const CBlock &block, int nHeight, CChain &active_chain, const FlatFilePos *dbp)
Store block on disk.
bool LoadingBlocks() const
std::set< CBlockIndex * > m_dirty_blockindex
Dirty block index entries.
bool m_check_for_pruning
Global flag to indicate we should check to see if there are block/undo files that should be deleted.
bool IsPruneMode() const
Whether running in -prune mode.
bool m_have_pruned
True if any block files have ever been pruned.
std::vector< CBlockIndex * > GetAllBlockIndices() EXCLUSIVE_LOCKS_REQUIRED(std::multimap< CBlockIndex *, CBlockIndex * > m_blocks_unlinked
All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions.
void FlushBlockFile(bool fFinalize=false, bool finalize_undo=false)
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
const Coin & AccessByTxid(const CCoinsViewCache &view, const TxId &txid)
Utility function to find any unspent output with a given txid.
void AddCoins(CCoinsViewCache &cache, const CTransaction &tx, int nHeight, bool check_for_overwrite)
Utility function to add all of a transaction's outputs to a cache.
@ BLOCK_CHECKPOINT
the block failed to meet one of our checkpoints
@ BLOCK_HEADER_LOW_WORK
the block header may be on a too-little-work chain
@ BLOCK_INVALID_HEADER
invalid proof of work or time too old
@ BLOCK_CACHED_INVALID
this block was cached as being invalid and we didn't store the reason why
@ BLOCK_CONSENSUS
invalid by consensus rules (excluding any below reasons)
@ BLOCK_MISSING_PREV
We don't have the previous block the checked one is built on.
@ BLOCK_INVALID_PREV
A block this one builds on is invalid.
@ BLOCK_MUTATED
the block's data didn't match the data committed to by the PoW
@ BLOCK_TIME_FUTURE
block timestamp was > 2 hours in the future (or our clock is bad)
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
@ TX_CHILD_BEFORE_PARENT
This tx outputs are already spent in the mempool.
@ TX_MEMPOOL_POLICY
violated mempool's fee/size/descendant/etc limits
@ TX_PREMATURE_SPEND
transaction spends a coinbase too early, or violates locktime/sequence locks
@ TX_DUPLICATE
Tx already in mempool or in the chain.
@ TX_INPUTS_NOT_STANDARD
inputs failed policy rules
@ TX_CONFLICT
Tx conflicts with another mempool tx, i.e.
@ TX_NOT_STANDARD
otherwise didn't meet our local policy rules
@ TX_NO_MEMPOOL
this node does not have a mempool so can't validate the transaction
@ TX_CONSENSUS
invalid by consensus rules
static constexpr unsigned int LOCKTIME_VERIFY_SEQUENCE
Flags for nSequence and nLockTime locks.
static const uint64_t MAX_TX_SIZE
The maximum allowed size for a transaction, in bytes.
uint64_t GetMaxBlockSigChecksCount(uint64_t maxBlockSize)
Compute the maximum number of sigchecks that can be contained in a block given the MAXIMUM block size...
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep)
Determine if a deployment is active for the next block.
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep)
Determine if a deployment is active for this block.
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, uint32_t flags, const BaseSignatureChecker &checker, ScriptExecutionMetrics &metricsOut, ScriptError *serror)
Execute an unlocking and locking script together.
static void LoadExternalBlockFile(benchmark::Bench &bench)
The LoadExternalBlockFile() function is used during -reindex and -loadblock.
#define LogPrint(category,...)
uint256 BlockMerkleRoot(const CBlock &block, bool *mutated)
Compute the Merkle root of the transactions in a block.
bool CheckBlock(const CCheckpointData &data, int nHeight, const BlockHash &hash)
Returns true if block passes checkpoint checks.
bool CheckTxInputs(const CTransaction &tx, TxValidationState &state, const CCoinsViewCache &inputs, int nSpendHeight, Amount &txfee)
Check whether all inputs of this transaction are valid (no double spends and amounts).
static bool exists(const path &p)
static std::string PathToString(const path &path)
Convert path object to byte string.
std::string get_filesystem_error_message(const fs::filesystem_error &e)
std::function< FILE *(const fs::path &, const char *)> FopenFn
bool LoadMempool(CTxMemPool &pool, const fs::path &load_path, Chainstate &active_chainstate, FopenFn mockable_fopen_function)
static const unsigned int UNDOFILE_CHUNK_SIZE
The pre-allocation chunk size for rev?????.dat files (since 0.8)
const fs::path SNAPSHOT_BLOCKHASH_FILENAME
The file in the snapshot chainstate dir which stores the base blockhash.
bool WriteSnapshotBaseBlockhash(Chainstate &snapshot_chainstate)
std::optional< fs::path > FindSnapshotChainstateDir()
Return a path to the snapshot-based chainstate dir, if one exists.
std::unordered_map< BlockHash, CBlockIndex, BlockHasher > BlockMap
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos, const Consensus::Params ¶ms)
Functions for disk access for blocks.
std::optional< BlockHash > ReadSnapshotBaseBlockhash(const fs::path &chaindir)
static bool ComputeUTXOStats(CCoinsView *view, CCoinsStats &stats, T hash_obj, const std::function< void()> &interruption_point)
Calculate statistics about the unspent transaction output set.
void UnlinkPrunedFiles(const std::set< int > &setFilesToPrune)
Actually unlink the specified files.
FILE * OpenBlockFile(const FlatFilePos &pos, bool fReadOnly)
Open a block file (blk?????.dat)
static constexpr unsigned int BLOCKFILE_CHUNK_SIZE
The pre-allocation chunk size for blk?????.dat files (since 0.8)
std::atomic_bool fReindex
bool WriteSnapshotBaseBlockhash(Chainstate &snapshot_chainstate) EXCLUSIVE_LOCKS_REQUIRED(std::optional< BlockHash > constexpr ReadSnapshotBaseBlockhash(const fs::path &chaindir) EXCLUSIVE_LOCKS_REQUIRED(std::string_view SNAPSHOT_CHAINSTATE_SUFFIX
Write out the blockhash of the snapshot base block that was used to construct this chainstate.
bool UndoReadFromDisk(CBlockUndo &blockundo, const CBlockIndex *pindex)
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
Implement std::hash so RCUPtr can be used as a key for maps or sets.
bilingual_str ErrorString(const Result< T > &result)
bool IsChildWithParents(const Package &package)
Context-free check that a package is exactly one child and its parents; not all parents need to be pr...
bool CheckPackage(const Package &txns, PackageValidationState &state)
Context-free package policy checks:
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
@ PCKG_POLICY
The package itself is invalid (e.g. too many transactions).
@ PCKG_TX
At least one tx is invalid.
bool AreInputsStandard(const CTransaction &tx, const CCoinsViewCache &mapInputs, uint32_t flags)
Check transaction inputs to mitigate two potential denial-of-service attacks:
bool IsStandardTx(const CTransaction &tx, const std::optional< unsigned > &max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate &dust_relay_fee, std::string &reason)
Check for standard transaction types.
static constexpr uint32_t STANDARD_SCRIPT_VERIFY_FLAGS
Standard script verification flags that standard transactions will comply with.
static constexpr uint32_t STANDARD_LOCKTIME_VERIFY_FLAGS
Used as the flags parameter to sequence and nLocktime checks in non-consensus code.
static constexpr uint32_t STANDARD_NOT_MANDATORY_VERIFY_FLAGS
For convenience, standard but not mandatory verify flags.
bool CheckProofOfWork(const BlockHash &hash, uint32_t nBits, const Consensus::Params ¶ms)
Check whether a block hash satisfies the proof-of-work requirement specified by nBits.
uint32_t GetNextWorkRequired(const CBlockIndex *pindexPrev, const CBlockHeader *pblock, const CChainParams &chainParams)
std::shared_ptr< const CTransaction > CTransactionRef
uint256 GetRandHash() noexcept
reverse_range< T > reverse_iterate(T &x)
std::string ScriptErrorString(const ScriptError serror)
@ SIGCHECKS_LIMIT_EXCEEDED
@ SCRIPT_VERIFY_SIGPUSHONLY
@ SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY
@ SCRIPT_ENABLE_REPLAY_PROTECTION
@ SCRIPT_ENABLE_SCHNORR_MULTISIG
@ SCRIPT_VERIFY_STRICTENC
@ SCRIPT_ENFORCE_SIGCHECKS
@ SCRIPT_VERIFY_CLEANSTACK
@ SCRIPT_VERIFY_MINIMALDATA
@ SCRIPT_VERIFY_CHECKSEQUENCEVERIFY
@ SCRIPT_ENABLE_SIGHASH_FORKID
void AddKeyInScriptCache(ScriptCacheKey key, int nSigChecks)
Add an entry in the cache.
bool IsKeyInScriptCache(ScriptCacheKey key, bool erase, int &nSigChecksOut)
Check if a given key is in the cache, and if so, return its values.
size_t GetSerializeSize(const T &t, int nVersion=0)
bool ShutdownRequested()
Returns true if a shutdown is requested, false otherwise.
void StartShutdown()
Request shutdown of the application.
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
static constexpr Amount zero() noexcept
Holds configuration for use during UTXO snapshot load and validation.
const AssumeutxoHash hash_serialized
The expected hash of the deserialized UTXO set.
const unsigned int nChainTx
Used to populate the nChainTx value, which is used during BlockManager::LoadBlockIndex().
A BlockHash is a unqiue identifier for a block.
bool isValid(enum BlockValidity nUpTo=BlockValidity::TRANSACTIONS) const
Check whether this block index entry is valid up to the passed validity level.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< BlockHash > vHave
Holds various statistics on transactions within a chain.
Parameters that influence chain consensus.
int BIP34Height
Block height and hash at which BIP34 becomes active.
int nSubsidyHalvingInterval
BlockHash hashGenesisBlock
int64_t nPowTargetSpacing
int augustoActivationTime
Unix time used for MTP activation of 15 Nov 2024 12:00:00 UTC upgrade.
Validation result for a single transaction mempool acceptance.
const ResultType m_result_type
static MempoolAcceptResult Success(int64_t vsize, Amount fees)
Constructor for success case.
@ VALID
Fully validated, valid.
static MempoolAcceptResult Failure(TxValidationState state)
static MempoolAcceptResult MempoolTx(int64_t vsize, Amount fees)
Constructor for already-in-mempool case.
std::chrono::time_point< NodeClock > time_point
Validation result for package mempool acceptance.
std::shared_ptr< const CBlock > pblock
Precompute sighash midstate to avoid quadratic hashing.
const char * what() const override
A TxId is the identifier of a transaction.
An options struct for BlockManager, more ergonomically referred to as BlockManager::Options due to th...
An options struct for ChainstateManager, more ergonomically referred to as ChainstateManager::Options...
const std::function< NodeClock::time_point()> adjusted_time_callback
std::optional< bool > check_block_index
std::chrono::seconds max_tip_age
If the tip is older than this, the node is considered to be in initial block download.
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
bool CheckDiskSpace(const fs::path &dir, uint64_t additional_bytes)
bool error(const char *fmt, const Args &...args)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
#define NO_THREAD_SAFETY_ANALYSIS
int64_t GetTimeMicros()
Returns the system time (not mockable)
int64_t GetTimeMillis()
Returns the system time (not mockable)
std::string FormatISO8601DateTime(int64_t nTime)
ISO 8601 formatting is preferred.
#define LOG_TIME_MILLIS_WITH_CATEGORY(end_msg, log_category)
#define LOG_TIME_MILLIS_WITH_CATEGORY_MSG_ONCE(end_msg, log_category)
#define TRACE6(context, event, a, b, c, d, e, f)
#define TRACE5(context, event, a, b, c, d, e)
bilingual_str _(const char *psz)
Translation function.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
bool CheckRegularTransaction(const CTransaction &tx, TxValidationState &state)
Context-independent validity checks for coinbase and non-coinbase transactions.
bool CheckCoinbase(const CTransaction &tx, TxValidationState &state)
std::pair< int, int64_t > CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector< int > &prevHeights, const CBlockIndex &block)
Calculates the block height and previous block's median time past at which the transaction will be co...
bool EvaluateSequenceLocks(const CBlockIndex &block, std::pair< int, int64_t > lockPair)
bool SequenceLocks(const CTransaction &tx, int flags, std::vector< int > &prevHeights, const CBlockIndex &block)
Check if transaction is final per BIP 68 sequence numbers and can be included in a block.
bool ContextualCheckTransaction(const Consensus::Params ¶ms, const CTransaction &tx, TxValidationState &state, int nHeight, int64_t nMedianTimePast)
Context dependent validity checks for non coinbase transactions.
static const uint32_t MEMPOOL_HEIGHT
Fake height value used in Coins to signify they are only in the memory pool(since 0....
CClientUIInterface uiInterface
uint256 uint256S(const char *str)
uint256 from const char *.
static bool DeleteCoinsDBFromDisk(const fs::path &db_path, bool is_snapshot) EXCLUSIVE_LOCKS_REQUIRED(
void StartScriptCheckWorkerThreads(int threads_num)
Run instances of script checking worker threads.
bool ContextualCheckTransactionForCurrentBlock(const CBlockIndex *active_chain_tip, const Consensus::Params ¶ms, const CTransaction &tx, TxValidationState &state)
static int64_t nTimeConnectTotal
GlobalMutex g_best_block_mutex
Amount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams)
std::condition_variable g_best_block_cv
static void AlertNotify(const std::string &strMessage)
arith_uint256 CalculateHeadersWork(const std::vector< CBlockHeader > &headers)
Return the sum of the work on a given set of headers.
DisconnectResult ApplyBlockUndo(CBlockUndo &&blockUndo, const CBlock &block, const CBlockIndex *pindex, CCoinsViewCache &view)
Undo a block from the block and the undoblock data.
double GuessVerificationProgress(const ChainTxData &data, const CBlockIndex *pindex)
Guess how far we are in the verification process at the given block index require cs_main if pindex h...
MempoolAcceptResult AcceptToMemoryPool(Chainstate &active_chainstate, const CTransactionRef &tx, int64_t accept_time, bool bypass_limits, bool test_accept, unsigned int heightOverride)
Try to add a transaction to the mempool.
static int64_t nBlocksTotal
static int64_t nTimePostConnect
static bool CheckBlockHeader(const CBlockHeader &block, BlockValidationState &state, const Consensus::Params ¶ms, BlockValidationOptions validationOptions)
Return true if the provided block header is valid.
static SynchronizationState GetSynchronizationState(bool init)
static void SnapshotUTXOHashBreakpoint()
static int64_t nTimeFlush
static bool ContextualCheckBlock(const CBlock &block, BlockValidationState &state, const ChainstateManager &chainman, const CBlockIndex *pindexPrev)
NOTE: This function is not currently invoked by ConnectBlock(), so we should consider upgrade issues ...
static uint32_t GetNextBlockScriptFlags(const CBlockIndex *pindex, const ChainstateManager &chainman)
bool HasValidProofOfWork(const std::vector< CBlockHeader > &headers, const Consensus::Params &consensusParams)
Check with the proof of work on each blockheader matches the value in nBits.
static constexpr std::chrono::hours DATABASE_FLUSH_INTERVAL
Time to wait between flushing chainstate to disk.
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept)
Validate (and maybe submit) a package to the mempool.
static int64_t nTimeVerify
const AssumeutxoData * ExpectedAssumeutxo(const int height, const CChainParams &chainparams)
Return the expected assumeutxo value for a given height, if one exists.
void StopScriptCheckWorkerThreads()
Stop all of the script checking worker threads.
static void LimitValidationInterfaceQueue() LOCKS_EXCLUDED(cs_main)
return CheckInputScripts(tx, state, view, flags, true, true, txdata, nSigChecksOut)
static bool CheckInputsFromMempoolAndCache(const CTransaction &tx, TxValidationState &state, const CCoinsViewCache &view, const CTxMemPool &pool, const uint32_t flags, PrecomputedTransactionData &txdata, int &nSigChecksOut, CCoinsViewCache &coins_tip) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Checks to avoid mempool polluting consensus critical paths since cached signature and script validity...
void SpendCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo, int nHeight)
Mark all the coins corresponding to a given transaction inputs as spent.
static int64_t nTimeTotal
static int64_t nTimeConnect
static bool NotifyHeaderTip(Chainstate &chainstate) LOCKS_EXCLUDED(cs_main)
bool CheckBlock(const CBlock &block, BlockValidationState &state, const Consensus::Params ¶ms, BlockValidationOptions validationOptions)
Functions for validating blocks and updating the block tree.
const std::vector< std::string > CHECKLEVEL_DOC
Documentation for argument 'checklevel'.
static ChainstateManager::Options && Flatten(ChainstateManager::Options &&opts)
Apply default chain params to nullopt members.
DisconnectResult UndoCoinSpend(Coin &&undo, CCoinsViewCache &view, const COutPoint &out)
Restore the UTXO in a Coin at a given COutPoint.
static int64_t nTimeIndex
bool TestBlockValidity(BlockValidationState &state, const CChainParams ¶ms, Chainstate &chainstate, const CBlock &block, CBlockIndex *pindexPrev, const std::function< NodeClock::time_point()> &adjusted_time_callback, BlockValidationOptions validationOptions)
void PruneBlockFilesManual(Chainstate &active_chainstate, int nManualPruneHeight)
Prune block files up to a given height.
static void FlushSnapshotToDisk(CCoinsViewCache &coins_cache, bool snapshot_loaded)
bool AbortNode(BlockValidationState &state, const std::string &strMessage, const bilingual_str &userMessage)
void UpdateCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo, int nHeight)
Apply the effects of this transaction on the UTXO set represented by view.
static bool ContextualCheckBlockHeader(const CBlockHeader &block, BlockValidationState &state, BlockManager &blockman, ChainstateManager &chainman, const CBlockIndex *pindexPrev, NodeClock::time_point now, const std::optional< CCheckpointData > &test_checkpoints=std::nullopt) EXCLUSIVE_LOCKS_REQUIRED(
Context-dependent validity checks.
static int64_t nTimeForks
static int64_t nTimeCheck
uint256 g_best_block
Used to notify getblocktemplate RPC of new tips.
static void UpdateTipLog(const CCoinsViewCache &coins_tip, const CBlockIndex *tip, const CChainParams ¶ms, const std::string &func_name, const std::string &prefix) EXCLUSIVE_LOCKS_REQUIRED(
static constexpr std::chrono::hours DATABASE_WRITE_INTERVAL
Time to wait between writing blocks/block index to disk.
static int64_t nTimeChainState
static CCheckQueue< CScriptCheck > scriptcheckqueue(128)
static int64_t nTimeReadFromDisk
bool CheckSequenceLocksAtTip(CBlockIndex *tip, const CCoinsView &coins_view, const CTransaction &tx, LockPoints *lp, bool useExistingLockPoints)
Check if transaction will be BIP68 final in the next block to be created on top of tip.
static bool IsReplayProtectionEnabled(const Consensus::Params ¶ms, int64_t nMedianTimePast)
#define MIN_TRANSACTION_SIZE
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...
@ BASE_BLOCKHASH_MISMATCH
SynchronizationState
Current sync state passed to tip changed callbacks.
@ LARGE
The cache is at >= 90% capacity.
@ CRITICAL
The coins cache is in immediate need of a flush.
static const int DEFAULT_STOPATHEIGHT
Default for -stopatheight.
CMainSignals & GetMainSignals()
void SyncWithValidationInterfaceQueue()
This is a synonym for the following, which asserts certain locks are not held: std::promise<void> pro...
static const int PROTOCOL_VERSION
network protocol versioning
void SetfLargeWorkInvalidChainFound(bool flag)
void SetfLargeWorkForkFound(bool flag)
bool GetfLargeWorkForkFound()