81 #define MICRO 0.000001
93 "level 0 reads the blocks from disk",
94 "level 1 verifies block validity",
95 "level 2 verifies undo data",
96 "level 3 checks disconnection of tip blocks",
97 "level 4 tries to reconnect the blocks",
98 "each level includes the checks of the previous levels",
154 std::vector<CScriptCheck>* pvChecks =
nullptr)
168 const int nBlockHeight = active_chain_tip->nHeight + 1;
175 const int64_t nBlockTime{active_chain_tip->GetMedianTimePast()};
177 return IsFinalTx(tx, nBlockHeight, nBlockTime);
184 bool useExistingLockPoints)
198 std::pair<int, int64_t> lockPair;
199 if (useExistingLockPoints) {
202 lockPair.second =
lp->
time;
205 std::vector<int> prevheights;
206 prevheights.resize(tx.
vin.size());
207 for (
size_t txinIndex = 0; txinIndex < tx.
vin.size(); txinIndex++) {
208 const CTxIn& txin = tx.
vin[txinIndex];
211 return error(
"%s: Missing input", __func__);
215 prevheights[txinIndex] = tip->
nHeight + 1;
217 prevheights[txinIndex] = coin.
nHeight;
223 lp->
time = lockPair.second;
237 int maxInputHeight = 0;
238 for (
const int height : prevheights) {
240 if (height != tip->
nHeight+1) {
241 maxInputHeight = std::max(maxInputHeight, height);
263 int expired = pool.Expire(GetTime<std::chrono::seconds>() - age);
268 std::vector<COutPoint> vNoSpendsRemaining;
269 pool.TrimToSize(limit, &vNoSpendsRemaining);
270 for (
const COutPoint& removed : vNoSpendsRemaining)
271 coins_cache.Uncache(removed);
277 if (active_chainstate.IsInitialBlockDownload())
281 if (active_chainstate.m_chain.Height() < active_chainstate.m_chainman.m_best_header->nHeight - 1) {
295 std::vector<uint256> vHashUpdate;
305 if (!fAddToMempool || (*it)->IsCoinBase() ||
307 true,
false).m_result_type !=
313 vHashUpdate.push_back((*it)->GetHash());
350 }
else if (!validLP) {
357 if (it->GetSpendsCoinbase()) {
365 if (coin.IsCoinBase() && mempool_spend_height - coin.nHeight <
COINBASE_MATURITY) {
381 std::chrono::hours{gArgs.GetIntArg(
"-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
404 if (coin.
IsSpent())
return false;
416 const Coin& coinFromUTXOSet = coins_tip.AccessCoin(txin.
prevout);
431 explicit MemPoolAccept(
CTxMemPool& mempool,
CChainState& active_chainstate) : m_pool(mempool), m_view(&m_dummy), m_viewmempool(&active_chainstate.CoinsTip(), m_pool), m_active_chainstate(active_chainstate),
442 const int64_t m_accept_time;
443 const bool m_bypass_limits;
451 std::vector<COutPoint>& m_coins_to_uncache;
452 const bool m_test_accept;
456 const bool m_allow_bip125_replacement;
461 const bool m_package_submission;
465 const bool m_package_feerates;
468 static ATMPArgs SingleAccept(
const CChainParams& chainparams, int64_t accept_time,
469 bool bypass_limits, std::vector<COutPoint>& coins_to_uncache,
471 return ATMPArgs{ chainparams,
483 static ATMPArgs PackageTestAccept(
const CChainParams& chainparams, int64_t accept_time,
484 std::vector<COutPoint>& coins_to_uncache) {
485 return ATMPArgs{ chainparams,
497 static ATMPArgs PackageChildWithParents(
const CChainParams& chainparams, int64_t accept_time,
498 std::vector<COutPoint>& coins_to_uncache) {
499 return ATMPArgs{ chainparams,
511 static ATMPArgs SingleInPackageAccept(
const ATMPArgs& package_args) {
512 return ATMPArgs{ package_args.m_chainparams,
513 package_args.m_accept_time,
515 package_args.m_coins_to_uncache,
516 package_args.m_test_accept,
529 std::vector<COutPoint>& coins_to_uncache,
531 bool allow_bip125_replacement,
532 bool package_submission,
533 bool package_feerates)
534 : m_chainparams{chainparams},
535 m_accept_time{accept_time},
536 m_bypass_limits{bypass_limits},
537 m_coins_to_uncache{coins_to_uncache},
538 m_test_accept{test_accept},
539 m_allow_bip125_replacement{allow_bip125_replacement},
540 m_package_submission{package_submission},
541 m_package_feerates{package_feerates}
566 explicit Workspace(
const CTransactionRef& ptx) : m_ptx(ptx), m_hash(ptx->GetHash()) {}
568 std::set<uint256> m_conflicts;
578 std::unique_ptr<CTxMemPoolEntry> m_entry;
582 std::list<CTransactionRef> m_replaced_transactions;
594 size_t m_conflicting_size{0};
616 bool PackageMempoolChecks(
const std::vector<CTransactionRef>& txns,
639 std::map<const uint256, const MempoolAcceptResult>& results)
648 if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) {
667 const size_t m_limit_ancestors;
668 const size_t m_limit_ancestor_size;
671 size_t m_limit_descendants;
672 size_t m_limit_descendant_size;
678 bool MemPoolAccept::PreChecks(ATMPArgs&
args, Workspace& ws)
684 const uint256& hash = ws.m_hash;
687 const int64_t nAcceptTime =
args.m_accept_time;
688 const bool bypass_limits =
args.m_bypass_limits;
689 std::vector<COutPoint>& coins_to_uncache =
args.m_coins_to_uncache;
693 std::unique_ptr<CTxMemPoolEntry>& entry = ws.m_entry;
735 if (ptxConflicting) {
736 if (!
args.m_allow_bip125_replacement) {
740 if (!ws.m_conflicts.count(ptxConflicting->
GetHash()))
753 ws.m_conflicts.insert(ptxConflicting->
GetHash());
759 m_view.SetBackend(m_viewmempool);
765 coins_to_uncache.push_back(txin.
prevout);
771 if (!m_view.HaveCoin(txin.
prevout)) {
773 for (
size_t out = 0; out < tx.
vout.size(); out++) {
786 m_view.GetBestBlock();
791 m_view.SetBackend(m_dummy);
793 assert(m_active_chainstate.m_blockman.LookupBlockIndex(m_view.GetBestBlock()) == m_active_chainstate.m_chain.Tip());
820 ws.m_modified_fees = ws.m_base_fees;
821 m_pool.ApplyDelta(hash, ws.m_modified_fees);
825 bool fSpendsCoinbase =
false;
827 const Coin &coin = m_view.AccessCoin(txin.
prevout);
829 fSpendsCoinbase =
true;
834 entry.reset(
new CTxMemPoolEntry(ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(),
835 fSpendsCoinbase, nSigOpsCost,
lp));
836 ws.m_vsize = entry->GetTxSize();
845 if (!bypass_limits && !
args.m_package_feerates && !
CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state))
return false;
847 ws.m_iters_conflicting = m_pool.GetIterSet(ws.m_conflicts);
849 if (ws.m_conflicts.size() == 1) {
877 assert(ws.m_iters_conflicting.size() == 1);
880 m_limit_descendants += 1;
881 m_limit_descendant_size += conflict->GetSizeWithDescendants();
884 std::string errString;
885 if (!m_pool.CalculateMemPoolAncestors(*entry, ws.m_ancestors, m_limit_ancestors, m_limit_ancestor_size, m_limit_descendants, m_limit_descendant_size, errString)) {
886 ws.m_ancestors.clear();
888 std::string dummy_err_string;
901 !m_pool.CalculateMemPoolAncestors(*entry, ws.m_ancestors, 2, m_limit_ancestor_size, m_limit_descendants + 1, m_limit_descendant_size +
EXTRA_DESCENDANT_TX_SIZE_LIMIT, dummy_err_string)) {
916 m_rbf = !ws.m_conflicts.empty();
920 bool MemPoolAccept::ReplacementChecks(Workspace& ws)
926 const uint256& hash = ws.m_hash;
929 CFeeRate newFeeRate(ws.m_modified_fees, ws.m_vsize);
944 if (
const auto err_string{
GetEntriesForConflicts(tx, m_pool, ws.m_iters_conflicting, ws.m_all_conflicting)}) {
946 "too many potential replacements", *err_string);
951 "replacement-adds-unconfirmed", *err_string);
956 ws.m_conflicting_fees += it->GetModifiedFee();
957 ws.m_conflicting_size += it->GetTxSize();
959 if (
const auto err_string{
PaysForRBF(ws.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
966 bool MemPoolAccept::PackageMempoolChecks(
const std::vector<CTransactionRef>& txns,
973 assert(std::all_of(txns.cbegin(), txns.cend(), [
this](
const auto& tx)
974 { return !m_pool.exists(GenTxid::Txid(tx->GetHash()));}));
976 std::string err_string;
977 if (!m_pool.CheckPackageLimits(txns, m_limit_ancestors, m_limit_ancestor_size, m_limit_descendants,
978 m_limit_descendant_size, err_string)) {
985 bool MemPoolAccept::PolicyScriptChecks(
const ATMPArgs&
args, Workspace& ws)
996 if (!
CheckInputScripts(tx, state, m_view, scriptVerifyFlags,
true,
false, ws.m_precomputed_txdata)) {
1013 bool MemPoolAccept::ConsensusScriptChecks(
const ATMPArgs&
args, Workspace& ws)
1018 const uint256& hash = ws.m_hash;
1036 unsigned int currentBlockScriptVerifyFlags{
GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)};
1038 ws.m_precomputed_txdata, m_active_chainstate.CoinsTip())) {
1039 LogPrintf(
"BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s\n", hash.
ToString(), state.
ToString());
1046 bool MemPoolAccept::Finalize(
const ATMPArgs&
args, Workspace& ws)
1051 const uint256& hash = ws.m_hash;
1053 const bool bypass_limits =
args.m_bypass_limits;
1055 std::unique_ptr<CTxMemPoolEntry>& entry = ws.m_entry;
1061 it->GetTx().GetHash().ToString(),
1063 FormatMoney(ws.m_modified_fees - ws.m_conflicting_fees),
1064 (
int)entry->GetTxSize() - (
int)ws.m_conflicting_size);
1065 ws.m_replaced_transactions.push_back(it->GetSharedTx());
1075 bool validForFeeEstimation = !bypass_limits && !
args.m_package_submission &&
IsCurrentForFeeEstimation(m_active_chainstate) && m_pool.HasNoInputsOf(tx);
1078 m_pool.addUnchecked(*entry, ws.m_ancestors, validForFeeEstimation);
1084 if (!
args.m_package_submission && !bypass_limits) {
1092 bool MemPoolAccept::SubmitPackage(
const ATMPArgs&
args, std::vector<Workspace>& workspaces,
1094 std::map<const uint256, const MempoolAcceptResult>& results)
1100 assert(std::all_of(workspaces.cbegin(), workspaces.cend(), [
this](
const auto& ws){
1101 return !m_pool.exists(GenTxid::Txid(ws.m_ptx->GetHash())); }));
1103 bool all_submitted =
true;
1108 for (Workspace& ws : workspaces) {
1109 if (!ConsensusScriptChecks(
args, ws)) {
1113 all_submitted =
false;
1115 strprintf(
"BUG! PolicyScriptChecks succeeded but ConsensusScriptChecks failed: %s",
1116 ws.m_ptx->GetHash().ToString()));
1121 std::string unused_err_string;
1122 if(!m_pool.CalculateMemPoolAncestors(*ws.m_entry, ws.m_ancestors, m_limit_ancestors,
1123 m_limit_ancestor_size, m_limit_descendants,
1124 m_limit_descendant_size, unused_err_string)) {
1128 all_submitted =
false;
1130 strprintf(
"BUG! Mempool ancestors or descendants were underestimated: %s",
1131 ws.m_ptx->GetHash().ToString()));
1138 if (!Finalize(
args, ws)) {
1142 all_submitted =
false;
1144 strprintf(
"BUG! Adding to mempool failed: %s", ws.m_ptx->GetHash().ToString()));
1152 std::chrono::hours{gArgs.GetIntArg(
"-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
1156 for (Workspace& ws : workspaces) {
1158 results.emplace(ws.m_ptx->GetWitnessHash(),
1162 all_submitted =
false;
1167 return all_submitted;
1188 if (
args.m_test_accept) {
1207 std::vector<Workspace> workspaces{};
1208 workspaces.reserve(txns.size());
1209 std::transform(txns.cbegin(), txns.cend(), std::back_inserter(workspaces),
1210 [](
const auto& tx) { return Workspace(tx); });
1211 std::map<const uint256, const MempoolAcceptResult> results;
1216 for (Workspace& ws : workspaces) {
1217 if (!PreChecks(
args, ws)) {
1228 m_viewmempool.PackageAddTransaction(ws.m_ptx);
1234 const auto m_total_vsize = std::accumulate(workspaces.cbegin(), workspaces.cend(), int64_t{0},
1235 [](int64_t
sum,
auto& ws) { return sum + ws.m_vsize; });
1236 const auto m_total_modified_fees = std::accumulate(workspaces.cbegin(), workspaces.cend(),
CAmount{0},
1237 [](
CAmount sum,
auto& ws) { return sum + ws.m_modified_fees; });
1238 const CFeeRate package_feerate(m_total_modified_fees, m_total_vsize);
1240 if (
args.m_package_feerates &&
1241 !
CheckFeeRate(m_total_vsize, m_total_modified_fees, placeholder_state)) {
1249 std::string err_string;
1250 if (txns.size() > 1 && !PackageMempoolChecks(txns, package_state)) {
1254 for (Workspace& ws : workspaces) {
1255 if (!PolicyScriptChecks(
args, ws)) {
1261 if (
args.m_test_accept) {
1264 results.emplace(ws.m_ptx->GetWitnessHash(),
1266 ws.m_vsize, ws.m_base_fees));
1272 if (!SubmitPackage(
args, workspaces, package_state, results)) {
1299 assert(package.size() > 1);
1302 const auto& child = package.back();
1303 std::unordered_set<uint256, SaltedTxidHasher> unconfirmed_parent_txids;
1304 std::transform(package.cbegin(), package.cend() - 1,
1305 std::inserter(unconfirmed_parent_txids, unconfirmed_parent_txids.end()),
1306 [](
const auto& tx) { return tx->GetHash(); });
1313 const CCoinsViewCache& coins_tip_cache = m_active_chainstate.CoinsTip();
1314 for (
const auto& input : child->vin) {
1316 args.m_coins_to_uncache.push_back(input.prevout);
1322 m_view.SetBackend(m_active_chainstate.CoinsTip());
1323 const auto package_or_confirmed = [
this, &unconfirmed_parent_txids](
const auto& input) {
1324 return unconfirmed_parent_txids.count(input.prevout.hash) > 0 || m_view.HaveCoin(input.prevout);
1326 if (!std::all_of(child->vin.cbegin(), child->vin.cend(), package_or_confirmed)) {
1332 m_view.SetBackend(m_dummy);
1335 std::map<const uint256, const MempoolAcceptResult> results;
1344 ATMPArgs single_args = ATMPArgs::SingleInPackageAccept(
args);
1345 bool quit_early{
false};
1346 std::vector<CTransactionRef> txns_new;
1347 for (
const auto& tx : package) {
1349 const auto& txid = tx->
GetHash();
1355 auto iter = m_pool.GetIter(txid);
1356 assert(iter != std::nullopt);
1366 auto iter = m_pool.GetIter(txid);
1367 assert(iter != std::nullopt);
1373 const auto single_res = AcceptSingleTransaction(tx, single_args);
1378 results.emplace(wtxid, single_res);
1392 txns_new.push_back(tx);
1398 if (quit_early || txns_new.empty()) {
1403 auto submission_result = AcceptMultipleTransactions(txns_new,
args);
1405 for (
const auto& [wtxid, mempoolaccept_res] : results) {
1406 submission_result.m_tx_results.emplace(wtxid, mempoolaccept_res);
1408 if (submission_result.m_state.IsValid())
assert(submission_result.m_package_feerate.has_value());
1409 return submission_result;
1415 int64_t accept_time,
bool bypass_limits,
bool test_accept)
1419 const CChainParams& chainparams{active_chainstate.m_params};
1420 assert(active_chainstate.GetMempool() !=
nullptr);
1421 CTxMemPool& pool{*active_chainstate.GetMempool()};
1423 std::vector<COutPoint> coins_to_uncache;
1424 auto args = MemPoolAccept::ATMPArgs::SingleAccept(chainparams, accept_time, bypass_limits, coins_to_uncache, test_accept);
1432 for (
const COutPoint& hashTx : coins_to_uncache)
1433 active_chainstate.CoinsTip().Uncache(hashTx);
1442 const Package& package,
bool test_accept)
1445 assert(!package.empty());
1446 assert(std::all_of(package.cbegin(), package.cend(), [](
const auto& tx){return tx != nullptr;}));
1448 std::vector<COutPoint> coins_to_uncache;
1453 auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(chainparams,
GetTime(), coins_to_uncache);
1454 return MemPoolAccept(pool, active_chainstate).AcceptMultipleTransactions(package,
args);
1456 auto args = MemPoolAccept::ATMPArgs::PackageChildWithParents(chainparams,
GetTime(), coins_to_uncache);
1457 return MemPoolAccept(pool, active_chainstate).AcceptPackage(package,
args);
1462 if (test_accept || result.m_state.IsInvalid()) {
1463 for (
const COutPoint& hashTx : coins_to_uncache) {
1482 nSubsidy >>= halvings;
1488 size_t cache_size_bytes,
1490 bool should_wipe) : m_dbview(
1491 gArgs.GetDataDirNet() / ldb_name, cache_size_bytes, in_memory, should_wipe),
1492 m_catcherview(&m_dbview) {}
1494 void CoinsViews::InitCache()
1497 m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview);
1504 std::optional<uint256> from_snapshot_blockhash)
1505 : m_mempool(mempool),
1506 m_blockman(blockman),
1507 m_params(chainman.GetParams()),
1508 m_chainman(chainman),
1509 m_from_snapshot_blockhash(from_snapshot_blockhash) {}
1512 size_t cache_size_bytes,
1522 leveldb_name, cache_size_bytes, in_memory, should_wipe);
1525 void CChainState::InitCoinsCache(
size_t cache_size_bytes)
1538 bool CChainState::IsInitialBlockDownload()
const
1555 LogPrintf(
"Leaving InitialBlockDownload (latching to false)\n");
1564 std::string strCmd =
gArgs.
GetArg(
"-alertnotify",
"");
1565 if (strCmd.empty())
return;
1570 std::string singleQuote(
"'");
1572 safeStatus = singleQuote+safeStatus+singleQuote;
1575 std::thread
t(runCommand, strCmd);
1586 if (IsInitialBlockDownload()) {
1591 LogPrintf(
"%s: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n", __func__);
1609 LogPrintf(
"%s: invalid block=%s height=%d log2_work=%f date=%s\n", __func__,
1614 LogPrintf(
"%s: current best=%s height=%d log2_work=%f date=%s\n", __func__,
1670 LogPrintf(
"Using %zu MiB out of %zu/2 requested for script execution cache, able to store %zu elements\n",
1671 (nElems*
sizeof(
uint256)) >>20, (nMaxCacheSize*2)>>20, nElems);
1696 std::vector<CScriptCheck>* pvChecks)
1701 pvChecks->reserve(tx.
vin.size());
1718 std::vector<CTxOut> spent_outputs;
1719 spent_outputs.reserve(tx.
vin.size());
1721 for (
const auto& txin : tx.
vin) {
1725 spent_outputs.emplace_back(coin.
out);
1727 txdata.
Init(tx, std::move(spent_outputs));
1731 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
1743 check.
swap(pvChecks->back());
1744 }
else if (!check()) {
1772 if (cacheFullScriptStore && !pvChecks) {
1784 return state.
Error(strMessage);
1798 if (view.
HaveCoin(out)) fClean =
false;
1800 if (undo.nHeight == 0) {
1806 undo.nHeight = alternate.
nHeight;
1817 view.
AddCoin(out, std::move(undo), !fClean);
1831 error(
"DisconnectBlock(): failure reading undo data");
1835 if (blockUndo.
vtxundo.size() + 1 != block.
vtx.size()) {
1836 error(
"DisconnectBlock(): block and undo data inconsistent");
1841 for (
int i = block.
vtx.size() - 1; i >= 0; i--) {
1848 for (
size_t o = 0; o < tx.
vout.size(); o++) {
1849 if (!tx.
vout[o].scriptPubKey.IsUnspendable()) {
1852 bool is_spent = view.
SpendCoin(out, &coin);
1863 error(
"DisconnectBlock(): transaction and undo data inconsistent");
1866 for (
unsigned int j = tx.
vin.size(); j > 0;) {
1921 static std::array<ThresholdConditionCache, VERSIONBITS_NUM_BITS> warningcache
GUARDED_BY(
cs_main);
2006 return AbortNode(state,
"Corrupt block found indicating potential hardware failure; shutting down");
2008 return error(
"%s: Consensus::CheckBlock: %s", __func__, state.
ToString());
2025 bool fScriptChecks =
true;
2034 if (it->second.GetAncestor(pindex->
nHeight) == pindex &&
2069 bool fEnforceBIP30 = !((pindex->
nHeight==91842 && pindex->
GetBlockHash() ==
uint256S(
"0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
2070 (pindex->
nHeight==91880 && pindex->
GetBlockHash() ==
uint256S(
"0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
2098 static constexpr
int BIP34_IMPLIES_BIP30_LIMIT = 1983702;
2135 if (fEnforceBIP30 || pindex->
nHeight >= BIP34_IMPLIES_BIP30_LIMIT) {
2136 for (
const auto& tx : block.
vtx) {
2137 for (
size_t o = 0; o < tx->
vout.size(); o++) {
2139 LogPrintf(
"ERROR: ConnectBlock(): tried to overwrite transaction\n");
2147 int nLockTimeFlags = 0;
2166 std::vector<PrecomputedTransactionData> txsdata(block.
vtx.size());
2168 std::vector<int> prevheights;
2171 int64_t nSigOpsCost = 0;
2172 blockundo.
vtxundo.reserve(block.
vtx.size() - 1);
2173 for (
unsigned int i = 0; i < block.
vtx.size(); i++)
2177 nInputs += tx.
vin.size();
2191 LogPrintf(
"ERROR: %s: accumulated fee in the block out of range.\n", __func__);
2198 prevheights.resize(tx.
vin.size());
2199 for (
size_t j = 0; j < tx.
vin.size(); j++) {
2203 if (!
SequenceLocks(tx, nLockTimeFlags, prevheights, *pindex)) {
2204 LogPrintf(
"ERROR: %s: contains a non-BIP68-final transaction\n", __func__);
2215 LogPrintf(
"ERROR: ConnectBlock(): too many sigops\n");
2221 std::vector<CScriptCheck> vChecks;
2222 bool fCacheResults = fJustCheck;
2228 return error(
"ConnectBlock(): CheckInputScripts on %s failed with %s",
2231 control.
Add(vChecks);
2244 if (block.
vtx[0]->GetValueOut() > blockReward) {
2245 LogPrintf(
"ERROR: ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)\n", block.
vtx[0]->GetValueOut(), blockReward);
2249 if (!control.
Wait()) {
2250 LogPrintf(
"ERROR: %s: CheckQueue failed\n", __func__);
2278 TRACE6(validation, block_connected,
2293 return this->GetCoinsCacheSizeState(
2299 size_t max_coins_cache_size_bytes,
2300 size_t max_mempool_size_bytes)
2305 int64_t nTotalSpace =
2306 max_coins_cache_size_bytes + std::max<int64_t>(int64_t(max_mempool_size_bytes) - nMempoolUsage, 0);
2309 static constexpr int64_t MAX_BLOCK_COINSDB_USAGE_BYTES = 10 * 1024 * 1024;
2310 int64_t large_threshold =
2311 std::max((9 * nTotalSpace) / 10, nTotalSpace - MAX_BLOCK_COINSDB_USAGE_BYTES);
2313 if (cacheSize > nTotalSpace) {
2314 LogPrintf(
"Cache size (%s) exceeds total space (%s)\n", cacheSize, nTotalSpace);
2316 }
else if (cacheSize > large_threshold) {
2325 int nManualPruneHeight)
2328 assert(this->CanFlushToDisk());
2329 static std::chrono::microseconds nLastWrite{0};
2330 static std::chrono::microseconds nLastFlush{0};
2331 std::set<int> setFilesToPrune;
2332 bool full_flush_completed =
false;
2339 bool fFlushForPrune =
false;
2340 bool fDoFullFlush =
false;
2348 std::optional<std::string> limiting_lock;
2350 for (
const auto& prune_lock :
m_blockman.m_prune_locks) {
2351 if (prune_lock.second.height_first == std::numeric_limits<int>::max())
continue;
2354 last_prune = std::max(1, std::min(last_prune, lock_height));
2355 if (last_prune == lock_height) {
2356 limiting_lock = prune_lock.first;
2360 if (limiting_lock) {
2361 LogPrint(
BCLog::PRUNE,
"%s limited pruning to height %d\n", limiting_lock.value(), last_prune);
2364 if (nManualPruneHeight > 0) {
2374 if (!setFilesToPrune.empty()) {
2375 fFlushForPrune =
true;
2377 m_blockman.m_block_tree_db->WriteFlag(
"prunedblockfiles",
true);
2382 const auto nNow = GetTime<std::chrono::microseconds>();
2384 if (nLastWrite.count() == 0) {
2387 if (nLastFlush.count() == 0) {
2399 fDoFullFlush = (mode ==
FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune;
2401 if (fDoFullFlush || fPeriodicWrite) {
2404 return AbortNode(state,
"Disk space is too low!",
_(
"Disk space is too low!"));
2418 return AbortNode(state,
"Failed to write to block index database");
2422 if (fFlushForPrune) {
2430 if (fDoFullFlush && !
CoinsTip().GetBestBlock().IsNull()) {
2440 return AbortNode(state,
"Disk space is too low!",
_(
"Disk space is too low!"));
2444 return AbortNode(state,
"Failed to write to coin database");
2446 full_flush_completed =
true;
2450 (uint64_t)coins_count,
2451 (uint64_t)coins_mem_usage,
2452 (
bool)fFlushForPrune);
2455 if (full_flush_completed) {
2459 }
catch (
const std::runtime_error& e) {
2460 return AbortNode(state, std::string(
"System error while flushing: ") + e.what());
2484 static bool fWarned =
false;
2503 const std::string& func_name,
2504 const std::string&
prefix,
2509 LogPrintf(
"%s%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)%s\n",
2511 tip->GetBlockHash().ToString(), tip->nHeight, tip->nVersion,
2512 log(tip->nChainWork.getdouble()) / log(2.0), (
unsigned long)tip->nChainTx,
2515 coins_tip.DynamicMemoryUsage() * (1.0 / (1 << 20)),
2516 coins_tip.GetCacheSize(),
2517 !warning_messages.empty() ?
strprintf(
" warning='%s'", warning_messages) :
"");
2520 void CChainState::UpdateTip(
const CBlockIndex* pindexNew)
2523 const auto& coins_tip = this->
CoinsTip();
2529 constexpr
int BACKGROUND_LOG_INTERVAL = 2000;
2530 if (pindexNew->
nHeight % BACKGROUND_LOG_INTERVAL == 0) {
2548 if (!this->IsInitialBlockDownload()) {
2584 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
2587 return error(
"DisconnectTip(): Failed to read block");
2594 if (DisconnectBlock(block, pindexDelete, view) !=
DISCONNECT_OK)
2596 bool flushed = view.
Flush();
2603 const int max_height_first{pindexDelete->
nHeight - 1};
2604 for (
auto& prune_lock :
m_blockman.m_prune_locks) {
2605 if (prune_lock.second.height_first <= max_height_first)
continue;
2607 prune_lock.second.height_first = max_height_first;
2608 LogPrint(
BCLog::PRUNE,
"%s prune lock moved back to %d\n", prune_lock.first, max_height_first);
2619 for (
auto it = block.
vtx.rbegin(); it != block.
vtx.rend(); ++it) {
2632 UpdateTip(pindexDelete->
pprev);
2699 std::shared_ptr<const CBlock> pthisBlock;
2701 std::shared_ptr<CBlock> pblockNew = std::make_shared<CBlock>();
2703 return AbortNode(state,
"Failed to read block");
2705 pthisBlock = pblockNew;
2708 pthisBlock = pblock;
2710 const CBlock& blockConnecting = *pthisBlock;
2717 bool rv =
ConnectBlock(blockConnecting, state, pindexNew, view);
2727 bool flushed = view.
Flush();
2745 UpdateTip(pindexNew);
2776 bool fInvalidAncestor =
false;
2786 if (fFailedChain || fMissingData) {
2793 while (pindexTest != pindexFailed) {
2796 }
else if (fMissingData) {
2801 std::make_pair(pindexFailed->
pprev, pindexFailed));
2804 pindexFailed = pindexFailed->
pprev;
2807 fInvalidAncestor =
true;
2810 pindexTest = pindexTest->
pprev;
2812 if (!fInvalidAncestor)
2844 bool fBlocksDisconnected =
false;
2855 AbortNode(state,
"Failed to disconnect block; see debug.log for details");
2858 fBlocksDisconnected =
true;
2862 std::vector<CBlockIndex*> vpindexToConnect;
2863 bool fContinue =
true;
2868 int nTargetHeight = std::min(
nHeight + 32, pindexMostWork->
nHeight);
2869 vpindexToConnect.clear();
2870 vpindexToConnect.reserve(nTargetHeight -
nHeight);
2873 vpindexToConnect.push_back(pindexIter);
2874 pindexIter = pindexIter->
pprev;
2880 if (!
ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool)) {
2887 fInvalidFound =
true;
2908 if (fBlocksDisconnected) {
2928 bool fNotify =
false;
2929 bool fInitialBlockDownload =
false;
2934 pindexHeader = chainstate.m_chainman.m_best_header;
2936 if (pindexHeader != pindexHeaderOld) {
2938 fInitialBlockDownload = chainstate.IsInitialBlockDownload();
2939 pindexHeaderOld = pindexHeader;
2957 bool CChainState::ActivateBestChain(
BlockValidationState& state, std::shared_ptr<const CBlock> pblock)
2990 bool blocks_connected =
false;
2996 if (pindexMostWork ==
nullptr) {
3001 if (pindexMostWork ==
nullptr || pindexMostWork ==
m_chain.
Tip()) {
3005 bool fInvalidFound =
false;
3006 std::shared_ptr<const CBlock> nullBlockPtr;
3007 if (!
ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->
GetBlockHash() ? pblock : nullBlockPtr, fInvalidFound, connectTrace)) {
3011 blocks_connected =
true;
3013 if (fInvalidFound) {
3015 pindexMostWork =
nullptr;
3020 assert(trace.pblock && trace.pindex);
3024 if (!blocks_connected)
return true;
3027 bool fInitialDownload = IsInitialBlockDownload();
3031 if (pindexFork != pindexNewTip) {
3048 }
while (pindexNewTip != pindexMostWork);
3087 return ActivateBestChain(state, std::shared_ptr<const CBlock>());
3097 if (pindex->
nHeight == 0)
return false;
3100 bool pindex_was_in_chain =
false;
3101 int disconnected = 0;
3115 std::multimap<const arith_uint256, CBlockIndex *> candidate_blocks_by_work;
3119 for (
auto& entry :
m_blockman.m_block_index) {
3130 candidate_blocks_by_work.insert(std::make_pair(candidate->
nChainWork, candidate));
3147 pindex_was_in_chain =
true;
3160 if (!
ret)
return false;
3180 auto candidate_it = candidate_blocks_by_work.lower_bound(invalid_walk_tip->
pprev->
nChainWork);
3181 while (candidate_it != candidate_blocks_by_work.end()) {
3184 candidate_it = candidate_blocks_by_work.erase(candidate_it);
3192 to_mark_failed = invalid_walk_tip;
3217 for (
auto& [
_, block_index] :
m_blockman.m_block_index) {
3227 if (pindex_was_in_chain) {
3239 for (
auto& [
_, block_index] :
m_blockman.m_block_index) {
3240 if (!block_index.IsValid() && block_index.GetAncestor(
nHeight) == pindex) {
3246 if (&block_index ==
m_chainman.m_best_invalid) {
3255 while (pindex !=
nullptr) {
3261 pindex = pindex->
pprev;
3269 pindexNew->
nTx = block.
vtx.size();
3271 pindexNew->nFile = pos.
nFile;
3272 pindexNew->nDataPos = pos.
nPos;
3273 pindexNew->nUndoPos = 0;
3283 std::deque<CBlockIndex*> queue;
3284 queue.push_back(pindexNew);
3287 while (!queue.empty()) {
3295 std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range =
m_blockman.
m_blocks_unlinked.equal_range(pindex);
3296 while (range.first != range.second) {
3297 std::multimap<CBlockIndex*, CBlockIndex*>::iterator it = range.first;
3298 queue.push_back(it->second);
3337 if (fCheckMerkleRoot) {
3361 if (block.
vtx.empty() || !block.
vtx[0]->IsCoinBase())
3363 for (
unsigned int i = 1; i < block.
vtx.size(); i++)
3364 if (block.
vtx[i]->IsCoinBase())
3369 for (
const auto& tx : block.
vtx) {
3379 unsigned int nSigOps = 0;
3380 for (
const auto& tx : block.
vtx)
3387 if (fCheckPOW && fCheckMerkleRoot)
3393 void ChainstateManager::UpdateUncommittedBlockStructures(
CBlock& block,
const CBlockIndex* pindexPrev)
const
3396 static const std::vector<unsigned char>
nonce(32, 0x00);
3399 tx.
vin[0].scriptWitness.stack.resize(1);
3400 tx.
vin[0].scriptWitness.stack[0] =
nonce;
3407 std::vector<unsigned char> commitment;
3409 std::vector<unsigned char>
ret(32, 0x00);
3425 tx.
vout.push_back(out);
3428 UpdateUncommittedBlockStructures(block, pindexPrev);
3444 assert(pindexPrev !=
nullptr);
3457 const CBlockIndex* pcheckpoint = blockman.GetLastCheckpoint(chainman.GetParams().Checkpoints());
3458 if (pcheckpoint && nHeight < pcheckpoint->
nHeight) {
3459 LogPrintf(
"ERROR: %s: forked chain older than last checkpoint (height %d)\n", __func__,
nHeight);
3491 const int nHeight = pindexPrev ==
nullptr ? 0 : pindexPrev->
nHeight + 1;
3494 int nLockTimeFlags = 0;
3496 assert(pindexPrev !=
nullptr);
3505 for (
const auto& tx : block.
vtx) {
3515 if (block.
vtx[0]->vin[0].scriptSig.size() <
expect.size() ||
3516 !std::equal(
expect.begin(),
expect.end(), block.
vtx[0]->vin[0].scriptSig.begin())) {
3529 bool fHaveWitness =
false;
3533 bool malleated =
false;
3538 if (block.
vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.
vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
3542 if (memcmp(hashWitness.
begin(), &block.
vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
3545 fHaveWitness =
true;
3550 if (!fHaveWitness) {
3551 for (
const auto& tx : block.
vtx) {
3576 BlockMap::iterator miSelf{
m_blockman.m_block_index.find(hash)};
3578 if (miSelf !=
m_blockman.m_block_index.end()) {
3602 pindexPrev = &((*mi).second);
3637 if (pindexPrev->
GetAncestor(failedit->nHeight) == failedit) {
3640 while (invalid_walk != failedit) {
3643 invalid_walk = invalid_walk->
pprev;
3682 const double progress{100.0 * last_accepted.nHeight / (last_accepted.nHeight + blocks_left)};
3683 LogPrintf(
"Synchronizing blockheaders, height: %d (~%.2f%%)\n", last_accepted.nHeight, progress);
3692 const CBlock& block = *pblock;
3694 if (fNewBlock) *fNewBlock =
false;
3698 CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
3703 if (!accepted_header)
3726 if (fAlreadyHave)
return true;
3728 if (pindex->
nTx != 0)
return true;
3729 if (!fHasMoreOrSameWork)
return true;
3730 if (fTooFarAhead)
return true;
3754 if (fNewBlock) *fNewBlock =
true;
3757 if (blockPos.IsNull()) {
3758 state.
Error(
strprintf(
"%s: Failed to find position to write new block to disk", __func__));
3762 }
catch (
const std::runtime_error& e) {
3763 return AbortNode(state, std::string(
"System error: ") + e.what());
3779 if (new_block) *new_block =
false;
3798 return error(
"%s: AcceptBlock FAILED (%s)", __func__, state.
ToString());
3806 return error(
"%s: ActivateBestChain failed (%s)", __func__, state.
ToString());
3831 const std::function<int64_t()>& adjusted_time_callback,
3833 bool fCheckMerkleRoot)
3840 indexDummy.
pprev = pindexPrev;
3846 return error(
"%s: Consensus::ContextualCheckBlockHeader: %s", __func__, state.
ToString());
3848 return error(
"%s: Consensus::CheckBlock: %s", __func__, state.
ToString());
3850 return error(
"%s: Consensus::ContextualCheckBlock: %s", __func__, state.
ToString());
3851 if (!chainstate.
ConnectBlock(block, state, &indexDummy, viewNew,
true)) {
3898 LogPrintf(
"Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n",
3908 uiInterface.ShowProgress(
_(
"Verifying blocks…").translated, 0,
false);
3920 int nCheckLevel,
int nCheckDepth)
3929 if (nCheckDepth <= 0 || nCheckDepth > chainstate.
m_chain.
Height()) {
3932 nCheckLevel = std::max(0, std::min(4, nCheckLevel));
3933 LogPrintf(
"Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
3937 int nGoodTransactions = 0;
3945 const int percentageDone = std::max(1, std::min(99, (
int)(((
double)(chainstate.
m_chain.
Height() - pindex->
nHeight)) / (
double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
3946 if (reportDone < percentageDone / 10) {
3949 reportDone = percentageDone / 10;
3951 uiInterface.ShowProgress(
_(
"Verifying blocks…").translated, percentageDone,
false);
3958 LogPrintf(
"VerifyDB(): block verification stopping at height %d (pruning, no data)\n", pindex->
nHeight);
3967 if (nCheckLevel >= 1 && !
CheckBlock(block, state, consensus_params)) {
3968 return error(
"%s: *** found bad block at %d, hash=%s (%s)\n", __func__,
3972 if (nCheckLevel >= 2 && pindex) {
3990 nGoodTransactions = 0;
3991 pindexFailure = pindex;
3993 nGoodTransactions += block.
vtx.size();
3998 if (pindexFailure) {
3999 return error(
"VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainstate.
m_chain.
Height() - pindexFailure->
nHeight + 1, nGoodTransactions);
4006 if (nCheckLevel >= 4) {
4008 const int percentageDone = std::max(1, std::min(99, 100 - (
int)(((
double)(chainstate.
m_chain.
Height() - pindex->
nHeight)) / (
double)nCheckDepth * 50)));
4009 if (reportDone < percentageDone / 10) {
4012 reportDone = percentageDone / 10;
4014 uiInterface.ShowProgress(
_(
"Verifying blocks…").translated, percentageDone,
false);
4019 if (!chainstate.
ConnectBlock(block, state, pindex, coins)) {
4027 LogPrintf(
"No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions);
4043 if (!tx->IsCoinBase()) {
4044 for (
const CTxIn &txin : tx->vin) {
4062 if (hashHeads.empty())
return true;
4063 if (hashHeads.size() != 2)
return error(
"ReplayBlocks(): unknown inconsistent state");
4065 uiInterface.ShowProgress(
_(
"Replaying blocks…").translated, 0,
false);
4072 if (
m_blockman.m_block_index.count(hashHeads[0]) == 0) {
4073 return error(
"ReplayBlocks(): reorganization to unknown block requested");
4075 pindexNew = &(
m_blockman.m_block_index[hashHeads[0]]);
4077 if (!hashHeads[1].IsNull()) {
4078 if (
m_blockman.m_block_index.count(hashHeads[1]) == 0) {
4079 return error(
"ReplayBlocks(): reorganization from unknown block requested");
4081 pindexOld = &(
m_blockman.m_block_index[hashHeads[1]]);
4083 assert(pindexFork !=
nullptr);
4087 while (pindexOld != pindexFork) {
4103 pindexOld = pindexOld->
pprev;
4107 int nForkHeight = pindexFork ? pindexFork->
nHeight : 0;
4112 uiInterface.ShowProgress(
_(
"Replaying blocks…").translated, (
int) ((
nHeight - nForkHeight) * 100.0 / (pindexNew->
nHeight - nForkHeight)) ,
false);
4134 block = block->pprev;
4140 void CChainState::UnloadBlockIndex()
4143 nBlockSequenceId = 1;
4154 if (!
ret)
return false;
4156 std::vector<CBlockIndex*> vSortedByHeight{
m_blockman.GetAllBlockIndices()};
4157 std::sort(vSortedByHeight.begin(), vSortedByHeight.end(),
4161 int first_assumed_valid_height = std::numeric_limits<int>::max();
4163 for (
const CBlockIndex* block : vSortedByHeight) {
4164 if (block->IsAssumedValid()) {
4165 auto chainstates =
GetAll();
4171 auto any_chain = [&](
auto fnc) {
return std::any_of(chainstates.cbegin(), chainstates.cend(), fnc); };
4175 first_assumed_valid_height = block->nHeight;
4211 pindex->
nHeight < first_assumed_valid_height) {
4217 m_best_invalid = pindex;
4223 needs_init =
m_blockman.m_block_index.empty();
4233 LogPrintf(
"Initializing databases...\n");
4252 if (blockPos.IsNull()) {
4253 return error(
"%s: writing genesis block to disk failed", __func__);
4257 }
catch (
const std::runtime_error& e) {
4258 return error(
"%s: failed to write genesis block: %s", __func__, e.what());
4264 void CChainState::LoadExternalBlockFile(FILE* fileIn,
FlatFilePos* dbp)
4268 static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
4275 uint64_t nRewind = blkdat.GetPos();
4276 while (!blkdat.eof()) {
4279 blkdat.SetPos(nRewind);
4282 unsigned int nSize = 0;
4287 nRewind = blkdat.GetPos() + 1;
4296 }
catch (
const std::exception&) {
4302 uint64_t nBlockPos = blkdat.GetPos();
4304 dbp->
nPos = nBlockPos;
4305 blkdat.SetLimit(nBlockPos + nSize);
4306 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4309 nRewind = blkdat.GetPos();
4311 uint256 hash = block.GetHash();
4317 block.hashPrevBlock.ToString());
4319 mapBlocksUnknownParent.insert(std::make_pair(block.hashPrevBlock, *dbp));
4327 if (
AcceptBlock(pblock, state,
nullptr,
true, dbp,
nullptr)) {
4341 if (!ActivateBestChain(state,
nullptr)) {
4349 std::deque<uint256> queue;
4350 queue.push_back(hash);
4351 while (!queue.empty()) {
4354 std::pair<std::multimap<uint256, FlatFilePos>::iterator, std::multimap<uint256, FlatFilePos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
4355 while (range.first != range.second) {
4356 std::multimap<uint256, FlatFilePos>::iterator it = range.first;
4357 std::shared_ptr<CBlock> pblockrecursive = std::make_shared<CBlock>();
4359 LogPrint(
BCLog::REINDEX,
"%s: Processing out of order child %s of %s\n", __func__, pblockrecursive->GetHash().ToString(),
4363 if (
AcceptBlock(pblockrecursive, dummy,
nullptr,
true, &it->second,
nullptr)) {
4365 queue.push_back(pblockrecursive->GetHash());
4369 mapBlocksUnknownParent.erase(it);
4373 }
catch (
const std::exception& e) {
4374 LogPrintf(
"%s: Deserialize or I/O error - %s\n", __func__, e.what());
4377 }
catch (
const std::runtime_error& e) {
4378 AbortNode(std::string(
"System error: ") + e.what());
4400 std::multimap<CBlockIndex*,CBlockIndex*> forward;
4401 for (
auto& [
_, block_index] :
m_blockman.m_block_index) {
4402 forward.emplace(block_index.pprev, &block_index);
4407 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeGenesis = forward.equal_range(
nullptr);
4409 rangeGenesis.first++;
4410 assert(rangeGenesis.first == rangeGenesis.second);
4421 CBlockIndex* pindexFirstNotTransactionsValid =
nullptr;
4423 CBlockIndex* pindexFirstNotScriptsValid =
nullptr;
4424 while (pindex !=
nullptr) {
4426 if (pindexFirstInvalid ==
nullptr && pindex->nStatus &
BLOCK_FAILED_VALID) pindexFirstInvalid = pindex;
4430 pindexFirstMissing = pindex;
4432 if (pindexFirstNeverProcessed ==
nullptr && pindex->
nTx == 0) pindexFirstNeverProcessed = pindex;
4439 if (pindexFirstNotTransactionsValid ==
nullptr &&
4441 pindexFirstNotTransactionsValid = pindex;
4444 if (pindexFirstNotChainValid ==
nullptr &&
4446 pindexFirstNotChainValid = pindex;
4449 if (pindexFirstNotScriptsValid ==
nullptr &&
4451 pindexFirstNotScriptsValid = pindex;
4456 if (pindex->
pprev ==
nullptr) {
4469 assert(pindexFirstMissing == pindexFirstNeverProcessed);
4491 assert(pindexFirstNotTreeValid ==
nullptr);
4495 if (pindexFirstInvalid ==
nullptr) {
4500 if (pindexFirstInvalid ==
nullptr) {
4511 if (is_active && (pindexFirstMissing ==
nullptr || pindex ==
m_chain.
Tip())) {
4522 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeUnlinked =
m_blockman.
m_blocks_unlinked.equal_range(pindex->
pprev);
4523 bool foundInUnlinked =
false;
4524 while (rangeUnlinked.first != rangeUnlinked.second) {
4525 assert(rangeUnlinked.first->first == pindex->
pprev);
4526 if (rangeUnlinked.first->second == pindex) {
4527 foundInUnlinked =
true;
4530 rangeUnlinked.first++;
4532 if (pindex->
pprev && (pindex->nStatus &
BLOCK_HAVE_DATA) && pindexFirstNeverProcessed !=
nullptr && pindexFirstInvalid ==
nullptr) {
4537 if (pindexFirstMissing ==
nullptr)
assert(!foundInUnlinked);
4538 if (pindex->
pprev && (pindex->nStatus &
BLOCK_HAVE_DATA) && pindexFirstNeverProcessed ==
nullptr && pindexFirstMissing !=
nullptr) {
4550 if (pindexFirstInvalid ==
nullptr) {
4559 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> range = forward.equal_range(pindex);
4560 if (range.first != range.second) {
4562 pindex = range.first->second;
4571 if (pindex == pindexFirstInvalid) pindexFirstInvalid =
nullptr;
4572 if (pindex == pindexFirstMissing) pindexFirstMissing =
nullptr;
4573 if (pindex == pindexFirstNeverProcessed) pindexFirstNeverProcessed =
nullptr;
4574 if (pindex == pindexFirstNotTreeValid) pindexFirstNotTreeValid =
nullptr;
4575 if (pindex == pindexFirstNotTransactionsValid) pindexFirstNotTransactionsValid =
nullptr;
4576 if (pindex == pindexFirstNotChainValid) pindexFirstNotChainValid =
nullptr;
4577 if (pindex == pindexFirstNotScriptsValid) pindexFirstNotScriptsValid =
nullptr;
4581 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangePar = forward.equal_range(pindexPar);
4582 while (rangePar.first->second != pindex) {
4583 assert(rangePar.first != rangePar.second);
4588 if (rangePar.first != rangePar.second) {
4590 pindex = rangePar.first->second;
4602 assert(nNodes == forward.size());
4609 return strprintf(
"Chainstate [%s] @ height %d (%s)",
4614 bool CChainState::ResizeCoinsCaches(
size_t coinstip_size,
size_t coinsdb_size)
4627 LogPrintf(
"[%s] resized coinsdb cache to %.1f MiB\n",
4628 this->
ToString(), coinsdb_size * (1.0 / 1024 / 1024));
4629 LogPrintf(
"[%s] resized coinstip cache to %.1f MiB\n",
4630 this->
ToString(), coinstip_size * (1.0 / 1024 / 1024));
4635 if (coinstip_size > old_coinstip_size) {
4654 LogPrintf(
"Failed to open mempool file from disk. Continuing anyway.\n");
4659 int64_t expired = 0;
4661 int64_t already_there = 0;
4662 int64_t unbroadcast = 0;
4682 CAmount amountdelta = nFeeDelta;
4686 if (nTime > nNow - nExpiryTimeout) {
4688 const auto& accepted =
AcceptToMemoryPool(active_chainstate, tx, nTime,
false,
false);
4708 std::map<uint256, CAmount> mapDeltas;
4711 for (
const auto& i : mapDeltas) {
4715 std::set<uint256> unbroadcast_txids;
4716 file >> unbroadcast_txids;
4717 unbroadcast = unbroadcast_txids.size();
4718 for (
const auto& txid : unbroadcast_txids) {
4723 }
catch (
const std::exception& e) {
4724 LogPrintf(
"Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
4728 LogPrintf(
"Imported mempool transactions from disk: %i succeeded, %i failed, %i expired, %i already there, %i waiting for initial broadcast\n",
count, failed, expired, already_there, unbroadcast);
4736 std::map<uint256, CAmount> mapDeltas;
4737 std::vector<TxMempoolInfo> vinfo;
4738 std::set<uint256> unbroadcast_txids;
4740 static Mutex dump_mutex;
4745 for (
const auto &i : pool.mapDeltas) {
4746 mapDeltas[i.first] = i.second;
4755 FILE* filestr{mockable_fopen_function(
gArgs.
GetDataDirNet() /
"mempool.dat.new",
"wb")};
4765 file << (uint64_t)vinfo.size();
4766 for (
const auto& i : vinfo) {
4769 file << int64_t{i.nFeeDelta};
4770 mapDeltas.erase(i.tx->GetHash());
4775 LogPrintf(
"Writing %d unbroadcast transactions to disk.\n", unbroadcast_txids.size());
4776 file << unbroadcast_txids;
4779 throw std::runtime_error(
"FileCommit failed");
4782 throw std::runtime_error(
"Rename failed");
4785 LogPrintf(
"Dumped mempool: %gs to copy, %gs to dump\n", (mid-start)*
MICRO, (last-mid)*
MICRO);
4786 }
catch (
const std::exception& e) {
4787 LogPrintf(
"Failed to dump mempool: %s. Continuing anyway.\n", e.what());
4796 if (pindex ==
nullptr)
4799 int64_t nNow = time(
nullptr);
4809 return std::min<double>(pindex->
nChainTx / fTxTotal, 1.0);
4815 if (m_active_chainstate && m_active_chainstate->m_from_snapshot_blockhash) {
4817 return m_active_chainstate->m_from_snapshot_blockhash;
4819 return std::nullopt;
4825 std::vector<CChainState*> out;
4828 out.push_back(m_ibd_chainstate.get());
4831 if (m_snapshot_chainstate) {
4832 out.push_back(m_snapshot_chainstate.get());
4838 CChainState& ChainstateManager::InitializeChainstate(
4839 CTxMemPool* mempool,
const std::optional<uint256>& snapshot_blockhash)
4842 bool is_snapshot = snapshot_blockhash.has_value();
4843 std::unique_ptr<CChainState>& to_modify =
4844 is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate;
4847 throw std::logic_error(
"should not be overwriting a chainstate");
4852 if (is_snapshot || (!is_snapshot && !m_active_chainstate)) {
4853 LogPrintf(
"Switching active chainstate to %s\n", to_modify->ToString());
4854 m_active_chainstate = to_modify.get();
4856 throw std::logic_error(
"unexpected chainstate activation");
4866 const auto assumeutxo_found = valid_assumeutxos_map.find(height);
4868 if (assumeutxo_found != valid_assumeutxos_map.end()) {
4869 return &assumeutxo_found->second;
4882 LogPrintf(
"[snapshot] can't activate a snapshot-based chainstate more than once\n");
4886 int64_t current_coinsdb_cache_size{0};
4887 int64_t current_coinstip_cache_size{0};
4895 static constexpr
double IBD_CACHE_PERC = 0.01;
4896 static constexpr
double SNAPSHOT_CACHE_PERC = 0.99;
4914 static_cast<size_t>(current_coinstip_cache_size * IBD_CACHE_PERC),
4915 static_cast<size_t>(current_coinsdb_cache_size * IBD_CACHE_PERC));
4919 return std::make_unique<CChainState>(
4920 nullptr,
m_blockman, *
this, base_blockhash));
4924 snapshot_chainstate->InitCoinsDB(
4925 static_cast<size_t>(current_coinsdb_cache_size * SNAPSHOT_CACHE_PERC),
4926 in_memory,
false,
"chainstate");
4927 snapshot_chainstate->InitCoinsCache(
4928 static_cast<size_t>(current_coinstip_cache_size * SNAPSHOT_CACHE_PERC));
4932 *snapshot_chainstate, coins_file, metadata);
4941 assert(!m_snapshot_chainstate);
4942 m_snapshot_chainstate.swap(snapshot_chainstate);
4943 const bool chaintip_loaded = m_snapshot_chainstate->LoadChainTip();
4946 m_active_chainstate = m_snapshot_chainstate.get();
4948 LogPrintf(
"[snapshot] successfully activated snapshot %s\n", base_blockhash.
ToString());
4950 m_snapshot_chainstate->CoinsTip().DynamicMemoryUsage() / (1000 * 1000));
4952 this->MaybeRebalanceCaches();
4961 snapshot_loaded ?
"saving snapshot chainstate" :
"flushing coins cache",
4965 coins_cache.
Flush();
4981 if (!snapshot_start_block) {
4984 LogPrintf(
"[snapshot] Did not find snapshot start blockheader %s\n",
4989 int base_height = snapshot_start_block->
nHeight;
4992 if (!maybe_au_data) {
4993 LogPrintf(
"[snapshot] assumeutxo height in snapshot metadata not recognized "
4994 "(%d) - refusing to load snapshot\n", base_height);
5005 LogPrintf(
"[snapshot] loading coins from snapshot %s\n", base_blockhash.
ToString());
5006 int64_t coins_processed{0};
5008 while (coins_left > 0) {
5010 coins_file >> outpoint;
5012 }
catch (
const std::ios_base::failure&) {
5013 LogPrintf(
"[snapshot] bad snapshot format or truncated snapshot after deserializing %d coins\n",
5014 coins_count - coins_left);
5017 if (coin.
nHeight > base_height ||
5018 outpoint.
n >= std::numeric_limits<decltype(outpoint.
n)>::max()
5020 LogPrintf(
"[snapshot] bad snapshot data after deserializing %d coins\n",
5021 coins_count - coins_left);
5030 if (coins_processed % 1000000 == 0) {
5031 LogPrintf(
"[snapshot] %d coins loaded (%.2f%%, %.2f MB)\n",
5033 static_cast<float>(coins_processed) * 100 /
static_cast<float>(coins_count),
5041 if (coins_processed % 120000 == 0) {
5047 return snapshot_chainstate.GetCoinsCacheSizeState());