63 #include <boost/algorithm/string/replace.hpp>
84 #define MICRO 0.000001
102 "level 0 reads the blocks from disk",
103 "level 1 verifies block validity",
104 "level 2 verifies undo data",
105 "level 3 checks disconnection of tip blocks",
106 "level 4 tries to reconnect the blocks",
107 "each level includes the checks of the previous levels",
121 if (pa < pb)
return false;
122 if (pa > pb)
return true;
162 CBlockIndex* pindex{m_blockman.LookupBlockIndex(hash)};
164 if (m_chain.Contains(pindex)) {
167 if (pindex->GetAncestor(m_chain.Height()) == m_chain.Tip()) {
168 return m_chain.Tip();
172 return m_chain.Genesis();
178 std::vector<CScriptCheck>* pvChecks =
nullptr)
200 const int nBlockHeight = active_chain_tip->nHeight + 1;
208 ? active_chain_tip->GetMedianTimePast()
211 return IsFinalTx(tx, nBlockHeight, nBlockTime);
219 bool useExistingLockPoints)
233 std::pair<int, int64_t> lockPair;
234 if (useExistingLockPoints) {
237 lockPair.second =
lp->
time;
240 std::vector<int> prevheights;
241 prevheights.resize(tx.
vin.size());
242 for (
size_t txinIndex = 0; txinIndex < tx.
vin.size(); txinIndex++) {
243 const CTxIn& txin = tx.
vin[txinIndex];
246 return error(
"%s: Missing input", __func__);
250 prevheights[txinIndex] = tip->
nHeight + 1;
252 prevheights[txinIndex] = coin.
nHeight;
258 lp->
time = lockPair.second;
272 int maxInputHeight = 0;
273 for (
const int height : prevheights) {
275 if (height != tip->
nHeight+1) {
276 maxInputHeight = std::max(maxInputHeight, height);
293 int expired = pool.Expire(GetTime<std::chrono::seconds>() - age);
298 std::vector<COutPoint> vNoSpendsRemaining;
299 pool.TrimToSize(limit, &vNoSpendsRemaining);
300 for (
const COutPoint& removed : vNoSpendsRemaining)
301 coins_cache.Uncache(removed);
307 if (active_chainstate.IsInitialBlockDownload())
320 if (!m_mempool)
return;
324 std::vector<uint256> vHashUpdate;
334 if (!fAddToMempool || (*it)->IsCoinBase() ||
336 true,
false).m_result_type !=
341 }
else if (m_mempool->exists(
GenTxid::Txid((*it)->GetHash()))) {
342 vHashUpdate.push_back((*it)->GetHash());
354 m_mempool->UpdateTransactionsFromBlock(vHashUpdate, ancestor_size_limit, ancestor_count_limit);
379 }
else if (!validLP) {
386 if (it->GetSpendsCoinbase()) {
388 auto it2 = m_mempool->mapTx.find(txin.
prevout.
hash);
389 if (it2 != m_mempool->mapTx.end())
391 const Coin& coin{CoinsTip().AccessCoin(txin.
prevout)};
393 const auto mempool_spend_height{m_chain.Tip()->nHeight + 1};
394 if (coin.IsCoinBase() && mempool_spend_height - coin.nHeight <
COINBASE_MATURITY) {
404 m_mempool->removeForReorg(m_chain, filter_final_and_mature);
410 std::chrono::hours{gArgs.GetIntArg(
"-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
433 if (coin.
IsSpent())
return false;
445 const Coin& coinFromUTXOSet = coins_tip.AccessCoin(txin.
prevout);
460 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),
471 const int64_t m_accept_time;
472 const bool m_bypass_limits;
480 std::vector<COutPoint>& m_coins_to_uncache;
481 const bool m_test_accept;
485 const bool m_allow_bip125_replacement;
490 const bool m_package_submission;
493 static ATMPArgs SingleAccept(
const CChainParams& chainparams, int64_t accept_time,
494 bool bypass_limits, std::vector<COutPoint>& coins_to_uncache,
496 return ATMPArgs{ chainparams,
507 static ATMPArgs PackageTestAccept(
const CChainParams& chainparams, int64_t accept_time,
508 std::vector<COutPoint>& coins_to_uncache) {
509 return ATMPArgs{ chainparams,
520 static ATMPArgs PackageChildWithParents(
const CChainParams& chainparams, int64_t accept_time,
521 std::vector<COutPoint>& coins_to_uncache) {
522 return ATMPArgs{ chainparams,
556 explicit Workspace(
const CTransactionRef& ptx) : m_ptx(ptx), m_hash(ptx->GetHash()) {}
558 std::set<uint256> m_conflicts;
568 std::unique_ptr<CTxMemPoolEntry> m_entry;
572 std::list<CTransactionRef> m_replaced_transactions;
584 size_t m_conflicting_size{0};
606 bool PackageMempoolChecks(
const std::vector<CTransactionRef>& txns,
629 std::map<const uint256, const MempoolAcceptResult>& results)
638 if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) {
657 const size_t m_limit_ancestors;
658 const size_t m_limit_ancestor_size;
661 size_t m_limit_descendants;
662 size_t m_limit_descendant_size;
668 bool MemPoolAccept::PreChecks(ATMPArgs&
args, Workspace& ws)
674 const uint256& hash = ws.m_hash;
677 const int64_t nAcceptTime =
args.m_accept_time;
678 const bool bypass_limits =
args.m_bypass_limits;
679 std::vector<COutPoint>& coins_to_uncache =
args.m_coins_to_uncache;
683 std::unique_ptr<CTxMemPoolEntry>& entry = ws.m_entry;
724 if (ptxConflicting) {
725 if (!
args.m_allow_bip125_replacement) {
729 if (!ws.m_conflicts.count(ptxConflicting->
GetHash()))
742 ws.m_conflicts.insert(ptxConflicting->
GetHash());
748 m_view.SetBackend(m_viewmempool);
754 coins_to_uncache.push_back(txin.
prevout);
760 if (!m_view.HaveCoin(txin.
prevout)) {
762 for (
size_t out = 0; out < tx.
vout.size(); out++) {
775 m_view.GetBestBlock();
780 m_view.SetBackend(m_dummy);
782 assert(m_active_chainstate.m_blockman.LookupBlockIndex(m_view.GetBestBlock()) == m_active_chainstate.m_chain.Tip());
809 ws.m_modified_fees = ws.m_base_fees;
810 m_pool.ApplyDelta(hash, ws.m_modified_fees);
814 bool fSpendsCoinbase =
false;
816 const Coin &coin = m_view.AccessCoin(txin.
prevout);
818 fSpendsCoinbase =
true;
823 entry.reset(
new CTxMemPoolEntry(ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(),
824 fSpendsCoinbase, nSigOpsCost,
lp));
825 ws.m_vsize = entry->GetTxSize();
833 if (!bypass_limits && !
CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state))
return false;
835 ws.m_iters_conflicting = m_pool.GetIterSet(ws.m_conflicts);
837 if (ws.m_conflicts.size() == 1) {
865 assert(ws.m_iters_conflicting.size() == 1);
868 m_limit_descendants += 1;
869 m_limit_descendant_size += conflict->GetSizeWithDescendants();
872 std::string errString;
873 if (!m_pool.CalculateMemPoolAncestors(*entry, ws.m_ancestors, m_limit_ancestors, m_limit_ancestor_size, m_limit_descendants, m_limit_descendant_size, errString)) {
874 ws.m_ancestors.clear();
876 std::string dummy_err_string;
889 !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)) {
904 m_rbf = !ws.m_conflicts.empty();
908 bool MemPoolAccept::ReplacementChecks(Workspace& ws)
914 const uint256& hash = ws.m_hash;
917 CFeeRate newFeeRate(ws.m_modified_fees, ws.m_vsize);
929 if (
const auto err_string{
GetEntriesForConflicts(tx, m_pool, ws.m_iters_conflicting, ws.m_all_conflicting)}) {
931 "too many potential replacements", *err_string);
936 "replacement-adds-unconfirmed", *err_string);
941 ws.m_conflicting_fees += it->GetModifiedFee();
942 ws.m_conflicting_size += it->GetTxSize();
944 if (
const auto err_string{
PaysForRBF(ws.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
951 bool MemPoolAccept::PackageMempoolChecks(
const std::vector<CTransactionRef>& txns,
958 assert(std::all_of(txns.cbegin(), txns.cend(), [
this](
const auto& tx)
959 { return !m_pool.exists(GenTxid::Txid(tx->GetHash()));}));
961 std::string err_string;
962 if (!m_pool.CheckPackageLimits(txns, m_limit_ancestors, m_limit_ancestor_size, m_limit_descendants,
963 m_limit_descendant_size, err_string)) {
970 bool MemPoolAccept::PolicyScriptChecks(
const ATMPArgs&
args, Workspace& ws)
981 if (!
CheckInputScripts(tx, state, m_view, scriptVerifyFlags,
true,
false, ws.m_precomputed_txdata)) {
998 bool MemPoolAccept::ConsensusScriptChecks(
const ATMPArgs&
args, Workspace& ws)
1003 const uint256& hash = ws.m_hash;
1024 ws.m_precomputed_txdata, m_active_chainstate.CoinsTip())) {
1025 LogPrintf(
"BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s\n", hash.
ToString(), state.
ToString());
1032 bool MemPoolAccept::Finalize(
const ATMPArgs&
args, Workspace& ws)
1037 const uint256& hash = ws.m_hash;
1039 const bool bypass_limits =
args.m_bypass_limits;
1041 std::unique_ptr<CTxMemPoolEntry>& entry = ws.m_entry;
1047 it->GetTx().GetHash().ToString(),
1049 FormatMoney(ws.m_modified_fees - ws.m_conflicting_fees),
1050 (
int)entry->GetTxSize() - (
int)ws.m_conflicting_size);
1051 ws.m_replaced_transactions.push_back(it->GetSharedTx());
1061 bool validForFeeEstimation = !bypass_limits && !
args.m_package_submission &&
IsCurrentForFeeEstimation(m_active_chainstate) && m_pool.HasNoInputsOf(tx);
1064 m_pool.addUnchecked(*entry, ws.m_ancestors, validForFeeEstimation);
1070 if (!
args.m_package_submission && !bypass_limits) {
1078 bool MemPoolAccept::SubmitPackage(
const ATMPArgs&
args, std::vector<Workspace>& workspaces,
1080 std::map<const uint256, const MempoolAcceptResult>& results)
1086 assert(std::all_of(workspaces.cbegin(), workspaces.cend(), [
this](
const auto& ws){
1087 return !m_pool.exists(GenTxid::Txid(ws.m_ptx->GetHash())); }));
1089 bool all_submitted =
true;
1094 for (Workspace& ws : workspaces) {
1095 if (!ConsensusScriptChecks(
args, ws)) {
1098 all_submitted =
false;
1100 strprintf(
"BUG! PolicyScriptChecks succeeded but ConsensusScriptChecks failed: %s",
1101 ws.m_ptx->GetHash().ToString()));
1106 std::string unused_err_string;
1107 if(!m_pool.CalculateMemPoolAncestors(*ws.m_entry, ws.m_ancestors, m_limit_ancestors,
1108 m_limit_ancestor_size, m_limit_descendants,
1109 m_limit_descendant_size, unused_err_string)) {
1112 all_submitted =
false;
1114 strprintf(
"BUG! Mempool ancestors or descendants were underestimated: %s",
1115 ws.m_ptx->GetHash().ToString()));
1122 if (!Finalize(
args, ws)) {
1125 all_submitted =
false;
1127 strprintf(
"BUG! Adding to mempool failed: %s", ws.m_ptx->GetHash().ToString()));
1135 std::chrono::hours{gArgs.GetIntArg(
"-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
1139 for (Workspace& ws : workspaces) {
1141 results.emplace(ws.m_ptx->GetWitnessHash(),
1145 all_submitted =
false;
1150 return all_submitted;
1171 if (
args.m_test_accept) {
1190 std::vector<Workspace> workspaces{};
1191 workspaces.reserve(txns.size());
1192 std::transform(txns.cbegin(), txns.cend(), std::back_inserter(workspaces),
1193 [](
const auto& tx) { return Workspace(tx); });
1194 std::map<const uint256, const MempoolAcceptResult> results;
1199 for (Workspace& ws : workspaces) {
1200 if (!PreChecks(
args, ws)) {
1211 m_viewmempool.PackageAddTransaction(ws.m_ptx);
1217 std::string err_string;
1218 if (txns.size() > 1 && !PackageMempoolChecks(txns, package_state)) {
1222 for (Workspace& ws : workspaces) {
1223 if (!PolicyScriptChecks(
args, ws)) {
1229 if (
args.m_test_accept) {
1232 results.emplace(ws.m_ptx->GetWitnessHash(),
1234 ws.m_vsize, ws.m_base_fees));
1240 if (!SubmitPackage(
args, workspaces, package_state, results)) {
1267 assert(package.size() > 1);
1270 const auto& child = package.back();
1271 std::unordered_set<uint256, SaltedTxidHasher> unconfirmed_parent_txids;
1272 std::transform(package.cbegin(), package.cend() - 1,
1273 std::inserter(unconfirmed_parent_txids, unconfirmed_parent_txids.end()),
1274 [](
const auto& tx) { return tx->GetHash(); });
1281 const CCoinsViewCache& coins_tip_cache = m_active_chainstate.CoinsTip();
1282 for (
const auto& input : child->vin) {
1284 args.m_coins_to_uncache.push_back(input.prevout);
1290 m_view.SetBackend(m_active_chainstate.CoinsTip());
1291 const auto package_or_confirmed = [
this, &unconfirmed_parent_txids](
const auto& input) {
1292 return unconfirmed_parent_txids.count(input.prevout.hash) > 0 || m_view.HaveCoin(input.prevout);
1294 if (!std::all_of(child->vin.cbegin(), child->vin.cend(), package_or_confirmed)) {
1300 m_view.SetBackend(m_dummy);
1303 std::map<const uint256, const MempoolAcceptResult> results;
1312 std::vector<CTransactionRef> txns_new;
1313 for (
const auto& tx : package) {
1315 const auto& txid = tx->
GetHash();
1321 auto iter = m_pool.GetIter(wtxid);
1322 assert(iter != std::nullopt);
1332 auto iter = m_pool.GetIter(txid);
1333 assert(iter != std::nullopt);
1338 txns_new.push_back(tx);
1345 auto submission_result = AcceptMultipleTransactions(txns_new,
args);
1347 for (
const auto& [wtxid, mempoolaccept_res] : results) {
1348 submission_result.m_tx_results.emplace(wtxid, mempoolaccept_res);
1350 return submission_result;
1356 int64_t accept_time,
bool bypass_limits,
bool test_accept)
1360 const CChainParams& chainparams{active_chainstate.m_params};
1361 assert(active_chainstate.GetMempool() !=
nullptr);
1362 CTxMemPool& pool{*active_chainstate.GetMempool()};
1364 std::vector<COutPoint> coins_to_uncache;
1365 auto args = MemPoolAccept::ATMPArgs::SingleAccept(chainparams, accept_time, bypass_limits, coins_to_uncache, test_accept);
1373 for (
const COutPoint& hashTx : coins_to_uncache)
1374 active_chainstate.CoinsTip().Uncache(hashTx);
1383 const Package& package,
bool test_accept)
1386 assert(!package.empty());
1387 assert(std::all_of(package.cbegin(), package.cend(), [](
const auto& tx){return tx != nullptr;}));
1389 std::vector<COutPoint> coins_to_uncache;
1394 auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(chainparams,
GetTime(), coins_to_uncache);
1395 return MemPoolAccept(pool, active_chainstate).AcceptMultipleTransactions(package,
args);
1397 auto args = MemPoolAccept::ATMPArgs::PackageChildWithParents(chainparams,
GetTime(), coins_to_uncache);
1398 return MemPoolAccept(pool, active_chainstate).AcceptPackage(package,
args);
1403 if (test_accept || result.m_state.IsInvalid()) {
1404 for (
const COutPoint& hashTx : coins_to_uncache) {
1423 nSubsidy >>= halvings;
1428 std::string ldb_name,
1429 size_t cache_size_bytes,
1431 bool should_wipe) : m_dbview(
1432 gArgs.GetDataDirNet() / ldb_name, cache_size_bytes, in_memory, should_wipe),
1433 m_catcherview(&m_dbview) {}
1435 void CoinsViews::InitCache()
1438 m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview);
1445 std::optional<uint256> from_snapshot_blockhash)
1446 : m_mempool(mempool),
1447 m_blockman(blockman),
1449 m_chainman(chainman),
1450 m_from_snapshot_blockhash(from_snapshot_blockhash) {}
1453 size_t cache_size_bytes,
1456 std::string leveldb_name)
1463 leveldb_name, cache_size_bytes, in_memory, should_wipe);
1466 void CChainState::InitCoinsCache(
size_t cache_size_bytes)
1479 bool CChainState::IsInitialBlockDownload()
const
1496 LogPrintf(
"Leaving InitialBlockDownload (latching to false)\n");
1505 std::string strCmd =
gArgs.
GetArg(
"-alertnotify",
"");
1506 if (strCmd.empty())
return;
1511 std::string singleQuote(
"'");
1513 safeStatus = singleQuote+safeStatus+singleQuote;
1514 boost::replace_all(strCmd,
"%s", safeStatus);
1516 std::thread
t(runCommand, strCmd);
1527 if (IsInitialBlockDownload()) {
1532 LogPrintf(
"%s: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n", __func__);
1550 LogPrintf(
"%s: invalid block=%s height=%d log2_work=%f date=%s\n", __func__,
1555 LogPrintf(
"%s: current best=%s height=%d log2_work=%f date=%s\n", __func__,
1611 LogPrintf(
"Using %zu MiB out of %zu/2 requested for script execution cache, able to store %zu elements\n",
1612 (nElems*
sizeof(
uint256)) >>20, (nMaxCacheSize*2)>>20, nElems);
1637 std::vector<CScriptCheck>* pvChecks)
1642 pvChecks->reserve(tx.
vin.size());
1659 std::vector<CTxOut> spent_outputs;
1660 spent_outputs.reserve(tx.
vin.size());
1662 for (
const auto& txin : tx.
vin) {
1666 spent_outputs.emplace_back(coin.
out);
1668 txdata.
Init(tx, std::move(spent_outputs));
1672 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
1684 check.
swap(pvChecks->back());
1685 }
else if (!check()) {
1713 if (cacheFullScriptStore && !pvChecks) {
1725 return state.
Error(strMessage);
1739 if (view.
HaveCoin(out)) fClean =
false;
1741 if (undo.nHeight == 0) {
1747 undo.nHeight = alternate.
nHeight;
1758 view.
AddCoin(out, std::move(undo), !fClean);
1772 error(
"DisconnectBlock(): failure reading undo data");
1776 if (blockUndo.
vtxundo.size() + 1 != block.
vtx.size()) {
1777 error(
"DisconnectBlock(): block and undo data inconsistent");
1782 for (
int i = block.
vtx.size() - 1; i >= 0; i--) {
1789 for (
size_t o = 0; o < tx.
vout.size(); o++) {
1790 if (!tx.
vout[o].scriptPubKey.IsUnspendable()) {
1793 bool is_spent = view.
SpendCoin(out, &coin);
1804 error(
"DisconnectBlock(): transaction and undo data inconsistent");
1807 for (
unsigned int j = tx.
vin.size(); j > 0;) {
1950 return AbortNode(state,
"Corrupt block found indicating potential hardware failure; shutting down");
1952 return error(
"%s: Consensus::CheckBlock: %s", __func__, state.
ToString());
1969 bool fScriptChecks =
true;
1978 if (it->second->GetAncestor(pindex->
nHeight) == pindex &&
2013 bool fEnforceBIP30 = !((pindex->
nHeight==91842 && pindex->
GetBlockHash() ==
uint256S(
"0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
2014 (pindex->
nHeight==91880 && pindex->
GetBlockHash() ==
uint256S(
"0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
2042 static constexpr
int BIP34_IMPLIES_BIP30_LIMIT = 1983702;
2079 if (fEnforceBIP30 || pindex->
nHeight >= BIP34_IMPLIES_BIP30_LIMIT) {
2080 for (
const auto& tx : block.
vtx) {
2081 for (
size_t o = 0; o < tx->
vout.size(); o++) {
2083 LogPrintf(
"ERROR: ConnectBlock(): tried to overwrite transaction\n");
2091 int nLockTimeFlags = 0;
2110 std::vector<PrecomputedTransactionData> txsdata(block.
vtx.size());
2112 std::vector<int> prevheights;
2115 int64_t nSigOpsCost = 0;
2116 blockundo.
vtxundo.reserve(block.
vtx.size() - 1);
2117 for (
unsigned int i = 0; i < block.
vtx.size(); i++)
2121 nInputs += tx.
vin.size();
2135 LogPrintf(
"ERROR: %s: accumulated fee in the block out of range.\n", __func__);
2142 prevheights.resize(tx.
vin.size());
2143 for (
size_t j = 0; j < tx.
vin.size(); j++) {
2147 if (!
SequenceLocks(tx, nLockTimeFlags, prevheights, *pindex)) {
2148 LogPrintf(
"ERROR: %s: contains a non-BIP68-final transaction\n", __func__);
2159 LogPrintf(
"ERROR: ConnectBlock(): too many sigops\n");
2165 std::vector<CScriptCheck> vChecks;
2166 bool fCacheResults = fJustCheck;
2172 return error(
"ConnectBlock(): CheckInputScripts on %s failed with %s",
2175 control.
Add(vChecks);
2188 if (block.
vtx[0]->GetValueOut() > blockReward) {
2189 LogPrintf(
"ERROR: ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)\n", block.
vtx[0]->GetValueOut(), blockReward);
2193 if (!control.
Wait()) {
2194 LogPrintf(
"ERROR: %s: CheckQueue failed\n", __func__);
2219 TRACE6(validation, block_connected,
2234 return this->GetCoinsCacheSizeState(
2240 size_t max_coins_cache_size_bytes,
2241 size_t max_mempool_size_bytes)
2246 int64_t nTotalSpace =
2247 max_coins_cache_size_bytes + std::max<int64_t>(int64_t(max_mempool_size_bytes) - nMempoolUsage, 0);
2250 static constexpr int64_t MAX_BLOCK_COINSDB_USAGE_BYTES = 10 * 1024 * 1024;
2251 int64_t large_threshold =
2252 std::max((9 * nTotalSpace) / 10, nTotalSpace - MAX_BLOCK_COINSDB_USAGE_BYTES);
2254 if (cacheSize > nTotalSpace) {
2255 LogPrintf(
"Cache size (%s) exceeds total space (%s)\n", cacheSize, nTotalSpace);
2257 }
else if (cacheSize > large_threshold) {
2266 int nManualPruneHeight)
2269 assert(this->CanFlushToDisk());
2270 static std::chrono::microseconds nLastWrite{0};
2271 static std::chrono::microseconds nLastFlush{0};
2272 std::set<int> setFilesToPrune;
2273 bool full_flush_completed =
false;
2280 bool fFlushForPrune =
false;
2281 bool fDoFullFlush =
false;
2293 if (nManualPruneHeight > 0) {
2303 if (!setFilesToPrune.empty()) {
2304 fFlushForPrune =
true;
2306 m_blockman.m_block_tree_db->WriteFlag(
"prunedblockfiles",
true);
2311 const auto nNow = GetTime<std::chrono::microseconds>();
2313 if (nLastWrite.count() == 0) {
2316 if (nLastFlush.count() == 0) {
2328 fDoFullFlush = (mode ==
FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune;
2330 if (fDoFullFlush || fPeriodicWrite) {
2333 return AbortNode(state,
"Disk space is too low!",
_(
"Disk space is too low!"));
2347 return AbortNode(state,
"Failed to write to block index database");
2351 if (fFlushForPrune) {
2359 if (fDoFullFlush && !
CoinsTip().GetBestBlock().IsNull()) {
2369 return AbortNode(state,
"Disk space is too low!",
_(
"Disk space is too low!"));
2373 return AbortNode(state,
"Failed to write to coin database");
2375 full_flush_completed =
true;
2380 (u_int64_t)coins_count,
2381 (u_int64_t)coins_mem_usage,
2382 (
bool)fFlushForPrune,
2383 (
bool)fDoFullFlush);
2385 if (full_flush_completed) {
2389 }
catch (
const std::runtime_error& e) {
2390 return AbortNode(state, std::string(
"System error while flushing: ") + e.what());
2414 static bool fWarned =
false;
2433 const std::string& func_name,
2434 const std::string&
prefix,
2439 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",
2441 tip->GetBlockHash().ToString(), tip->nHeight, tip->nVersion,
2442 log(tip->nChainWork.getdouble()) / log(2.0), (
unsigned long)tip->nChainTx,
2445 coins_tip.DynamicMemoryUsage() * (1.0 / (1 << 20)),
2446 coins_tip.GetCacheSize(),
2447 !warning_messages.empty() ?
strprintf(
" warning='%s'", warning_messages) :
"");
2450 void CChainState::UpdateTip(
const CBlockIndex* pindexNew)
2453 const auto& coins_tip = this->
CoinsTip();
2459 constexpr
int BACKGROUND_LOG_INTERVAL = 2000;
2460 if (pindexNew->
nHeight % BACKGROUND_LOG_INTERVAL == 0) {
2478 if (!this->IsInitialBlockDownload()) {
2514 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
2517 return error(
"DisconnectTip(): Failed to read block");
2524 if (DisconnectBlock(block, pindexDelete, view) !=
DISCONNECT_OK)
2526 bool flushed = view.
Flush();
2537 for (
auto it = block.
vtx.rbegin(); it != block.
vtx.rend(); ++it) {
2550 UpdateTip(pindexDelete->
pprev);
2617 std::shared_ptr<const CBlock> pthisBlock;
2619 std::shared_ptr<CBlock> pblockNew = std::make_shared<CBlock>();
2621 return AbortNode(state,
"Failed to read block");
2623 pthisBlock = pblockNew;
2625 pthisBlock = pblock;
2627 const CBlock& blockConnecting = *pthisBlock;
2634 bool rv =
ConnectBlock(blockConnecting, state, pindexNew, view);
2644 bool flushed = view.
Flush();
2662 UpdateTip(pindexNew);
2693 bool fInvalidAncestor =
false;
2703 if (fFailedChain || fMissingData) {
2710 while (pindexTest != pindexFailed) {
2713 }
else if (fMissingData) {
2718 std::make_pair(pindexFailed->
pprev, pindexFailed));
2721 pindexFailed = pindexFailed->
pprev;
2724 fInvalidAncestor =
true;
2727 pindexTest = pindexTest->
pprev;
2729 if (!fInvalidAncestor)
2761 bool fBlocksDisconnected =
false;
2772 AbortNode(state,
"Failed to disconnect block; see debug.log for details");
2775 fBlocksDisconnected =
true;
2779 std::vector<CBlockIndex*> vpindexToConnect;
2780 bool fContinue =
true;
2785 int nTargetHeight = std::min(
nHeight + 32, pindexMostWork->
nHeight);
2786 vpindexToConnect.clear();
2787 vpindexToConnect.reserve(nTargetHeight -
nHeight);
2790 vpindexToConnect.push_back(pindexIter);
2791 pindexIter = pindexIter->
pprev;
2797 if (!
ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool)) {
2804 fInvalidFound =
true;
2825 if (fBlocksDisconnected) {
2845 bool fNotify =
false;
2846 bool fInitialBlockDownload =
false;
2853 if (pindexHeader != pindexHeaderOld) {
2855 fInitialBlockDownload = chainstate.IsInitialBlockDownload();
2856 pindexHeaderOld = pindexHeader;
2874 bool CChainState::ActivateBestChain(
BlockValidationState& state, std::shared_ptr<const CBlock> pblock)
2907 bool blocks_connected =
false;
2913 if (pindexMostWork ==
nullptr) {
2918 if (pindexMostWork ==
nullptr || pindexMostWork ==
m_chain.
Tip()) {
2922 bool fInvalidFound =
false;
2923 std::shared_ptr<const CBlock> nullBlockPtr;
2924 if (!
ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->
GetBlockHash() ? pblock : nullBlockPtr, fInvalidFound, connectTrace)) {
2928 blocks_connected =
true;
2930 if (fInvalidFound) {
2932 pindexMostWork =
nullptr;
2937 assert(trace.pblock && trace.pindex);
2941 if (!blocks_connected)
return true;
2944 bool fInitialDownload = IsInitialBlockDownload();
2948 if (pindexFork != pindexNewTip) {
2965 }
while (pindexNewTip != pindexMostWork);
3004 return ActivateBestChain(state, std::shared_ptr<const CBlock>());
3014 if (pindex->
nHeight == 0)
return false;
3017 bool pindex_was_in_chain =
false;
3018 int disconnected = 0;
3032 std::multimap<const arith_uint256, CBlockIndex *> candidate_blocks_by_work;
3036 for (
const auto& entry :
m_blockman.m_block_index) {
3047 candidate_blocks_by_work.insert(std::make_pair(candidate->
nChainWork, candidate));
3064 pindex_was_in_chain =
true;
3077 if (!ret)
return false;
3097 auto candidate_it = candidate_blocks_by_work.lower_bound(invalid_walk_tip->
pprev->
nChainWork);
3098 while (candidate_it != candidate_blocks_by_work.end()) {
3101 candidate_it = candidate_blocks_by_work.erase(candidate_it);
3109 to_mark_failed = invalid_walk_tip;
3134 BlockMap::iterator it =
m_blockman.m_block_index.begin();
3135 while (it !=
m_blockman.m_block_index.end()) {
3146 if (pindex_was_in_chain) {
3158 BlockMap::iterator it =
m_blockman.m_block_index.begin();
3159 while (it !=
m_blockman.m_block_index.end()) {
3160 if (!it->second->IsValid() && it->second->GetAncestor(
nHeight) == pindex) {
3176 while (pindex !=
nullptr) {
3182 pindex = pindex->
pprev;
3190 pindexNew->
nTx = block.
vtx.size();
3192 pindexNew->nFile = pos.
nFile;
3193 pindexNew->nDataPos = pos.
nPos;
3194 pindexNew->nUndoPos = 0;
3204 std::deque<CBlockIndex*> queue;
3205 queue.push_back(pindexNew);
3208 while (!queue.empty()) {
3216 std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range =
m_blockman.
m_blocks_unlinked.equal_range(pindex);
3217 while (range.first != range.second) {
3218 std::multimap<CBlockIndex*, CBlockIndex*>::iterator it = range.first;
3219 queue.push_back(it->second);
3258 if (fCheckMerkleRoot) {
3282 if (block.
vtx.empty() || !block.
vtx[0]->IsCoinBase())
3284 for (
unsigned int i = 1; i < block.
vtx.size(); i++)
3285 if (block.
vtx[i]->IsCoinBase())
3290 for (
const auto& tx : block.
vtx) {
3300 unsigned int nSigOps = 0;
3301 for (
const auto& tx : block.
vtx)
3308 if (fCheckPOW && fCheckMerkleRoot)
3317 static const std::vector<unsigned char>
nonce(32, 0x00);
3320 tx.
vin[0].scriptWitness.stack.resize(1);
3321 tx.
vin[0].scriptWitness.stack[0] =
nonce;
3328 std::vector<unsigned char> commitment;
3330 std::vector<unsigned char> ret(32, 0x00);
3346 tx.
vout.push_back(out);
3365 assert(pindexPrev !=
nullptr);
3366 const int nHeight = pindexPrev->nHeight + 1;
3378 CBlockIndex* pcheckpoint = blockman.GetLastCheckpoint(params.Checkpoints());
3379 if (pcheckpoint && nHeight < pcheckpoint->
nHeight) {
3380 LogPrintf(
"ERROR: %s: forked chain older than last checkpoint (height %d)\n", __func__,
nHeight);
3386 if (block.
GetBlockTime() <= pindexPrev->GetMedianTimePast())
3412 const int nHeight = pindexPrev ==
nullptr ? 0 : pindexPrev->
nHeight + 1;
3415 int nLockTimeFlags = 0;
3417 assert(pindexPrev !=
nullptr);
3426 for (
const auto& tx : block.
vtx) {
3436 if (block.
vtx[0]->vin[0].scriptSig.size() <
expect.size() ||
3437 !std::equal(
expect.begin(),
expect.end(), block.
vtx[0]->vin[0].scriptSig.begin())) {
3450 bool fHaveWitness =
false;
3454 bool malleated =
false;
3459 if (block.
vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.
vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
3463 if (memcmp(hashWitness.
begin(), &block.
vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
3466 fHaveWitness =
true;
3471 if (!fHaveWitness) {
3472 for (
const auto& tx : block.
vtx) {
3497 BlockMap::iterator miSelf{
m_blockman.m_block_index.find(hash)};
3499 if (miSelf !=
m_blockman.m_block_index.end()) {
3523 pindexPrev = (*mi).second;
3558 if (pindexPrev->
GetAncestor(failedit->nHeight) == failedit) {
3561 while (invalid_walk != failedit) {
3564 invalid_walk = invalid_walk->
pprev;
3603 const double progress{100.0 * last_accepted.nHeight / (last_accepted.nHeight + blocks_left)};
3604 LogPrintf(
"Synchronizing blockheaders, height: %d (~%.2f%%)\n", last_accepted.nHeight, progress);
3613 const CBlock& block = *pblock;
3615 if (fNewBlock) *fNewBlock =
false;
3619 CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
3624 if (!accepted_header)
3647 if (fAlreadyHave)
return true;
3649 if (pindex->
nTx != 0)
return true;
3650 if (!fHasMoreOrSameWork)
return true;
3651 if (fTooFarAhead)
return true;
3675 if (fNewBlock) *fNewBlock =
true;
3678 if (blockPos.IsNull()) {
3679 state.
Error(
strprintf(
"%s: Failed to find position to write new block to disk", __func__));
3683 }
catch (
const std::runtime_error& e) {
3684 return AbortNode(state, std::string(
"System error: ") + e.what());
3700 if (new_block) *new_block =
false;
3719 return error(
"%s: AcceptBlock FAILED (%s)", __func__, state.
ToString());
3727 return error(
"%s: ActivateBestChain failed (%s)", __func__, state.
ToString());
3753 bool fCheckMerkleRoot)
3760 indexDummy.
pprev = pindexPrev;
3766 return error(
"%s: Consensus::ContextualCheckBlockHeader: %s", __func__, state.
ToString());
3768 return error(
"%s: Consensus::CheckBlock: %s", __func__, state.
ToString());
3770 return error(
"%s: Consensus::ContextualCheckBlock: %s", __func__, state.
ToString());
3771 if (!chainstate.
ConnectBlock(block, state, &indexDummy, viewNew,
true)) {
3818 LogPrintf(
"Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n",
3828 uiInterface.ShowProgress(
_(
"Verifying blocks…").translated, 0,
false);
3840 int nCheckLevel,
int nCheckDepth)
3848 if (nCheckDepth <= 0 || nCheckDepth > chainstate.
m_chain.
Height())
3850 nCheckLevel = std::max(0, std::min(4, nCheckLevel));
3851 LogPrintf(
"Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
3855 int nGoodTransactions = 0;
3863 const int percentageDone = std::max(1, std::min(99, (
int)(((
double)(chainstate.
m_chain.
Height() - pindex->
nHeight)) / (
double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
3864 if (reportDone < percentageDone/10) {
3867 reportDone = percentageDone/10;
3869 uiInterface.ShowProgress(
_(
"Verifying blocks…").translated, percentageDone,
false);
3875 LogPrintf(
"VerifyDB(): block verification stopping at height %d (pruning, no data)\n", pindex->
nHeight);
3883 if (nCheckLevel >= 1 && !
CheckBlock(block, state, consensus_params))
3884 return error(
"%s: *** found bad block at %d, hash=%s (%s)\n", __func__,
3887 if (nCheckLevel >= 2 && pindex) {
3905 nGoodTransactions = 0;
3906 pindexFailure = pindex;
3908 nGoodTransactions += block.
vtx.size();
3914 return error(
"VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainstate.
m_chain.
Height() - pindexFailure->
nHeight + 1, nGoodTransactions);
3920 if (nCheckLevel >= 4) {
3922 const int percentageDone = std::max(1, std::min(99, 100 - (
int)(((
double)(chainstate.
m_chain.
Height() - pindex->
nHeight)) / (
double)nCheckDepth * 50)));
3923 if (reportDone < percentageDone/10) {
3926 reportDone = percentageDone/10;
3928 uiInterface.ShowProgress(
_(
"Verifying blocks…").translated, percentageDone,
false);
3933 if (!chainstate.
ConnectBlock(block, state, pindex, coins)) {
3941 LogPrintf(
"No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions);
3957 if (!tx->IsCoinBase()) {
3958 for (
const CTxIn &txin : tx->vin) {
3976 if (hashHeads.empty())
return true;
3977 if (hashHeads.size() != 2)
return error(
"ReplayBlocks(): unknown inconsistent state");
3979 uiInterface.ShowProgress(
_(
"Replaying blocks…").translated, 0,
false);
3986 if (
m_blockman.m_block_index.count(hashHeads[0]) == 0) {
3987 return error(
"ReplayBlocks(): reorganization to unknown block requested");
3989 pindexNew =
m_blockman.m_block_index[hashHeads[0]];
3991 if (!hashHeads[1].IsNull()) {
3992 if (
m_blockman.m_block_index.count(hashHeads[1]) == 0) {
3993 return error(
"ReplayBlocks(): reorganization from unknown block requested");
3995 pindexOld =
m_blockman.m_block_index[hashHeads[1]];
3997 assert(pindexFork !=
nullptr);
4001 while (pindexOld != pindexFork) {
4017 pindexOld = pindexOld->
pprev;
4021 int nForkHeight = pindexFork ? pindexFork->
nHeight : 0;
4025 uiInterface.ShowProgress(
_(
"Replaying blocks…").translated, (
int) ((
nHeight - nForkHeight) * 100.0 / (pindexNew->
nHeight - nForkHeight)) ,
false);
4047 block = block->pprev;
4056 nBlockSequenceId = 1;
4068 if (mempool) mempool->
clear();
4071 warningcache[b].clear();
4082 bool ret =
m_blockman.LoadBlockIndexDB(*
this);
4083 if (!ret)
return false;
4084 needs_init =
m_blockman.m_block_index.empty();
4094 LogPrintf(
"Initializing databases...\n");
4113 if (blockPos.IsNull()) {
4114 return error(
"%s: writing genesis block to disk failed", __func__);
4118 }
catch (
const std::runtime_error& e) {
4119 return error(
"%s: failed to write genesis block: %s", __func__, e.what());
4125 void CChainState::LoadExternalBlockFile(FILE* fileIn,
FlatFilePos* dbp)
4129 static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
4136 uint64_t nRewind = blkdat.GetPos();
4137 while (!blkdat.eof()) {
4140 blkdat.SetPos(nRewind);
4143 unsigned int nSize = 0;
4148 nRewind = blkdat.GetPos() + 1;
4157 }
catch (
const std::exception&) {
4163 uint64_t nBlockPos = blkdat.GetPos();
4165 dbp->
nPos = nBlockPos;
4166 blkdat.SetLimit(nBlockPos + nSize);
4167 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4170 nRewind = blkdat.GetPos();
4172 uint256 hash = block.GetHash();
4178 block.hashPrevBlock.ToString());
4180 mapBlocksUnknownParent.insert(std::make_pair(block.hashPrevBlock, *dbp));
4188 if (
AcceptBlock(pblock, state,
nullptr,
true, dbp,
nullptr)) {
4202 if (!ActivateBestChain(state,
nullptr)) {
4210 std::deque<uint256> queue;
4211 queue.push_back(hash);
4212 while (!queue.empty()) {
4215 std::pair<std::multimap<uint256, FlatFilePos>::iterator, std::multimap<uint256, FlatFilePos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
4216 while (range.first != range.second) {
4217 std::multimap<uint256, FlatFilePos>::iterator it = range.first;
4218 std::shared_ptr<CBlock> pblockrecursive = std::make_shared<CBlock>();
4220 LogPrint(
BCLog::REINDEX,
"%s: Processing out of order child %s of %s\n", __func__, pblockrecursive->GetHash().ToString(),
4224 if (
AcceptBlock(pblockrecursive, dummy,
nullptr,
true, &it->second,
nullptr)) {
4226 queue.push_back(pblockrecursive->GetHash());
4230 mapBlocksUnknownParent.erase(it);
4234 }
catch (
const std::exception& e) {
4235 LogPrintf(
"%s: Deserialize or I/O error - %s\n", __func__, e.what());
4238 }
catch (
const std::runtime_error& e) {
4239 AbortNode(std::string(
"System error: ") + e.what());
4261 std::multimap<CBlockIndex*,CBlockIndex*> forward;
4262 for (
const std::pair<const uint256, CBlockIndex*>& entry :
m_blockman.m_block_index) {
4263 forward.insert(std::make_pair(entry.second->pprev, entry.second));
4268 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeGenesis = forward.equal_range(
nullptr);
4270 rangeGenesis.first++;
4271 assert(rangeGenesis.first == rangeGenesis.second);
4282 CBlockIndex* pindexFirstNotTransactionsValid =
nullptr;
4284 CBlockIndex* pindexFirstNotScriptsValid =
nullptr;
4285 while (pindex !=
nullptr) {
4287 if (pindexFirstInvalid ==
nullptr && pindex->nStatus &
BLOCK_FAILED_VALID) pindexFirstInvalid = pindex;
4291 pindexFirstMissing = pindex;
4293 if (pindexFirstNeverProcessed ==
nullptr && pindex->
nTx == 0) pindexFirstNeverProcessed = pindex;
4300 if (pindexFirstNotTransactionsValid ==
nullptr &&
4302 pindexFirstNotTransactionsValid = pindex;
4305 if (pindexFirstNotChainValid ==
nullptr &&
4307 pindexFirstNotChainValid = pindex;
4310 if (pindexFirstNotScriptsValid ==
nullptr &&
4312 pindexFirstNotScriptsValid = pindex;
4317 if (pindex->
pprev ==
nullptr) {
4330 assert(pindexFirstMissing == pindexFirstNeverProcessed);
4352 assert(pindexFirstNotTreeValid ==
nullptr);
4356 if (pindexFirstInvalid ==
nullptr) {
4361 if (pindexFirstInvalid ==
nullptr) {
4372 if (is_active && (pindexFirstMissing ==
nullptr || pindex ==
m_chain.
Tip())) {
4383 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeUnlinked =
m_blockman.
m_blocks_unlinked.equal_range(pindex->
pprev);
4384 bool foundInUnlinked =
false;
4385 while (rangeUnlinked.first != rangeUnlinked.second) {
4386 assert(rangeUnlinked.first->first == pindex->
pprev);
4387 if (rangeUnlinked.first->second == pindex) {
4388 foundInUnlinked =
true;
4391 rangeUnlinked.first++;
4393 if (pindex->
pprev && (pindex->nStatus &
BLOCK_HAVE_DATA) && pindexFirstNeverProcessed !=
nullptr && pindexFirstInvalid ==
nullptr) {
4398 if (pindexFirstMissing ==
nullptr)
assert(!foundInUnlinked);
4399 if (pindex->
pprev && (pindex->nStatus &
BLOCK_HAVE_DATA) && pindexFirstNeverProcessed ==
nullptr && pindexFirstMissing !=
nullptr) {
4411 if (pindexFirstInvalid ==
nullptr) {
4420 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> range = forward.equal_range(pindex);
4421 if (range.first != range.second) {
4423 pindex = range.first->second;
4432 if (pindex == pindexFirstInvalid) pindexFirstInvalid =
nullptr;
4433 if (pindex == pindexFirstMissing) pindexFirstMissing =
nullptr;
4434 if (pindex == pindexFirstNeverProcessed) pindexFirstNeverProcessed =
nullptr;
4435 if (pindex == pindexFirstNotTreeValid) pindexFirstNotTreeValid =
nullptr;
4436 if (pindex == pindexFirstNotTransactionsValid) pindexFirstNotTransactionsValid =
nullptr;
4437 if (pindex == pindexFirstNotChainValid) pindexFirstNotChainValid =
nullptr;
4438 if (pindex == pindexFirstNotScriptsValid) pindexFirstNotScriptsValid =
nullptr;
4442 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangePar = forward.equal_range(pindexPar);
4443 while (rangePar.first->second != pindex) {
4444 assert(rangePar.first != rangePar.second);
4449 if (rangePar.first != rangePar.second) {
4451 pindex = rangePar.first->second;
4463 assert(nNodes == forward.size());
4470 return strprintf(
"Chainstate [%s] @ height %d (%s)",
4475 bool CChainState::ResizeCoinsCaches(
size_t coinstip_size,
size_t coinsdb_size)
4488 LogPrintf(
"[%s] resized coinsdb cache to %.1f MiB\n",
4489 this->
ToString(), coinsdb_size * (1.0 / 1024 / 1024));
4490 LogPrintf(
"[%s] resized coinstip cache to %.1f MiB\n",
4491 this->
ToString(), coinstip_size * (1.0 / 1024 / 1024));
4496 if (coinstip_size > old_coinstip_size) {
4515 LogPrintf(
"Failed to open mempool file from disk. Continuing anyway.\n");
4520 int64_t expired = 0;
4522 int64_t already_there = 0;
4523 int64_t unbroadcast = 0;
4543 CAmount amountdelta = nFeeDelta;
4547 if (nTime > nNow - nExpiryTimeout) {
4549 const auto& accepted =
AcceptToMemoryPool(active_chainstate, tx, nTime,
false,
false);
4569 std::map<uint256, CAmount> mapDeltas;
4572 for (
const auto& i : mapDeltas) {
4576 std::set<uint256> unbroadcast_txids;
4577 file >> unbroadcast_txids;
4578 unbroadcast = unbroadcast_txids.size();
4579 for (
const auto& txid : unbroadcast_txids) {
4584 }
catch (
const std::exception& e) {
4585 LogPrintf(
"Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
4589 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);
4597 std::map<uint256, CAmount> mapDeltas;
4598 std::vector<TxMempoolInfo> vinfo;
4599 std::set<uint256> unbroadcast_txids;
4601 static Mutex dump_mutex;
4606 for (
const auto &i : pool.mapDeltas) {
4607 mapDeltas[i.first] = i.second;
4616 FILE* filestr{mockable_fopen_function(
gArgs.
GetDataDirNet() /
"mempool.dat.new",
"wb")};
4626 file << (uint64_t)vinfo.size();
4627 for (
const auto& i : vinfo) {
4630 file << int64_t{i.nFeeDelta};
4631 mapDeltas.erase(i.tx->GetHash());
4636 LogPrintf(
"Writing %d unbroadcast transactions to disk.\n", unbroadcast_txids.size());
4637 file << unbroadcast_txids;
4640 throw std::runtime_error(
"FileCommit failed");
4643 throw std::runtime_error(
"Rename failed");
4646 LogPrintf(
"Dumped mempool: %gs to copy, %gs to dump\n", (mid-start)*
MICRO, (last-mid)*
MICRO);
4647 }
catch (
const std::exception& e) {
4648 LogPrintf(
"Failed to dump mempool: %s. Continuing anyway.\n", e.what());
4657 if (pindex ==
nullptr)
4660 int64_t nNow = time(
nullptr);
4670 return std::min<double>(pindex->
nChainTx / fTxTotal, 1.0);
4676 if (m_active_chainstate && m_active_chainstate->m_from_snapshot_blockhash) {
4678 return m_active_chainstate->m_from_snapshot_blockhash;
4680 return std::nullopt;
4686 std::vector<CChainState*> out;
4689 out.push_back(m_ibd_chainstate.get());
4692 if (m_snapshot_chainstate) {
4693 out.push_back(m_snapshot_chainstate.get());
4699 CChainState& ChainstateManager::InitializeChainstate(
4700 CTxMemPool* mempool,
const std::optional<uint256>& snapshot_blockhash)
4703 bool is_snapshot = snapshot_blockhash.has_value();
4704 std::unique_ptr<CChainState>& to_modify =
4705 is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate;
4708 throw std::logic_error(
"should not be overwriting a chainstate");
4713 if (is_snapshot || (!is_snapshot && !m_active_chainstate)) {
4714 LogPrintf(
"Switching active chainstate to %s\n", to_modify->ToString());
4715 m_active_chainstate = to_modify.get();
4717 throw std::logic_error(
"unexpected chainstate activation");
4727 const auto assumeutxo_found = valid_assumeutxos_map.find(height);
4729 if (assumeutxo_found != valid_assumeutxos_map.end()) {
4730 return &assumeutxo_found->second;
4743 LogPrintf(
"[snapshot] can't activate a snapshot-based chainstate more than once\n");
4747 int64_t current_coinsdb_cache_size{0};
4748 int64_t current_coinstip_cache_size{0};
4756 static constexpr
double IBD_CACHE_PERC = 0.01;
4757 static constexpr
double SNAPSHOT_CACHE_PERC = 0.99;
4775 static_cast<size_t>(current_coinstip_cache_size * IBD_CACHE_PERC),
4776 static_cast<size_t>(current_coinsdb_cache_size * IBD_CACHE_PERC));
4780 return std::make_unique<CChainState>(
4781 nullptr,
m_blockman, *
this, base_blockhash));
4785 snapshot_chainstate->InitCoinsDB(
4786 static_cast<size_t>(current_coinsdb_cache_size * SNAPSHOT_CACHE_PERC),
4787 in_memory,
false,
"chainstate");
4788 snapshot_chainstate->InitCoinsCache(
4789 static_cast<size_t>(current_coinstip_cache_size * SNAPSHOT_CACHE_PERC));
4793 *snapshot_chainstate, coins_file, metadata);
4802 assert(!m_snapshot_chainstate);
4803 m_snapshot_chainstate.swap(snapshot_chainstate);
4804 const bool chaintip_loaded = m_snapshot_chainstate->LoadChainTip();
4807 m_active_chainstate = m_snapshot_chainstate.get();
4809 LogPrintf(
"[snapshot] successfully activated snapshot %s\n", base_blockhash.
ToString());
4811 m_snapshot_chainstate->CoinsTip().DynamicMemoryUsage() / (1000 * 1000));
4813 this->MaybeRebalanceCaches();
4822 snapshot_loaded ?
"saving snapshot chainstate" :
"flushing coins cache",
4826 coins_cache.
Flush();
4842 if (!snapshot_start_block) {
4844 LogPrintf(
"[snapshot] Did not find snapshot start blockheader %s\n",
4849 int base_height = snapshot_start_block->
nHeight;
4852 if (!maybe_au_data) {
4853 LogPrintf(
"[snapshot] assumeutxo height in snapshot metadata not recognized "
4854 "(%d) - refusing to load snapshot\n", base_height);
4865 LogPrintf(
"[snapshot] loading coins from snapshot %s\n", base_blockhash.
ToString());
4866 int64_t coins_processed{0};
4868 while (coins_left > 0) {
4870 coins_file >> outpoint;
4872 }
catch (
const std::ios_base::failure&) {
4873 LogPrintf(
"[snapshot] bad snapshot format or truncated snapshot after deserializing %d coins\n",
4874 coins_count - coins_left);
4877 if (coin.
nHeight > base_height ||
4878 outpoint.
n >= std::numeric_limits<decltype(outpoint.
n)>::max()
4880 LogPrintf(
"[snapshot] bad snapshot data after deserializing %d coins\n",
4881 coins_count - coins_left);
4890 if (coins_processed % 1000000 == 0) {
4891 LogPrintf(
"[snapshot] %d coins loaded (%.2f%%, %.2f MB)\n",
4893 static_cast<float>(coins_processed) * 100 /
static_cast<float>(coins_count),
4901 if (coins_processed % 120000 == 0) {
4907 return snapshot_chainstate.GetCoinsCacheSizeState());
4928 bool out_of_coins{
false};
4930 coins_file >> outpoint;
4931 }
catch (
const std::ios_base::failure&) {
4933 out_of_coins =
true;
4935 if (!out_of_coins) {
4936 LogPrintf(
"[snapshot] bad snapshot - coins left over after deserializing %d coins\n",
4941 LogPrintf(
"[snapshot] loaded %d (%.2f MB) coins from snapshot %s\n",
4951 CCoinsStats stats{CoinStatsHashType::HASH_SERIALIZED};
4952 auto breakpoint_fnc = [] { };
4959 LogPrintf(
"[snapshot] failed to generate coins stats\n");
4965 LogPrintf(
"[snapshot] bad snapshot content hash: expected %s, got %s\n",
4982 constexpr
int AFTER_GENESIS_START{1};
4984 for (
int i = AFTER_GENESIS_START; i <= snapshot_chainstate.
m_chain.
Height(); ++i) {
4985 index = snapshot_chainstate.
m_chain[i];
5020 LogPrintf(
"[snapshot] validated snapshot (%.2f MB)\n",
5028 assert(m_active_chainstate);
5029 return *m_active_chainstate;
5035 return m_snapshot_chainstate && m_active_chainstate == m_snapshot_chainstate.get();
5038 void ChainstateManager::Unload()
5042 chainstate->m_chain.SetTip(
nullptr);
5043 chainstate->UnloadBlockIndex();
5051 void ChainstateManager::Reset()
5054 m_ibd_chainstate.reset();
5055 m_snapshot_chainstate.reset();
5056 m_active_chainstate =
nullptr;
5060 void ChainstateManager::MaybeRebalanceCaches()
5063 if (m_ibd_chainstate && !m_snapshot_chainstate) {
5064 LogPrintf(
"[snapshot] allocating all cache to the IBD chainstate\n");
5068 else if (m_snapshot_chainstate && !m_ibd_chainstate) {
5069 LogPrintf(
"[snapshot] allocating all cache to the snapshot chainstate\n");