6 #include <bitcoin-build-config.h> 100 "level 0 reads the blocks from disk",
101 "level 1 verifies block validity",
102 "level 2 verifies undo data",
103 "level 3 checks disconnection of tip blocks",
104 "level 4 tries to reconnect the blocks",
105 "each level includes the checks of the previous levels",
143 std::vector<CScriptCheck>* pvChecks =
nullptr)
156 const int nBlockHeight = active_chain_tip.nHeight + 1;
163 const int64_t nBlockTime{active_chain_tip.GetMedianTimePast()};
165 return IsFinalTx(tx, nBlockHeight, nBlockTime);
179 std::optional<std::vector<int>> CalculatePrevHeights(
184 std::vector<int> prev_heights;
185 prev_heights.resize(tx.
vin.size());
186 for (
size_t i = 0; i < tx.
vin.size(); ++i) {
187 if (
auto coin{coins.
GetCoin(tx.
vin[i].prevout)}) {
207 auto prev_heights{CalculatePrevHeights(*tip, coins_view, tx)};
208 if (!prev_heights.has_value())
return std::nullopt;
211 next_tip.
pprev = tip;
229 int max_input_height{0};
230 for (
const int height : prev_heights.value()) {
232 if (height != next_tip.
nHeight) {
233 max_input_height = std::max(max_input_height, height);
271 int expired = pool.Expire(GetTime<std::chrono::seconds>() - pool.m_opts.expiry);
276 std::vector<COutPoint> vNoSpendsRemaining;
277 pool.TrimToSize(pool.m_opts.max_size_bytes, &vNoSpendsRemaining);
278 for (
const COutPoint& removed : vNoSpendsRemaining)
279 coins_cache.Uncache(removed);
285 if (active_chainstate.m_chainman.IsInitialBlockDownload()) {
290 if (active_chainstate.m_chain.Height() < active_chainstate.m_chainman.m_best_header->nHeight - 1) {
304 std::vector<uint256> vHashUpdate;
311 const auto queuedTx = disconnectpool.
take();
312 auto it = queuedTx.rbegin();
313 while (it != queuedTx.rend()) {
315 if (!fAddToMempool || (*it)->IsCoinBase() ||
323 vHashUpdate.push_back((*it)->GetHash());
364 it->UpdateLockPoints(*new_lock_points);
371 if (it->GetSpendsCoinbase()) {
377 if (coin.IsCoinBase() && mempool_spend_height - coin.nHeight <
COINBASE_MATURITY) {
413 if (coin.
IsSpent())
return false;
425 const Coin& coinFromUTXOSet = coins_tip.AccessCoin(txin.
prevout);
443 m_viewmempool(&active_chainstate.CoinsTip(), m_pool),
444 m_active_chainstate(active_chainstate)
452 const int64_t m_accept_time;
453 const bool m_bypass_limits;
461 std::vector<COutPoint>& m_coins_to_uncache;
463 const bool m_test_accept;
467 const bool m_allow_replacement;
469 const bool m_allow_sibling_eviction;
474 const bool m_package_submission;
478 const bool m_package_feerates;
483 const std::optional<CFeeRate> m_client_maxfeerate;
486 const bool m_allow_carveouts;
489 static ATMPArgs SingleAccept(
const CChainParams& chainparams, int64_t accept_time,
490 bool bypass_limits, std::vector<COutPoint>& coins_to_uncache,
492 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,
524 static ATMPArgs PackageChildWithParents(
const CChainParams& chainparams, int64_t accept_time,
525 std::vector<COutPoint>& coins_to_uncache,
const std::optional<CFeeRate>& client_maxfeerate) {
526 return ATMPArgs{ chainparams,
541 static ATMPArgs SingleInPackageAccept(
const ATMPArgs& package_args) {
542 return ATMPArgs{ package_args.m_chainparams,
543 package_args.m_accept_time,
545 package_args.m_coins_to_uncache,
546 package_args.m_test_accept,
551 package_args.m_client_maxfeerate,
562 std::vector<COutPoint>& coins_to_uncache,
564 bool allow_replacement,
565 bool allow_sibling_eviction,
566 bool package_submission,
567 bool package_feerates,
568 std::optional<CFeeRate> client_maxfeerate,
569 bool allow_carveouts)
570 : m_chainparams{chainparams},
571 m_accept_time{accept_time},
572 m_bypass_limits{bypass_limits},
573 m_coins_to_uncache{coins_to_uncache},
574 m_test_accept{test_accept},
575 m_allow_replacement{allow_replacement},
576 m_allow_sibling_eviction{allow_sibling_eviction},
577 m_package_submission{package_submission},
578 m_package_feerates{package_feerates},
579 m_client_maxfeerate{client_maxfeerate},
580 m_allow_carveouts{allow_carveouts}
584 if (m_package_feerates) {
585 Assume(m_package_submission);
586 Assume(!m_allow_carveouts);
587 Assume(!m_allow_sibling_eviction);
589 if (m_allow_sibling_eviction)
Assume(m_allow_replacement);
629 explicit Workspace(
const CTransactionRef& ptx) : m_ptx(ptx), m_hash(ptx->GetHash()) {}
632 std::set<Txid> m_conflicts;
642 bool m_sibling_eviction{
false};
677 bool PackageMempoolChecks(
const std::vector<CTransactionRef>& txns,
678 std::vector<Workspace>& workspaces,
699 std::map<Wtxid, MempoolAcceptResult>& results)
707 CAmount mempoolRejectFee = m_pool.GetMinFee().GetFee(package_size);
708 if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) {
712 if (package_fee < m_pool.m_opts.min_relay_feerate.GetFee(package_size)) {
714 strprintf(
"%d < %d", package_fee, m_pool.m_opts.min_relay_feerate.GetFee(package_size)));
721 return m_active_chainstate.m_chainman.m_validation_cache;
734 struct SubPackageState {
736 CAmount m_total_modified_fees{0};
738 int64_t m_total_vsize{0};
745 std::list<CTransactionRef> m_replaced_transactions;
747 std::unique_ptr<CTxMemPool::ChangeSet> m_changeset;
752 size_t m_conflicting_size{0};
755 struct SubPackageState m_subpackage;
760 m_subpackage = SubPackageState{};
763 CleanupTemporaryCoins();
767 bool MemPoolAccept::PreChecks(ATMPArgs&
args, Workspace& ws)
773 const Txid& hash = ws.m_hash;
776 const int64_t nAcceptTime =
args.m_accept_time;
777 const bool bypass_limits =
args.m_bypass_limits;
778 std::vector<COutPoint>& coins_to_uncache =
args.m_coins_to_uncache;
793 if (m_pool.m_opts.require_standard && !
IsStandardTx(tx, m_pool.m_opts.max_datacarrier_bytes, m_pool.m_opts.permit_bare_multisig, m_pool.m_opts.dust_relay_feerate, reason)) {
821 if (ptxConflicting) {
822 if (!
args.m_allow_replacement) {
826 ws.m_conflicts.insert(ptxConflicting->
GetHash());
830 m_view.SetBackend(m_viewmempool);
836 coins_to_uncache.push_back(txin.
prevout);
842 if (!m_view.HaveCoin(txin.
prevout)) {
857 m_view.GetBestBlock();
862 m_view.SetBackend(m_dummy);
864 assert(m_active_chainstate.m_blockman.LookupBlockIndex(m_view.GetBestBlock()) == m_active_chainstate.m_chain.Tip());
871 const std::optional<LockPoints> lock_points{
CalculateLockPointsAtTip(m_active_chainstate.m_chain.Tip(), m_view, tx)};
894 bool fSpendsCoinbase =
false;
896 const Coin &coin = m_view.AccessCoin(txin.
prevout);
898 fSpendsCoinbase =
true;
905 const uint64_t entry_sequence = bypass_limits ? 0 : m_pool.GetSequence();
906 if (!m_subpackage.m_changeset) {
907 m_subpackage.m_changeset = m_pool.GetChangeSet();
909 ws.m_tx_handle = m_subpackage.m_changeset->StageAddition(ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(), entry_sequence, fSpendsCoinbase, nSigOpsCost, lock_points.value());
912 ws.m_modified_fees = ws.m_tx_handle->GetModifiedFee();
914 ws.m_vsize = ws.m_tx_handle->GetTxSize();
917 if (m_pool.m_opts.require_standard) {
918 if (!
PreCheckEphemeralTx(*ptx, m_pool.m_opts.dust_relay_feerate, ws.m_base_fees, ws.m_modified_fees, state)) {
933 if (!bypass_limits && ws.m_ptx->version !=
TRUC_VERSION && ws.m_modified_fees < m_pool.m_opts.min_relay_feerate.GetFee(ws.m_vsize)) {
937 strprintf(
"%d < %d", ws.m_modified_fees, m_pool.m_opts.min_relay_feerate.GetFee(ws.m_vsize)));
942 if (!bypass_limits && !
args.m_package_feerates && !
CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state))
return false;
944 ws.m_iters_conflicting = m_pool.GetIterSet(ws.m_conflicts);
951 if (ws.m_conflicts.size() == 1 &&
args.m_allow_carveouts) {
979 assert(ws.m_iters_conflicting.size() == 1);
986 if (
auto ancestors{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, maybe_rbf_limits)}) {
987 ws.m_ancestors = std::move(*ancestors);
993 if (!
args.m_allow_carveouts) {
1018 if (
auto ancestors_retry{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, cpfp_carve_out_limits)}) {
1019 ws.m_ancestors = std::move(*ancestors_retry);
1028 if (
const auto err{
SingleTRUCChecks(ws.m_ptx, ws.m_ancestors, ws.m_conflicts, ws.m_vsize)}) {
1030 if (
args.m_allow_sibling_eviction && err->second !=
nullptr) {
1036 ws.m_conflicts.insert(err->second->GetHash());
1040 ws.m_iters_conflicting.insert(m_pool.GetIter(err->second->GetHash()).value());
1041 ws.m_sibling_eviction =
true;
1062 m_subpackage.m_rbf |= !ws.m_conflicts.empty();
1066 bool MemPoolAccept::ReplacementChecks(Workspace& ws)
1072 const uint256& hash = ws.m_hash;
1075 CFeeRate newFeeRate(ws.m_modified_fees, ws.m_vsize);
1089 strprintf(
"insufficient fee%s", ws.m_sibling_eviction ?
" (including sibling eviction)" :
""), *err_string);
1097 strprintf(
"too many potential replacements%s", ws.m_sibling_eviction ?
" (including sibling eviction)" :
""), *err_string);
1102 Assume(!ws.m_sibling_eviction);
1104 strprintf(
"replacement-adds-unconfirmed%s", ws.m_sibling_eviction ?
" (including sibling eviction)" :
""), *err_string);
1110 m_subpackage.m_conflicting_fees += it->GetModifiedFee();
1111 m_subpackage.m_conflicting_size += it->GetTxSize();
1113 if (
const auto err_string{
PaysForRBF(m_subpackage.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
1114 m_pool.m_opts.incremental_relay_feerate, hash)}) {
1117 strprintf(
"insufficient fee%s", ws.m_sibling_eviction ?
" (including sibling eviction)" :
""), *err_string);
1121 for (
auto it : all_conflicts) {
1122 m_subpackage.m_changeset->StageRemoval(it);
1127 bool MemPoolAccept::PackageMempoolChecks(
const std::vector<CTransactionRef>& txns,
1128 std::vector<Workspace>& workspaces,
1129 const int64_t total_vsize,
1136 assert(std::all_of(txns.cbegin(), txns.cend(), [
this](
const auto& tx)
1139 assert(txns.size() == workspaces.size());
1141 auto result = m_pool.CheckPackageLimits(txns, total_vsize);
1148 if (!m_subpackage.m_rbf)
return true;
1159 for (
const auto& ws : workspaces) {
1160 if (!ws.m_ancestors.empty()) {
1167 for (Workspace& ws : workspaces) {
1169 direct_conflict_iters.merge(ws.m_iters_conflicting);
1172 const auto& parent_ws = workspaces[0];
1173 const auto& child_ws = workspaces[1];
1181 "package RBF failed: too many potential replacements", *err_string);
1186 m_subpackage.m_changeset->StageRemoval(it);
1187 m_subpackage.m_conflicting_fees += it->GetModifiedFee();
1188 m_subpackage.m_conflicting_size += it->GetTxSize();
1192 const Txid& child_hash = child_ws.m_ptx->GetHash();
1193 if (
const auto err_string{
PaysForRBF(m_subpackage.m_conflicting_fees,
1194 m_subpackage.m_total_modified_fees,
1195 m_subpackage.m_total_vsize,
1196 m_pool.m_opts.incremental_relay_feerate, child_hash)}) {
1198 "package RBF failed: insufficient anti-DoS fees", *err_string);
1203 const CFeeRate parent_feerate(parent_ws.m_modified_fees, parent_ws.m_vsize);
1204 const CFeeRate package_feerate(m_subpackage.m_total_modified_fees, m_subpackage.m_total_vsize);
1205 if (package_feerate <= parent_feerate) {
1207 "package RBF failed: package feerate is less than or equal to parent feerate",
1208 strprintf(
"package feerate %s <= parent feerate is %s", package_feerate.ToString(), parent_feerate.ToString()));
1215 "package RBF failed: " + err_tup.value().second,
"");
1218 LogDebug(
BCLog::TXPACKAGES,
"package RBF checks passed: parent %s (wtxid=%s), child %s (wtxid=%s), package hash (%s)\n",
1219 txns.front()->GetHash().ToString(), txns.front()->GetWitnessHash().ToString(),
1220 txns.back()->GetHash().ToString(), txns.back()->GetWitnessHash().ToString(),
1227 bool MemPoolAccept::PolicyScriptChecks(
const ATMPArgs&
args, Workspace& ws)
1238 if (!
CheckInputScripts(tx, state, m_view, scriptVerifyFlags,
true,
false, ws.m_precomputed_txdata, GetValidationCache())) {
1255 bool MemPoolAccept::ConsensusScriptChecks(
const ATMPArgs&
args, Workspace& ws)
1260 const uint256& hash = ws.m_hash;
1278 unsigned int currentBlockScriptVerifyFlags{
GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)};
1280 ws.m_precomputed_txdata, m_active_chainstate.CoinsTip(), GetValidationCache())) {
1281 LogPrintf(
"BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s\n", hash.
ToString(), state.
ToString());
1288 void MemPoolAccept::FinalizeSubpackage(
const ATMPArgs&
args)
1293 if (!m_subpackage.m_changeset->GetRemovals().empty())
Assume(
args.m_allow_replacement);
1297 std::string log_string =
strprintf(
"replacing mempool tx %s (wtxid=%s, fees=%s, vsize=%s). ",
1298 it->GetTx().GetHash().ToString(),
1299 it->GetTx().GetWitnessHash().ToString(),
1302 FeeFrac feerate{m_subpackage.m_total_modified_fees, int32_t(m_subpackage.m_total_vsize)};
1304 const bool replaced_with_tx{m_subpackage.m_changeset->GetTxCount() == 1};
1305 if (replaced_with_tx) {
1306 const CTransaction& tx = m_subpackage.m_changeset->GetAddedTxn(0);
1307 tx_or_package_hash = tx.
GetHash();
1308 log_string +=
strprintf(
"New tx %s (wtxid=%s, fees=%s, vsize=%s)",
1314 tx_or_package_hash =
GetPackageHash(m_subpackage.m_changeset->GetAddedTxns());
1315 log_string +=
strprintf(
"New package %s with %lu txs, fees=%s, vsize=%s",
1316 tx_or_package_hash.ToString(),
1317 m_subpackage.m_changeset->GetTxCount(),
1324 it->GetTx().GetHash().data(),
1327 std::chrono::duration_cast<std::chrono::duration<std::uint64_t>>(it->GetTime()).
count(),
1328 tx_or_package_hash.data(),
1333 m_subpackage.m_replaced_transactions.push_back(it->GetSharedTx());
1335 m_subpackage.m_changeset->Apply();
1336 m_subpackage.m_changeset.reset();
1339 bool MemPoolAccept::SubmitPackage(
const ATMPArgs&
args, std::vector<Workspace>& workspaces,
1341 std::map<Wtxid, MempoolAcceptResult>& results)
1347 assert(std::all_of(workspaces.cbegin(), workspaces.cend(), [
this](
const auto& ws){
1348 return !m_pool.exists(
GenTxid::Txid(ws.m_ptx->GetHash())); }));
1350 bool all_submitted =
true;
1351 FinalizeSubpackage(
args);
1356 for (Workspace& ws : workspaces) {
1357 if (!ConsensusScriptChecks(
args, ws)) {
1361 all_submitted =
false;
1363 strprintf(
"BUG! PolicyScriptChecks succeeded but ConsensusScriptChecks failed: %s",
1364 ws.m_ptx->GetHash().ToString()));
1366 if (!m_subpackage.m_changeset) m_subpackage.m_changeset = m_pool.GetChangeSet();
1367 m_subpackage.m_changeset->StageRemoval(m_pool.GetIter(ws.m_ptx->GetHash()).value());
1370 if (!all_submitted) {
1371 Assume(m_subpackage.m_changeset);
1375 m_subpackage.m_changeset->Apply();
1376 m_subpackage.m_changeset.reset();
1380 std::vector<Wtxid> all_package_wtxids;
1381 all_package_wtxids.reserve(workspaces.size());
1382 std::transform(workspaces.cbegin(), workspaces.cend(), std::back_inserter(all_package_wtxids),
1383 [](
const auto& ws) {
return ws.m_ptx->GetWitnessHash(); });
1385 if (!m_subpackage.m_replaced_transactions.empty()) {
1386 LogDebug(
BCLog::MEMPOOL,
"replaced %u mempool transactions with %u new one(s) for %s additional fees, %d delta bytes\n",
1387 m_subpackage.m_replaced_transactions.size(), workspaces.size(),
1388 m_subpackage.m_total_modified_fees - m_subpackage.m_conflicting_fees,
1389 m_subpackage.m_total_vsize -
static_cast<int>(m_subpackage.m_conflicting_size));
1393 for (Workspace& ws : workspaces) {
1394 auto iter = m_pool.GetIter(ws.m_ptx->GetHash());
1395 Assume(iter.has_value());
1396 const auto effective_feerate =
args.m_package_feerates ? ws.m_package_feerate :
1397 CFeeRate{ws.m_modified_fees,
static_cast<uint32_t
>(ws.m_vsize)};
1398 const auto effective_feerate_wtxids =
args.m_package_feerates ? all_package_wtxids :
1399 std::vector<Wtxid>{ws.m_ptx->GetWitnessHash()};
1400 results.emplace(ws.m_ptx->GetWitnessHash(),
1402 ws.m_base_fees, effective_feerate, effective_feerate_wtxids));
1403 if (!m_pool.m_opts.signals)
continue;
1406 ws.m_vsize, (*iter)->GetHeight(),
1407 args.m_bypass_limits,
args.m_package_submission,
1409 m_pool.HasNoInputsOf(tx));
1410 m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
1412 return all_submitted;
1421 const std::vector<Wtxid> single_wtxid{ws.m_ptx->GetWitnessHash()};
1423 if (!PreChecks(
args, ws)) {
1431 m_subpackage.m_total_vsize = ws.m_vsize;
1432 m_subpackage.m_total_modified_fees = ws.m_modified_fees;
1435 if (
args.m_client_maxfeerate &&
CFeeRate(ws.m_modified_fees, ws.m_vsize) >
args.m_client_maxfeerate.value()) {
1440 if (m_pool.m_opts.require_standard) {
1442 if (!
CheckEphemeralSpends({ptx}, m_pool.m_opts.dust_relay_feerate, m_pool, ws.m_state, dummy_wtxid)) {
1447 if (m_subpackage.m_rbf && !ReplacementChecks(ws)) {
1461 const CFeeRate effective_feerate{ws.m_modified_fees,
static_cast<uint32_t
>(ws.m_vsize)};
1463 if (
args.m_test_accept) {
1465 ws.m_base_fees, effective_feerate, single_wtxid);
1468 FinalizeSubpackage(
args);
1471 if (!
args.m_package_submission && !
args.m_bypass_limits) {
1480 if (m_pool.m_opts.signals) {
1482 auto iter = m_pool.GetIter(tx.
GetHash());
1483 Assume(iter.has_value());
1485 ws.m_vsize, (*iter)->GetHeight(),
1486 args.m_bypass_limits,
args.m_package_submission,
1488 m_pool.HasNoInputsOf(tx));
1489 m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
1492 if (!m_subpackage.m_replaced_transactions.empty()) {
1493 LogDebug(
BCLog::MEMPOOL,
"replaced %u mempool transactions with 1 new transaction for %s additional fees, %d delta bytes\n",
1494 m_subpackage.m_replaced_transactions.size(),
1495 ws.m_modified_fees - m_subpackage.m_conflicting_fees,
1496 ws.m_vsize -
static_cast<int>(m_subpackage.m_conflicting_size));
1500 effective_feerate, single_wtxid);
1511 std::vector<Workspace> workspaces{};
1512 workspaces.reserve(txns.size());
1513 std::transform(txns.cbegin(), txns.cend(), std::back_inserter(workspaces),
1514 [](
const auto& tx) {
return Workspace(tx); });
1515 std::map<Wtxid, MempoolAcceptResult> results;
1520 for (Workspace& ws : workspaces) {
1521 if (!PreChecks(
args, ws)) {
1530 if (
args.m_client_maxfeerate &&
CFeeRate(ws.m_modified_fees, ws.m_vsize) >
args.m_client_maxfeerate.value()) {
1548 m_viewmempool.PackageAddTransaction(ws.m_ptx);
1553 for (Workspace& ws : workspaces) {
1569 m_subpackage.m_total_vsize = std::accumulate(workspaces.cbegin(), workspaces.cend(), int64_t{0},
1570 [](int64_t
sum,
auto& ws) {
return sum + ws.m_vsize; });
1571 m_subpackage.m_total_modified_fees = std::accumulate(workspaces.cbegin(), workspaces.cend(),
CAmount{0},
1572 [](
CAmount sum,
auto& ws) {
return sum + ws.m_modified_fees; });
1573 const CFeeRate package_feerate(m_subpackage.m_total_modified_fees, m_subpackage.m_total_vsize);
1574 std::vector<Wtxid> all_package_wtxids;
1575 all_package_wtxids.reserve(workspaces.size());
1576 std::transform(workspaces.cbegin(), workspaces.cend(), std::back_inserter(all_package_wtxids),
1577 [](
const auto& ws) {
return ws.m_ptx->GetWitnessHash(); });
1579 if (
args.m_package_feerates &&
1580 !
CheckFeeRate(m_subpackage.m_total_vsize, m_subpackage.m_total_modified_fees, placeholder_state)) {
1588 if (txns.size() > 1 && !PackageMempoolChecks(txns, workspaces, m_subpackage.m_total_vsize, package_state)) {
1593 if (m_pool.m_opts.require_standard) {
1596 if (!
CheckEphemeralSpends(txns, m_pool.m_opts.dust_relay_feerate, m_pool, child_state, child_wtxid)) {
1603 for (Workspace& ws : workspaces) {
1604 ws.m_package_feerate = package_feerate;
1605 if (!PolicyScriptChecks(
args, ws)) {
1611 if (
args.m_test_accept) {
1612 const auto effective_feerate =
args.m_package_feerates ? ws.m_package_feerate :
1613 CFeeRate{ws.m_modified_fees,
static_cast<uint32_t
>(ws.m_vsize)};
1614 const auto effective_feerate_wtxids =
args.m_package_feerates ? all_package_wtxids :
1615 std::vector<Wtxid>{ws.m_ptx->GetWitnessHash()};
1616 results.emplace(ws.m_ptx->GetWitnessHash(),
1618 ws.m_vsize, ws.m_base_fees, effective_feerate,
1619 effective_feerate_wtxids));
1625 if (!SubmitPackage(
args, workspaces, package_state, results)) {
1633 void MemPoolAccept::CleanupTemporaryCoins()
1653 for (
const auto& outpoint : m_viewmempool.GetNonBaseCoins()) {
1656 m_view.Uncache(outpoint);
1659 m_viewmempool.Reset();
1667 if (subpackage.size() > 1) {
1668 return AcceptMultipleTransactions(subpackage,
args);
1670 const auto& tx = subpackage.front();
1671 ATMPArgs single_args = ATMPArgs::SingleInPackageAccept(
args);
1672 const auto single_res = AcceptSingleTransaction(tx, single_args);
1683 ClearSubPackageState();
1690 Assert(!package.empty());
1706 if (package.size() > 1) {
1715 assert(package.size() > 1);
1718 const auto& child = package.back();
1719 std::unordered_set<uint256, SaltedTxidHasher> unconfirmed_parent_txids;
1720 std::transform(package.cbegin(), package.cend() - 1,
1721 std::inserter(unconfirmed_parent_txids, unconfirmed_parent_txids.end()),
1722 [](
const auto& tx) {
return tx->
GetHash(); });
1729 const CCoinsViewCache& coins_tip_cache = m_active_chainstate.CoinsTip();
1730 for (
const auto& input : child->vin) {
1731 if (!coins_tip_cache.HaveCoinInCache(input.prevout)) {
1732 args.m_coins_to_uncache.push_back(input.prevout);
1738 m_view.SetBackend(m_active_chainstate.CoinsTip());
1739 const auto package_or_confirmed = [
this, &unconfirmed_parent_txids](
const auto& input) {
1740 return unconfirmed_parent_txids.count(input.prevout.hash) > 0 || m_view.HaveCoin(input.prevout);
1742 if (!std::all_of(child->vin.cbegin(), child->vin.cend(), package_or_confirmed)) {
1748 m_view.SetBackend(m_dummy);
1754 std::map<Wtxid, MempoolAcceptResult> results_final;
1758 std::map<Wtxid, MempoolAcceptResult> individual_results_nonfinal;
1760 bool quit_early{
false};
1761 std::vector<CTransactionRef> txns_package_eval;
1762 for (
const auto& tx : package) {
1764 const auto& txid = tx->
GetHash();
1778 const auto& entry{*
Assert(m_pool.GetEntry(txid))};
1788 const auto& entry{*
Assert(m_pool.GetEntry(txid))};
1794 const auto single_package_res = AcceptSubPackage({tx},
args);
1795 const auto& single_res = single_package_res.m_tx_results.at(wtxid);
1800 results_final.emplace(wtxid, single_res);
1801 }
else if (package.size() == 1 ||
1815 individual_results_nonfinal.emplace(wtxid, single_res);
1817 individual_results_nonfinal.emplace(wtxid, single_res);
1818 txns_package_eval.push_back(tx);
1823 auto multi_submission_result = quit_early || txns_package_eval.empty() ?
PackageMempoolAcceptResult(package_state_quit_early, {}) :
1824 AcceptSubPackage(txns_package_eval,
args);
1830 ClearSubPackageState();
1836 for (
const auto& tx : package) {
1838 if (multi_submission_result.m_tx_results.count(wtxid) > 0) {
1840 Assume(results_final.count(wtxid) == 0);
1843 const auto& txresult = multi_submission_result.m_tx_results.at(wtxid);
1850 results_final.emplace(wtxid, txresult);
1852 }
else if (
const auto it{results_final.find(wtxid)}; it != results_final.end()) {
1856 Assume(individual_results_nonfinal.count(wtxid) == 0);
1863 results_final.erase(wtxid);
1866 }
else if (
const auto it{individual_results_nonfinal.find(wtxid)}; it != individual_results_nonfinal.end()) {
1869 results_final.emplace(wtxid, it->second);
1872 Assume(results_final.size() == package.size());
1879 int64_t accept_time,
bool bypass_limits,
bool test_accept)
1886 std::vector<COutPoint> coins_to_uncache;
1887 auto args = MemPoolAccept::ATMPArgs::SingleAccept(chainparams, accept_time, bypass_limits, coins_to_uncache, test_accept);
1895 for (
const COutPoint& hashTx : coins_to_uncache)
1898 tx->GetHash().data(),
1899 result.m_state.GetRejectReason().c_str()
1909 const Package& package,
bool test_accept,
const std::optional<CFeeRate>& client_maxfeerate)
1912 assert(!package.empty());
1913 assert(std::all_of(package.cbegin(), package.cend(), [](
const auto& tx){
return tx !=
nullptr;}));
1915 std::vector<COutPoint> coins_to_uncache;
1920 auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(chainparams,
GetTime(), coins_to_uncache);
1921 return MemPoolAccept(pool, active_chainstate).AcceptMultipleTransactions(package,
args);
1923 auto args = MemPoolAccept::ATMPArgs::PackageChildWithParents(chainparams,
GetTime(), coins_to_uncache, client_maxfeerate);
1924 return MemPoolAccept(pool, active_chainstate).AcceptPackage(package,
args);
1929 if (test_accept ||
result.m_state.IsInvalid()) {
1930 for (
const COutPoint& hashTx : coins_to_uncache) {
1949 nSubsidy >>= halvings;
1954 : m_dbview{std::move(db_params), std::move(options)},
1955 m_catcherview(&m_dbview) {}
1957 void CoinsViews::InitCache()
1960 m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview);
1967 std::optional<uint256> from_snapshot_blockhash)
1968 : m_mempool(mempool),
1969 m_blockman(blockman),
1970 m_chainman(chainman),
1971 m_from_snapshot_blockhash(from_snapshot_blockhash) {}
1977 return m_cached_snapshot_base;
1980 void Chainstate::InitCoinsDB(
1981 size_t cache_size_bytes,
1993 .cache_bytes = cache_size_bytes,
1994 .memory_only = in_memory,
1995 .wipe_data = should_wipe,
2003 void Chainstate::InitCoinsCache(
size_t cache_size_bytes)
2029 if (chain.Tip() ==
nullptr) {
2038 LogPrintf(
"Leaving InitialBlockDownload (latching to false)\n");
2055 LogPrintf(
"%s: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n", __func__);
2058 _(
"Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."));
2071 SetBlockFailureFlags(pindexNew);
2076 LogPrintf(
"%s: invalid block=%s height=%d log2_work=%f date=%s\n", __func__,
2081 LogPrintf(
"%s: current best=%s height=%d log2_work=%f date=%s\n", __func__,
2120 if (
VerifyScript(scriptSig,
m_tx_out.
scriptPubKey, witness,
nFlags,
CachingTransactionSignatureChecker(
ptxTo,
nIn,
m_tx_out.
nValue,
cacheStore, *
m_signature_cache, *
txdata), &error)) {
2121 return std::nullopt;
2124 return std::make_pair(error, std::move(debug_str));
2129 : m_signature_cache{signature_cache_bytes}
2136 m_script_execution_cache_hasher.Write(
nonce.begin(), 32);
2137 m_script_execution_cache_hasher.Write(
nonce.begin(), 32);
2139 const auto [num_elems, approx_size_bytes] = m_script_execution_cache.setup_bytes(script_execution_cache_bytes);
2140 LogPrintf(
"Using %zu MiB out of %zu MiB requested for script execution cache, able to store %zu elements\n",
2141 approx_size_bytes >> 20, script_execution_cache_bytes >> 20, num_elems);
2167 std::vector<CScriptCheck>* pvChecks)
2172 pvChecks->reserve(tx.
vin.size());
2189 std::vector<CTxOut> spent_outputs;
2190 spent_outputs.reserve(tx.
vin.size());
2192 for (
const auto& txin : tx.
vin) {
2196 spent_outputs.emplace_back(coin.
out);
2198 txdata.
Init(tx, std::move(spent_outputs));
2202 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
2213 pvChecks->emplace_back(std::move(check));
2214 }
else if (
auto result = check();
result.has_value()) {
2226 auto mandatory_result = check2();
2227 if (!mandatory_result.has_value()) {
2236 result = mandatory_result;
2246 if (cacheFullScriptStore && !pvChecks) {
2274 if (undo.nHeight == 0) {
2280 undo.nHeight = alternate.
nHeight;
2305 LogError(
"DisconnectBlock(): failure reading undo data\n");
2309 if (blockUndo.
vtxundo.size() + 1 != block.
vtx.size()) {
2310 LogError(
"DisconnectBlock(): block and undo data inconsistent\n");
2320 bool fEnforceBIP30 = !((pindex->
nHeight==91722 && pindex->
GetBlockHash() ==
uint256{
"00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e"}) ||
2321 (pindex->
nHeight==91812 && pindex->
GetBlockHash() ==
uint256{
"00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f"}));
2324 for (
int i = block.
vtx.size() - 1; i >= 0; i--) {
2328 bool is_bip30_exception = (is_coinbase && !fEnforceBIP30);
2332 for (
size_t o = 0; o < tx.
vout.size(); o++) {
2333 if (!tx.
vout[o].scriptPubKey.IsUnspendable()) {
2338 if (!is_bip30_exception) {
2349 LogError(
"DisconnectBlock(): transaction and undo data inconsistent\n");
2352 for (
unsigned int j = tx.
vin.size(); j > 0;) {
2450 const auto time_start{SteadyClock::now()};
2466 if (!
CheckBlock(block, state, params.GetConsensus(), !fJustCheck, !fJustCheck)) {
2478 uint256 hashPrevBlock = pindex->
pprev ==
nullptr ?
uint256() : pindex->pprev->GetBlockHash();
2485 if (block_hash == params.GetConsensus().hashGenesisBlock) {
2491 bool fScriptChecks =
true;
2500 if (it->second.GetAncestor(pindex->
nHeight) == pindex &&
2522 const auto time_1{SteadyClock::now()};
2523 m_chainman.time_check += time_1 - time_start;
2525 Ticks<MillisecondsDouble>(time_1 - time_start),
2567 static constexpr
int BIP34_IMPLIES_BIP30_LIMIT = 1983702;
2599 fEnforceBIP30 = fEnforceBIP30 && (!pindexBIP34height || !(pindexBIP34height->
GetBlockHash() == params.GetConsensus().BIP34Hash));
2604 if (fEnforceBIP30 || pindex->
nHeight >= BIP34_IMPLIES_BIP30_LIMIT) {
2605 for (
const auto& tx : block.
vtx) {
2606 for (
size_t o = 0; o < tx->
vout.size(); o++) {
2609 "tried to overwrite transaction");
2616 int nLockTimeFlags = 0;
2624 const auto time_2{SteadyClock::now()};
2627 Ticks<MillisecondsDouble>(time_2 - time_1),
2639 std::vector<PrecomputedTransactionData> txsdata(block.
vtx.size());
2641 std::vector<int> prevheights;
2644 int64_t nSigOpsCost = 0;
2645 blockundo.
vtxundo.reserve(block.
vtx.size() - 1);
2646 for (
unsigned int i = 0; i < block.
vtx.size(); i++)
2651 nInputs += tx.
vin.size();
2667 "accumulated fee in the block out of range");
2674 prevheights.resize(tx.
vin.size());
2675 for (
size_t j = 0; j < tx.
vin.size(); j++) {
2679 if (!
SequenceLocks(tx, nLockTimeFlags, prevheights, *pindex)) {
2698 std::vector<CScriptCheck> vChecks;
2699 bool fCacheResults = fJustCheck;
2707 control.Add(std::move(vChecks));
2712 blockundo.
vtxundo.emplace_back();
2716 const auto time_3{SteadyClock::now()};
2718 LogDebug(
BCLog::BENCH,
" - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs (%.2fms/blk)]\n", (
unsigned)block.
vtx.size(),
2719 Ticks<MillisecondsDouble>(time_3 - time_2), Ticks<MillisecondsDouble>(time_3 - time_2) / block.
vtx.size(),
2720 nInputs <= 1 ? 0 : Ticks<MillisecondsDouble>(time_3 - time_2) / (nInputs - 1),
2721 Ticks<SecondsDouble>(
m_chainman.time_connect),
2725 if (block.
vtx[0]->GetValueOut() > blockReward && state.
IsValid()) {
2727 strprintf(
"coinbase pays too much (actual=%d vs limit=%d)", block.
vtx[0]->GetValueOut(), blockReward));
2730 auto parallel_result = control.Complete();
2731 if (parallel_result.has_value() && state.
IsValid()) {
2738 const auto time_4{SteadyClock::now()};
2740 LogDebug(
BCLog::BENCH,
" - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs (%.2fms/blk)]\n", nInputs - 1,
2741 Ticks<MillisecondsDouble>(time_4 - time_2),
2742 nInputs <= 1 ? 0 : Ticks<MillisecondsDouble>(time_4 - time_2) / (nInputs - 1),
2743 Ticks<SecondsDouble>(
m_chainman.time_verify),
2750 if (!
m_blockman.WriteBlockUndo(blockundo, state, *pindex)) {
2754 const auto time_5{SteadyClock::now()};
2757 Ticks<MillisecondsDouble>(time_5 - time_4),
2769 const auto time_6{SteadyClock::now()};
2772 Ticks<MillisecondsDouble>(time_6 - time_5),
2782 Ticks<std::chrono::nanoseconds>(time_5 - time_start)
2791 return this->GetCoinsCacheSizeState(
2797 size_t max_coins_cache_size_bytes,
2798 size_t max_mempool_size_bytes)
2803 int64_t nTotalSpace =
2804 max_coins_cache_size_bytes + std::max<int64_t>(int64_t(max_mempool_size_bytes) - nMempoolUsage, 0);
2807 static constexpr int64_t MAX_BLOCK_COINSDB_USAGE_BYTES = 10 * 1024 * 1024;
2808 int64_t large_threshold =
2809 std::max((9 * nTotalSpace) / 10, nTotalSpace - MAX_BLOCK_COINSDB_USAGE_BYTES);
2811 if (cacheSize > nTotalSpace) {
2812 LogPrintf(
"Cache size (%s) exceeds total space (%s)\n", cacheSize, nTotalSpace);
2814 }
else if (cacheSize > large_threshold) {
2820 bool Chainstate::FlushStateToDisk(
2823 int nManualPruneHeight)
2826 assert(this->CanFlushToDisk());
2827 std::set<int> setFilesToPrune;
2828 bool full_flush_completed =
false;
2835 bool fFlushForPrune =
false;
2836 bool fDoFullFlush =
false;
2844 std::optional<std::string> limiting_lock;
2846 for (
const auto& prune_lock :
m_blockman.m_prune_locks) {
2847 if (prune_lock.second.height_first == std::numeric_limits<int>::max())
continue;
2850 last_prune = std::max(1, std::min(last_prune, lock_height));
2851 if (last_prune == lock_height) {
2852 limiting_lock = prune_lock.first;
2856 if (limiting_lock) {
2857 LogDebug(
BCLog::PRUNE,
"%s limited pruning to height %d\n", limiting_lock.value(), last_prune);
2860 if (nManualPruneHeight > 0) {
2865 std::min(last_prune, nManualPruneHeight),
2873 if (!setFilesToPrune.empty()) {
2874 fFlushForPrune =
true;
2876 m_blockman.m_block_tree_db->WriteFlag(
"prunedblockfiles",
true);
2881 const auto nNow{SteadyClock::now()};
2898 fDoFullFlush = (mode ==
FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune;
2900 if (fDoFullFlush || fPeriodicWrite) {
2925 if (fFlushForPrune) {
2933 if (fDoFullFlush && !
CoinsTip().GetBestBlock().IsNull()) {
2934 if (coins_mem_usage >=
WARN_FLUSH_COINS_SIZE)
LogWarning(
"Flushing large (%d GiB) UTXO set to disk, it may take several minutes", coins_mem_usage >> 30);
2952 full_flush_completed =
true;
2954 int64_t{Ticks<std::chrono::microseconds>(SteadyClock::now() - nNow)},
2956 (uint64_t)coins_count,
2957 (uint64_t)coins_mem_usage,
2958 (
bool)fFlushForPrune);
2965 }
catch (
const std::runtime_error& e) {
2992 const std::string& func_name,
2993 const std::string&
prefix,
3005 chainman.GuessVerificationProgress(tip),
3006 coins_tip.DynamicMemoryUsage() * (1.0 / (1 << 20)),
3007 coins_tip.GetCacheSize(),
3008 !warning_messages.empty() ?
strprintf(
" warning='%s'", warning_messages) :
"");
3011 void Chainstate::UpdateTip(
const CBlockIndex* pindexNew)
3014 const auto& coins_tip = this->
CoinsTip();
3020 constexpr
int BACKGROUND_LOG_INTERVAL = 2000;
3021 if (pindexNew->
nHeight % BACKGROUND_LOG_INTERVAL == 0) {
3032 std::vector<bilingual_str> warning_messages;
3043 warning_messages.push_back(warning);
3071 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3074 LogError(
"DisconnectTip(): Failed to read block\n");
3078 const auto time_start{SteadyClock::now()};
3082 if (DisconnectBlock(block, pindexDelete, view) !=
DISCONNECT_OK) {
3086 bool flushed = view.
Flush();
3090 Ticks<MillisecondsDouble>(SteadyClock::now() - time_start));
3094 const int max_height_first{pindexDelete->
nHeight - 1};
3095 for (
auto& prune_lock :
m_blockman.m_prune_locks) {
3096 if (prune_lock.second.height_first <= max_height_first)
continue;
3098 prune_lock.second.height_first = max_height_first;
3099 LogDebug(
BCLog::PRUNE,
"%s prune lock moved back to %d\n", prune_lock.first, max_height_first);
3118 UpdateTip(pindexDelete->
pprev);
3180 const auto time_1{SteadyClock::now()};
3181 std::shared_ptr<const CBlock> pthisBlock;
3183 std::shared_ptr<CBlock> pblockNew = std::make_shared<CBlock>();
3187 pthisBlock = pblockNew;
3190 pthisBlock = pblock;
3192 const CBlock& blockConnecting = *pthisBlock;
3194 const auto time_2{SteadyClock::now()};
3195 SteadyClock::time_point time_3;
3199 Ticks<MillisecondsDouble>(time_2 - time_1));
3202 bool rv =
ConnectBlock(blockConnecting, state, pindexNew, view);
3212 time_3 = SteadyClock::now();
3213 m_chainman.time_connect_total += time_3 - time_2;
3216 Ticks<MillisecondsDouble>(time_3 - time_2),
3217 Ticks<SecondsDouble>(
m_chainman.time_connect_total),
3219 bool flushed = view.
Flush();
3222 const auto time_4{SteadyClock::now()};
3225 Ticks<MillisecondsDouble>(time_4 - time_3),
3232 const auto time_5{SteadyClock::now()};
3233 m_chainman.time_chainstate += time_5 - time_4;
3235 Ticks<MillisecondsDouble>(time_5 - time_4),
3236 Ticks<SecondsDouble>(
m_chainman.time_chainstate),
3245 UpdateTip(pindexNew);
3247 const auto time_6{SteadyClock::now()};
3248 m_chainman.time_post_connect += time_6 - time_5;
3251 Ticks<MillisecondsDouble>(time_6 - time_5),
3252 Ticks<SecondsDouble>(
m_chainman.time_post_connect),
3255 Ticks<MillisecondsDouble>(time_6 - time_1),
3264 m_chainman.MaybeCompleteSnapshotValidation();
3292 bool fInvalidAncestor =
false;
3302 if (fFailedChain || fMissingData) {
3309 while (pindexTest != pindexFailed) {
3313 }
else if (fMissingData) {
3318 std::make_pair(pindexFailed->
pprev, pindexFailed));
3321 pindexFailed = pindexFailed->
pprev;
3324 fInvalidAncestor =
true;
3327 pindexTest = pindexTest->
pprev;
3329 if (!fInvalidAncestor)
3361 bool fBlocksDisconnected =
false;
3375 fBlocksDisconnected =
true;
3379 std::vector<CBlockIndex*> vpindexToConnect;
3380 bool fContinue =
true;
3385 int nTargetHeight = std::min(
nHeight + 32, pindexMostWork->
nHeight);
3386 vpindexToConnect.clear();
3387 vpindexToConnect.reserve(nTargetHeight -
nHeight);
3390 vpindexToConnect.push_back(pindexIter);
3391 pindexIter = pindexIter->
pprev;
3396 for (
CBlockIndex* pindexConnect : vpindexToConnect | std::views::reverse) {
3397 if (!
ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool)) {
3404 fInvalidFound =
true;
3425 if (fBlocksDisconnected) {
3446 bool fNotify =
false;
3447 bool fInitialBlockDownload =
false;
3451 pindexHeader = m_best_header;
3453 if (pindexHeader != m_last_notified_header) {
3456 m_last_notified_header = pindexHeader;
3469 if (signals.CallbacksPending() > 10) {
3470 signals.SyncWithValidationInterfaceQueue();
3474 bool Chainstate::ActivateBestChain(
BlockValidationState& state, std::shared_ptr<const CBlock> pblock)
3493 LogPrintf(
"m_disabled is set - this chainstate should not be in operation. " 3494 "Please report this as a bug. %s\n", CLIENT_BUGREPORT);
3500 bool exited_ibd{
false};
3514 LOCK(MempoolMutex());
3517 bool blocks_connected =
false;
3523 if (pindexMostWork ==
nullptr) {
3528 if (pindexMostWork ==
nullptr || pindexMostWork ==
m_chain.
Tip()) {
3532 bool fInvalidFound =
false;
3533 std::shared_ptr<const CBlock> nullBlockPtr;
3538 if (!
ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->
GetBlockHash() ? pblock : nullBlockPtr, fInvalidFound, connectTrace)) {
3542 blocks_connected =
true;
3544 if (fInvalidFound) {
3546 pindexMostWork =
nullptr;
3551 assert(trace.pblock && trace.pindex);
3566 if (!blocks_connected)
return true;
3571 if (was_in_ibd && !still_in_ibd) {
3627 }
while (pindexNewTip != pindexMostWork);
3667 return ActivateBestChain(state, std::shared_ptr<const CBlock>());
3677 if (pindex->
nHeight == 0)
return false;
3680 bool pindex_was_in_chain =
false;
3681 int disconnected = 0;
3695 std::multimap<const arith_uint256, CBlockIndex *> candidate_blocks_by_work;
3699 for (
auto& entry :
m_blockman.m_block_index) {
3710 candidate_blocks_by_work.insert(std::make_pair(candidate->
nChainWork, candidate));
3725 LOCK(MempoolMutex());
3727 pindex_was_in_chain =
true;
3740 if (!
ret)
return false;
3760 auto candidate_it = candidate_blocks_by_work.lower_bound(invalid_walk_tip->
pprev->
nChainWork);
3761 while (candidate_it != candidate_blocks_by_work.end()) {
3764 candidate_it = candidate_blocks_by_work.erase(candidate_it);
3772 to_mark_failed = invalid_walk_tip;
3797 for (
auto& [
_, block_index] :
m_blockman.m_block_index) {
3807 if (pindex_was_in_chain) {
3826 void Chainstate::SetBlockFailureFlags(
CBlockIndex* invalid_block)
3830 for (
auto& [
_, block_index] :
m_blockman.m_block_index) {
3831 if (block_index.GetAncestor(invalid_block->
nHeight) == invalid_block && !(block_index.nStatus &
BLOCK_FAILED_MASK)) {
3843 for (
auto& [
_, block_index] :
m_blockman.m_block_index) {
3844 if (!block_index.IsValid() && block_index.GetAncestor(
nHeight) == pindex) {
3850 if (&block_index ==
m_chainman.m_best_invalid) {
3859 while (pindex !=
nullptr) {
3865 pindex = pindex->
pprev;
3879 if (is_active_chainstate) {
3883 }
else if (!m_disabled) {
3888 if (snapshot_base->GetAncestor(pindex->
nHeight) == pindex) {
3898 pindexNew->
nTx = block.
vtx.size();
3904 auto prev_tx_sum = [](
CBlockIndex& block) {
return block.nTx + (block.pprev ? block.pprev->m_chain_tx_count : 0); };
3906 pindexNew == GetSnapshotBaseBlock())) {
3907 LogWarning(
"Internal bug detected: block %d has unexpected m_chain_tx_count %i that should be %i (%s %s). Please report this issue here: %s\n",
3911 pindexNew->nFile = pos.
nFile;
3912 pindexNew->nDataPos = pos.
nPos;
3913 pindexNew->nUndoPos = 0;
3923 std::deque<CBlockIndex*> queue;
3924 queue.push_back(pindexNew);
3927 while (!queue.empty()) {
3935 LogWarning(
"Internal bug detected: block %d has unexpected m_chain_tx_count %i that should be %i (%s %s). Please report this issue here: %s\n",
3941 c->TryAddBlockIndexCandidate(pindex);
3943 std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range =
m_blockman.
m_blocks_unlinked.equal_range(pindex);
3944 while (range.first != range.second) {
3945 std::multimap<CBlockIndex*, CBlockIndex*>::iterator it = range.first;
3946 queue.push_back(it->second);
3977 "hashMerkleRoot mismatch");
3986 "bad-txns-duplicate",
3987 "duplicate transaction");
4002 if (expect_witness_commitment) {
4007 assert(!block.
vtx.empty() && !block.
vtx[0]->vin.empty());
4008 const auto& witness_stack{block.
vtx[0]->vin[0].scriptWitness.stack};
4010 if (witness_stack.size() != 1 || witness_stack[0].size() != 32) {
4013 "bad-witness-nonce-size",
4014 strprintf(
"%s : invalid witness reserved value size", __func__));
4023 if (memcmp(hash_witness.
begin(), &block.
vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
4026 "bad-witness-merkle-match",
4027 strprintf(
"%s : witness merkle commitment mismatch", __func__));
4036 for (
const auto& tx : block.
vtx) {
4040 "unexpected-witness",
4041 strprintf(
"%s : unexpected witness data found", __func__));
4081 if (block.
vtx.empty() || !block.
vtx[0]->IsCoinBase())
4083 for (
unsigned int i = 1; i < block.
vtx.size(); i++)
4084 if (block.
vtx[i]->IsCoinBase())
4089 for (
const auto& tx : block.
vtx) {
4099 unsigned int nSigOps = 0;
4100 for (
const auto& tx : block.
vtx)
4107 if (fCheckPOW && fCheckMerkleRoot)
4113 void ChainstateManager::UpdateUncommittedBlockStructures(
CBlock& block,
const CBlockIndex* pindexPrev)
const 4116 static const std::vector<unsigned char>
nonce(32, 0x00);
4119 tx.
vin[0].scriptWitness.stack.resize(1);
4120 tx.
vin[0].scriptWitness.stack[0] =
nonce;
4127 std::vector<unsigned char> commitment;
4129 std::vector<unsigned char>
ret(32, 0x00);
4137 out.scriptPubKey[1] = 0x24;
4138 out.scriptPubKey[2] = 0xaa;
4139 out.scriptPubKey[3] = 0x21;
4140 out.scriptPubKey[4] = 0xa9;
4141 out.scriptPubKey[5] = 0xed;
4143 commitment = std::vector<unsigned char>(
out.scriptPubKey.begin(),
out.scriptPubKey.end());
4145 tx.vout.push_back(
out);
4148 UpdateUncommittedBlockStructures(block, pindexPrev);
4154 return std::all_of(headers.cbegin(), headers.cend(),
4155 [&](
const auto& header) {
return CheckProofOfWork(header.GetHash(), header.nBits, consensusParams);});
4166 if (block.
vtx.empty() || !block.
vtx[0]->IsCoinBase()) {
4173 return std::any_of(block.
vtx.begin(), block.
vtx.end(),
4211 assert(pindexPrev !=
nullptr);
4220 if (chainman.m_options.checkpoints_enabled) {
4224 const CBlockIndex* pcheckpoint = blockman.GetLastCheckpoint(chainman.GetParams().Checkpoints());
4225 if (pcheckpoint && nHeight < pcheckpoint->
nHeight) {
4226 LogPrintf(
"ERROR: %s: forked chain older than last checkpoint (height %d)\n", __func__,
nHeight);
4271 const int nHeight = pindexPrev ==
nullptr ? 0 : pindexPrev->
nHeight + 1;
4274 bool enforce_locktime_median_time_past{
false};
4276 assert(pindexPrev !=
nullptr);
4277 enforce_locktime_median_time_past =
true;
4280 const int64_t nLockTimeCutoff{enforce_locktime_median_time_past ?
4285 for (
const auto& tx : block.
vtx) {
4295 if (block.
vtx[0]->vin[0].scriptSig.size() <
expect.size() ||
4296 !std::equal(
expect.begin(),
expect.end(), block.
vtx[0]->vin[0].scriptSig.begin())) {
4332 BlockMap::iterator miSelf{
m_blockman.m_block_index.find(hash)};
4334 if (miSelf !=
m_blockman.m_block_index.end()) {
4358 pindexPrev = &((*mi).second);
4393 if (pindexPrev->
GetAncestor(failedit->nHeight) == failedit) {
4396 while (invalid_walk != failedit) {
4399 invalid_walk = invalid_walk->
pprev;
4407 if (!min_pow_checked) {
4425 "Saw new header hash=%s height=%d", hash.
ToString(), pindex->
nHeight);
4459 blocks_left = std::max<int64_t>(0, blocks_left);
4460 const double progress{100.0 * last_accepted.nHeight / (last_accepted.nHeight + blocks_left)};
4461 LogInfo(
"Synchronizing blockheaders, height: %d (~%.2f%%)\n", last_accepted.nHeight, progress);
4478 auto now = std::chrono::steady_clock::now();
4479 if (now < m_last_presync_update + std::chrono::milliseconds{250})
return;
4480 m_last_presync_update = now;
4484 if (initial_download) {
4486 blocks_left = std::max<int64_t>(0, blocks_left);
4487 const double progress{100.0 * height / (height + blocks_left)};
4488 LogInfo(
"Pre-synchronizing blockheaders, height: %d (~%.2f%%)\n", height, progress);
4495 const CBlock& block = *pblock;
4497 if (fNewBlock) *fNewBlock =
false;
4501 CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
4503 bool accepted_header{
AcceptBlockHeader(block, state, &pindex, min_pow_checked)};
4506 if (!accepted_header)
4530 if (fAlreadyHave)
return true;
4532 if (pindex->
nTx != 0)
return true;
4533 if (!fHasMoreOrSameWork)
return true;
4534 if (fTooFarAhead)
return true;
4545 if (!
CheckBlock(block, state, params.GetConsensus()) ||
4562 if (fNewBlock) *fNewBlock =
true;
4570 if (blockPos.IsNull()) {
4571 state.
Error(
strprintf(
"%s: Failed to find position to write new block to disk", __func__));
4576 }
catch (
const std::runtime_error& e) {
4600 if (new_block) *new_block =
false;
4615 ret =
AcceptBlock(block, state, &pindex, force_processing,
nullptr, new_block, min_pow_checked);
4630 LogError(
"%s: ActivateBestChain failed (%s)\n", __func__, state.
ToString());
4636 if (bg_chain && !bg_chain->ActivateBestChain(bg_state, block)) {
4637 LogError(
"%s: [background] ActivateBestChain failed (%s)\n", __func__, bg_state.
ToString());
4664 bool fCheckMerkleRoot)
4671 indexDummy.pprev = pindexPrev;
4673 indexDummy.phashBlock = &block_hash;
4677 LogError(
"%s: Consensus::ContextualCheckBlockHeader: %s\n", __func__, state.
ToString());
4685 LogError(
"%s: Consensus::ContextualCheckBlock: %s\n", __func__, state.
ToString());
4688 if (!chainstate.
ConnectBlock(block, state, &indexDummy, viewNew,
true)) {
4700 if (!active_chainstate.FlushStateToDisk(
4713 if (tip && tip->GetBlockHash() == coins_cache.
GetBestBlock()) {
4726 LogPrintf(
"Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n",
4727 tip->GetBlockHash().ToString(),
4756 int nCheckLevel,
int nCheckDepth)
4765 if (nCheckDepth <= 0 || nCheckDepth > chainstate.
m_chain.
Height()) {
4768 nCheckLevel = std::max(0, std::min(4, nCheckLevel));
4769 LogPrintf(
"Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
4773 int nGoodTransactions = 0;
4776 bool skipped_no_block_data{
false};
4777 bool skipped_l3_checks{
false};
4778 LogPrintf(
"Verification progress: 0%%\n");
4783 const int percentageDone = std::max(1, std::min(99, (
int)(((
double)(chainstate.
m_chain.
Height() - pindex->
nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
4784 if (reportDone < percentageDone / 10) {
4786 LogPrintf(
"Verification progress: %d%%\n", percentageDone);
4787 reportDone = percentageDone / 10;
4796 LogPrintf(
"VerifyDB(): block verification stopping at height %d (no data). This could be due to pruning or use of an assumeutxo snapshot.\n", pindex->
nHeight);
4797 skipped_no_block_data =
true;
4807 if (nCheckLevel >= 1 && !
CheckBlock(block, state, consensus_params)) {
4808 LogPrintf(
"Verification error: found bad block at %d, hash=%s (%s)\n",
4813 if (nCheckLevel >= 2 && pindex) {
4825 if (nCheckLevel >= 3) {
4834 nGoodTransactions = 0;
4835 pindexFailure = pindex;
4837 nGoodTransactions += block.
vtx.size();
4840 skipped_l3_checks =
true;
4845 if (pindexFailure) {
4846 LogPrintf(
"Verification error: coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainstate.
m_chain.
Height() - pindexFailure->
nHeight + 1, nGoodTransactions);
4849 if (skipped_l3_checks) {
4850 LogPrintf(
"Skipped verification of level >=3 (insufficient database cache size). Consider increasing -dbcache.\n");
4857 if (nCheckLevel >= 4 && !skipped_l3_checks) {
4859 const int percentageDone = std::max(1, std::min(99, 100 - (
int)(((
double)(chainstate.
m_chain.
Height() - pindex->
nHeight)) / (double)nCheckDepth * 50)));
4860 if (reportDone < percentageDone / 10) {
4862 LogPrintf(
"Verification progress: %d%%\n", percentageDone);
4863 reportDone = percentageDone / 10;
4872 if (!chainstate.
ConnectBlock(block, state, pindex, coins)) {
4880 LogPrintf(
"Verification: No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions);
4882 if (skipped_l3_checks) {
4885 if (skipped_no_block_data) {
4903 if (!tx->IsCoinBase()) {
4904 for (
const CTxIn &txin : tx->vin) {
4922 if (hashHeads.empty())
return true;
4923 if (hashHeads.size() != 2) {
4924 LogError(
"ReplayBlocks(): unknown inconsistent state\n");
4935 if (
m_blockman.m_block_index.count(hashHeads[0]) == 0) {
4936 LogError(
"ReplayBlocks(): reorganization to unknown block requested\n");
4939 pindexNew = &(
m_blockman.m_block_index[hashHeads[0]]);
4941 if (!hashHeads[1].IsNull()) {
4942 if (
m_blockman.m_block_index.count(hashHeads[1]) == 0) {
4943 LogError(
"ReplayBlocks(): reorganization from unknown block requested\n");
4946 pindexOld = &(
m_blockman.m_block_index[hashHeads[1]]);
4948 assert(pindexFork !=
nullptr);
4952 while (pindexOld != pindexFork) {
4970 pindexOld = pindexOld->
pprev;
4974 int nForkHeight = pindexFork ? pindexFork->
nHeight : 0;
5001 block = block->pprev;
5007 void Chainstate::ClearBlockIndexCandidates()
5019 if (!
ret)
return false;
5021 m_blockman.ScanAndUnlinkAlreadyPrunedFiles();
5023 std::vector<CBlockIndex*> vSortedByHeight{
m_blockman.GetAllBlockIndices()};
5024 std::sort(vSortedByHeight.begin(), vSortedByHeight.end(),
5034 if (pindex == GetSnapshotBaseBlock() ||
5039 chainstate->TryAddBlockIndexCandidate(pindex);
5043 m_best_invalid = pindex;
5046 m_best_header = pindex;
5062 if (
m_blockman.m_block_index.count(params.GenesisBlock().GetHash()))
5066 const CBlock& block = params.GenesisBlock();
5068 if (blockPos.IsNull()) {
5069 LogError(
"%s: writing genesis block to disk failed\n", __func__);
5074 }
catch (
const std::runtime_error& e) {
5075 LogError(
"%s: failed to write genesis block: %s\n", __func__, e.what());
5085 std::multimap<uint256, FlatFilePos>* blocks_with_unknown_parent)
5088 assert(!dbp == !blocks_with_unknown_parent);
5090 const auto start{SteadyClock::now()};
5098 uint64_t nRewind = blkdat.GetPos();
5099 while (!blkdat.eof()) {
5102 blkdat.SetPos(nRewind);
5105 unsigned int nSize = 0;
5109 blkdat.FindByte(std::byte(params.MessageStart()[0]));
5110 nRewind = blkdat.GetPos() + 1;
5112 if (buf != params.MessageStart()) {
5119 }
catch (
const std::exception&) {
5126 const uint64_t nBlockPos{blkdat.GetPos()};
5128 dbp->
nPos = nBlockPos;
5129 blkdat.SetLimit(nBlockPos + nSize);
5132 const uint256 hash{header.GetHash()};
5135 nRewind = nBlockPos + nSize;
5136 blkdat.SkipTo(nRewind);
5138 std::shared_ptr<CBlock> pblock{};
5145 header.hashPrevBlock.ToString());
5146 if (dbp && blocks_with_unknown_parent) {
5147 blocks_with_unknown_parent->emplace(header.hashPrevBlock, *dbp);
5156 blkdat.SetPos(nBlockPos);
5157 pblock = std::make_shared<CBlock>();
5159 nRewind = blkdat.GetPos();
5162 if (
AcceptBlock(pblock, state,
nullptr,
true, dbp,
nullptr,
true)) {
5168 }
else if (hash != params.GetConsensus().hashGenesisBlock && pindex->
nHeight % 1000 == 0) {
5195 bool activation_failure =
false;
5196 for (
auto c :
GetAll()) {
5198 if (!c->ActivateBestChain(state, pblock)) {
5200 activation_failure =
true;
5204 if (activation_failure) {
5211 if (!blocks_with_unknown_parent)
continue;
5214 std::deque<uint256> queue;
5215 queue.push_back(hash);
5216 while (!queue.empty()) {
5219 auto range = blocks_with_unknown_parent->equal_range(head);
5220 while (range.first != range.second) {
5221 std::multimap<uint256, FlatFilePos>::iterator it = range.first;
5222 std::shared_ptr<CBlock> pblockrecursive = std::make_shared<CBlock>();
5224 LogDebug(
BCLog::REINDEX,
"%s: Processing out of order child %s of %s\n", __func__, pblockrecursive->GetHash().ToString(),
5228 if (
AcceptBlock(pblockrecursive, dummy,
nullptr,
true, &it->second,
nullptr,
true)) {
5230 queue.push_back(pblockrecursive->GetHash());
5234 blocks_with_unknown_parent->erase(it);
5238 }
catch (
const std::exception& e) {
5250 LogDebug(
BCLog::REINDEX,
"%s: unexpected data at file offset 0x%x - %s. continuing\n", __func__, (nRewind - 1), e.what());
5253 }
catch (
const std::runtime_error& e) {
5256 LogPrintf(
"Loaded %i blocks from external file in %dms\n", nLoaded, Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
5290 best_hdr_chain.
SetTip(*m_best_header);
5292 std::multimap<CBlockIndex*,CBlockIndex*> forward;
5293 for (
auto& [
_, block_index] :
m_blockman.m_block_index) {
5295 if (!best_hdr_chain.
Contains(&block_index)) {
5297 assert(block_index.pprev);
5298 forward.emplace(block_index.pprev, &block_index);
5314 CBlockIndex* pindexFirstNotTransactionsValid =
nullptr;
5316 CBlockIndex* pindexFirstNotScriptsValid =
nullptr;
5322 const CBlockIndex* snap_base{GetSnapshotBaseBlock()};
5323 CBlockIndex *snap_first_missing{}, *snap_first_notx{}, *snap_first_notv{}, *snap_first_nocv{}, *snap_first_nosv{};
5324 auto snap_update_firsts = [&] {
5325 if (pindex == snap_base) {
5326 std::swap(snap_first_missing, pindexFirstMissing);
5327 std::swap(snap_first_notx, pindexFirstNeverProcessed);
5328 std::swap(snap_first_notv, pindexFirstNotTransactionsValid);
5329 std::swap(snap_first_nocv, pindexFirstNotChainValid);
5330 std::swap(snap_first_nosv, pindexFirstNotScriptsValid);
5334 while (pindex !=
nullptr) {
5336 if (pindexFirstInvalid ==
nullptr && pindex->nStatus &
BLOCK_FAILED_VALID) pindexFirstInvalid = pindex;
5337 if (pindexFirstMissing ==
nullptr && !(pindex->nStatus &
BLOCK_HAVE_DATA)) {
5338 pindexFirstMissing = pindex;
5340 if (pindexFirstNeverProcessed ==
nullptr && pindex->
nTx == 0) pindexFirstNeverProcessed = pindex;
5341 if (pindex->pprev !=
nullptr && pindexFirstNotTreeValid ==
nullptr && (pindex->nStatus &
BLOCK_VALID_MASK) <
BLOCK_VALID_TREE) pindexFirstNotTreeValid = pindex;
5343 if (pindex->pprev !=
nullptr) {
5344 if (pindexFirstNotTransactionsValid ==
nullptr &&
5346 pindexFirstNotTransactionsValid = pindex;
5349 if (pindexFirstNotChainValid ==
nullptr &&
5351 pindexFirstNotChainValid = pindex;
5354 if (pindexFirstNotScriptsValid ==
nullptr &&
5356 pindexFirstNotScriptsValid = pindex;
5361 if (pindex->pprev ==
nullptr) {
5364 for (
auto c :
GetAll()) {
5365 if (c->m_chain.Genesis() !=
nullptr) {
5366 assert(pindex == c->m_chain.Genesis());
5370 if (!pindex->HaveNumChainTxs())
assert(pindex->nSequenceId <= 0);
5376 assert(pindexFirstMissing == pindexFirstNeverProcessed);
5382 if (snap_base && snap_base->GetAncestor(pindex->nHeight) == pindex) {
5391 assert((pindexFirstNeverProcessed ==
nullptr || pindex == snap_base) == pindex->HaveNumChainTxs());
5392 assert((pindexFirstNotTransactionsValid ==
nullptr || pindex == snap_base) == pindex->HaveNumChainTxs());
5394 assert(pindex->pprev ==
nullptr || pindex->nChainWork >= pindex->pprev->nChainWork);
5396 assert(pindexFirstNotTreeValid ==
nullptr);
5400 if (pindexFirstInvalid ==
nullptr) {
5405 if (!pindex->pprev) {
5407 assert(pindex->m_chain_tx_count == pindex->nTx);
5408 }
else if (pindex->pprev->m_chain_tx_count > 0 && pindex->nTx > 0) {
5410 assert(pindex->m_chain_tx_count == pindex->nTx + pindex->pprev->m_chain_tx_count);
5414 assert((pindex->m_chain_tx_count != 0) == (pindex == snap_base));
5418 for (
auto c :
GetAll()) {
5419 if (c->m_chain.Tip() ==
nullptr)
continue;
5433 if (!
CBlockIndexWorkComparator()(pindex, c->m_chain.Tip()) && (pindexFirstNeverProcessed ==
nullptr || pindex == snap_base)) {
5437 if (pindexFirstInvalid ==
nullptr) {
5456 if (pindexFirstMissing ==
nullptr || pindex == c->m_chain.Tip() || pindex == c->SnapshotBase()) {
5463 assert(c->setBlockIndexCandidates.count(pindex));
5471 assert(c->setBlockIndexCandidates.count(pindex) == 0);
5475 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeUnlinked =
m_blockman.
m_blocks_unlinked.equal_range(pindex->pprev);
5476 bool foundInUnlinked =
false;
5477 while (rangeUnlinked.first != rangeUnlinked.second) {
5478 assert(rangeUnlinked.first->first == pindex->pprev);
5479 if (rangeUnlinked.first->second == pindex) {
5480 foundInUnlinked =
true;
5483 rangeUnlinked.first++;
5485 if (pindex->pprev && (pindex->nStatus &
BLOCK_HAVE_DATA) && pindexFirstNeverProcessed !=
nullptr && pindexFirstInvalid ==
nullptr) {
5490 if (pindexFirstMissing ==
nullptr)
assert(!foundInUnlinked);
5491 if (pindex->pprev && (pindex->nStatus &
BLOCK_HAVE_DATA) && pindexFirstNeverProcessed ==
nullptr && pindexFirstMissing !=
nullptr) {
5502 for (
auto c :
GetAll()) {
5505 if (pindexFirstInvalid ==
nullptr) {
5506 if (is_active || snap_base->GetAncestor(pindex->nHeight) == pindex) {
5518 snap_update_firsts();
5519 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> range = forward.equal_range(pindex);
5520 if (range.first != range.second) {
5522 pindex = range.first->second;
5525 }
else if (best_hdr_chain.
Contains(pindex)) {
5528 pindex = best_hdr_chain[
nHeight];
5536 snap_update_firsts();
5538 if (pindex == pindexFirstInvalid) pindexFirstInvalid =
nullptr;
5539 if (pindex == pindexFirstMissing) pindexFirstMissing =
nullptr;
5540 if (pindex == pindexFirstNeverProcessed) pindexFirstNeverProcessed =
nullptr;
5541 if (pindex == pindexFirstNotTreeValid) pindexFirstNotTreeValid =
nullptr;
5542 if (pindex == pindexFirstNotTransactionsValid) pindexFirstNotTransactionsValid =
nullptr;
5543 if (pindex == pindexFirstNotChainValid) pindexFirstNotChainValid =
nullptr;
5544 if (pindex == pindexFirstNotScriptsValid) pindexFirstNotScriptsValid =
nullptr;
5548 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangePar = forward.equal_range(pindexPar);
5549 while (rangePar.first->second != pindex) {
5550 assert(rangePar.first != rangePar.second);
5555 if (rangePar.first != rangePar.second) {
5557 pindex = rangePar.first->second;
5559 }
else if (pindexPar == best_hdr_chain[
nHeight - 1]) {
5561 pindex = best_hdr_chain[
nHeight];
5563 assert((pindex ==
nullptr) == (pindexPar == best_hdr_chain.
Tip()));
5575 assert(nNodes == forward.size() + best_hdr_chain.
Height() + 1);
5582 return strprintf(
"Chainstate [%s] @ height %d (%s)",
5587 bool Chainstate::ResizeCoinsCaches(
size_t coinstip_size,
size_t coinsdb_size)
5600 LogPrintf(
"[%s] resized coinsdb cache to %.1f MiB\n",
5601 this->
ToString(), coinsdb_size * (1.0 / 1024 / 1024));
5602 LogPrintf(
"[%s] resized coinstip cache to %.1f MiB\n",
5603 this->
ToString(), coinstip_size * (1.0 / 1024 / 1024));
5608 if (coinstip_size > old_coinstip_size) {
5623 if (pindex ==
nullptr) {
5632 int64_t nNow = time(
nullptr);
5637 fTxTotal =
data.tx_count + (nNow -
data.nTime) *
data.dTxRate;
5648 if (m_active_chainstate && m_active_chainstate->m_from_snapshot_blockhash) {
5650 return m_active_chainstate->m_from_snapshot_blockhash;
5652 return std::nullopt;
5658 std::vector<Chainstate*>
out;
5660 for (
Chainstate*
cs : {m_ibd_chainstate.get(), m_snapshot_chainstate.get()}) {
5670 assert(!m_ibd_chainstate);
5671 assert(!m_active_chainstate);
5673 m_ibd_chainstate = std::make_unique<Chainstate>(mempool,
m_blockman, *
this);
5674 m_active_chainstate = m_ibd_chainstate.get();
5675 return *m_active_chainstate;
5687 bool existed = fs::remove(base_blockhash_path);
5689 LogPrintf(
"[snapshot] snapshot chainstate dir being removed lacks %s file\n",
5692 }
catch (
const fs::filesystem_error& e) {
5693 LogPrintf(
"[snapshot] failed to remove file %s: %s\n",
5699 LogPrintf(
"Removing leveldb dir at %s\n", path_str);
5703 const bool destroyed =
DestroyDB(path_str);
5706 LogPrintf(
"error: leveldb DestroyDB call failed on %s\n", path_str);
5734 if (!
GetParams().AssumeutxoForBlockhash(base_blockhash).has_value()) {
5736 std::string heights_formatted =
util::Join(available_heights,
", ", [&](
const auto& i) {
return util::ToString(i); });
5737 return util::Error{
Untranslated(
strprintf(
"assumeutxo block hash in snapshot metadata not recognized (hash: %s). The following snapshot heights are available: %s",
5739 heights_formatted))};
5743 if (!snapshot_start_block) {
5744 return util::Error{
Untranslated(
strprintf(
"The base block header (%s) must appear in the headers chain. Make sure all headers are syncing, and call loadtxoutset again",
5749 if (start_block_invalid) {
5753 if (!m_best_header || m_best_header->GetAncestor(snapshot_start_block->nHeight) != snapshot_start_block) {
5754 return util::Error{
Untranslated(
"A forked headers-chain with more work than the chain with the snapshot base block header exists. Please proceed to sync without AssumeUtxo.")};
5757 auto mempool{m_active_chainstate->GetMempool()};
5758 if (mempool && mempool->size() > 0) {
5763 int64_t current_coinsdb_cache_size{0};
5764 int64_t current_coinstip_cache_size{0};
5772 static constexpr
double IBD_CACHE_PERC = 0.01;
5773 static constexpr
double SNAPSHOT_CACHE_PERC = 0.99;
5785 current_coinsdb_cache_size = this->
ActiveChainstate().m_coinsdb_cache_size_bytes;
5786 current_coinstip_cache_size = this->
ActiveChainstate().m_coinstip_cache_size_bytes;
5791 static_cast<size_t>(current_coinstip_cache_size * IBD_CACHE_PERC),
5792 static_cast<size_t>(current_coinsdb_cache_size * IBD_CACHE_PERC));
5796 return std::make_unique<Chainstate>(
5797 nullptr,
m_blockman, *
this, base_blockhash));
5801 snapshot_chainstate->InitCoinsDB(
5802 static_cast<size_t>(current_coinsdb_cache_size * SNAPSHOT_CACHE_PERC),
5803 in_memory,
false,
"chainstate");
5804 snapshot_chainstate->InitCoinsCache(
5805 static_cast<size_t>(current_coinstip_cache_size * SNAPSHOT_CACHE_PERC));
5809 this->MaybeRebalanceCaches();
5817 snapshot_chainstate.reset();
5821 "Manually remove it before restarting.\n"),
fs::PathToString(*snapshot_datadir)));
5838 return cleanup_bad_snapshot(
Untranslated(
"work does not exceed active chainstate"));
5844 return cleanup_bad_snapshot(
Untranslated(
"could not write base blockhash"));
5848 assert(!m_snapshot_chainstate);
5849 m_snapshot_chainstate.swap(snapshot_chainstate);
5850 const bool chaintip_loaded = m_snapshot_chainstate->LoadChainTip();
5855 Assert(m_active_chainstate->m_mempool->size() == 0);
5856 Assert(!m_snapshot_chainstate->m_mempool);
5857 m_snapshot_chainstate->m_mempool = m_active_chainstate->m_mempool;
5858 m_active_chainstate->m_mempool =
nullptr;
5859 m_active_chainstate = m_snapshot_chainstate.get();
5862 LogPrintf(
"[snapshot] successfully activated snapshot %s\n", base_blockhash.
ToString());
5864 m_snapshot_chainstate->CoinsTip().DynamicMemoryUsage() / (1000 * 1000));
5866 this->MaybeRebalanceCaches();
5867 return snapshot_start_block;
5874 snapshot_loaded ?
"saving snapshot chainstate" :
"flushing coins cache",
5878 coins_cache.
Flush();
5883 const char*
what() const noexcept
override 5885 return "ComputeUTXOStats interrupted.";
5907 if (!snapshot_start_block) {
5911 base_blockhash.ToString()))};
5914 int base_height = snapshot_start_block->
nHeight;
5917 if (!maybe_au_data) {
5919 "(%d) - refusing to load snapshot", base_height))};
5934 LogPrintf(
"[snapshot] loading %d coins from snapshot %s\n", coins_left, base_blockhash.ToString());
5935 int64_t coins_processed{0};
5937 while (coins_left > 0) {
5941 size_t coins_per_txid{0};
5944 if (coins_per_txid > coins_left) {
5948 for (
size_t i = 0; i < coins_per_txid; i++) {
5952 outpoint.
hash = txid;
5954 if (coin.nHeight > base_height ||
5955 outpoint.
n >= std::numeric_limits<decltype(outpoint.
n)>::max()
5958 coins_count - coins_left))};
5962 coins_count - coins_left))};
5969 if (coins_processed % 1000000 == 0) {
5970 LogPrintf(
"[snapshot] %d coins loaded (%.2f%%, %.2f MB)\n",
5972 static_cast<float>(coins_processed) * 100 / static_cast<float>(coins_count),
5980 if (coins_processed % 120000 == 0) {
5986 return snapshot_chainstate.GetCoinsCacheSizeState());
5999 }
catch (
const std::ios_base::failure&) {
6012 bool out_of_coins{
false};
6014 std::byte left_over_byte;
6015 coins_file >> left_over_byte;
6016 }
catch (
const std::ios_base::failure&) {
6018 out_of_coins =
true;
6020 if (!out_of_coins) {
6025 LogPrintf(
"[snapshot] loaded %d (%.2f MB) coins from snapshot %s\n",
6028 base_blockhash.ToString());
6039 std::optional<CCoinsStats> maybe_stats;
6047 if (!maybe_stats.has_value()) {
6068 constexpr
int AFTER_GENESIS_START{1};
6070 for (
int i = AFTER_GENESIS_START; i <= snapshot_chainstate.
m_chain.
Height(); ++i) {
6071 index = snapshot_chainstate.
m_chain[i];
6088 assert(index == snapshot_start_block);
6092 LogPrintf(
"[snapshot] validated snapshot (%.2f MB)\n",
6115 !this->
IsUsable(m_snapshot_chainstate.get()) ||
6116 !this->
IsUsable(m_ibd_chainstate.get()) ||
6117 !m_ibd_chainstate->m_chain.Tip()) {
6123 const int snapshot_base_height = *
Assert(this->GetSnapshotBaseHeight());
6126 if (index_new.
nHeight < snapshot_base_height) {
6136 "%s failed to validate the -assumeutxo snapshot state. " 6137 "This indicates a hardware problem, or a bug in the software, or a " 6138 "bad software modification that allowed an invalid snapshot to be " 6139 "loaded. As a result of this, the node will shut down and stop using any " 6140 "state that was built on the snapshot, resetting the chain height " 6141 "from %d to %d. On the next " 6142 "restart, the node will resume syncing from %d " 6143 "without using any snapshot data. " 6144 "Please report this incident to %s, including how you obtained the snapshot. " 6145 "The invalid snapshot chainstate will be left on disk in case it is " 6146 "helpful in diagnosing the issue that caused this error."),
6147 CLIENT_NAME, snapshot_tip_height, snapshot_base_height, snapshot_base_height, CLIENT_BUGREPORT
6151 LogError(
"[snapshot] deleting snapshot, reverting to validated chain, and stopping node\n");
6153 m_active_chainstate = m_ibd_chainstate.get();
6154 m_snapshot_chainstate->m_disabled =
true;
6158 auto rename_result = m_snapshot_chainstate->InvalidateCoinsDBOnDisk();
6159 if (!rename_result) {
6167 LogPrintf(
"[snapshot] supposed base block %s does not match the " 6168 "snapshot base block %s (height %d). Snapshot is not valid.\n",
6169 index_new.
ToString(), snapshot_blockhash.
ToString(), snapshot_base_height);
6170 handle_invalid_snapshot();
6176 int curr_height = m_ibd_chainstate->m_chain.Height();
6178 assert(snapshot_base_height == curr_height);
6183 CCoinsViewDB& ibd_coins_db = m_ibd_chainstate->CoinsDB();
6184 m_ibd_chainstate->ForceFlushStateToDisk();
6187 if (!maybe_au_data) {
6188 LogPrintf(
"[snapshot] assumeutxo data not found for height " 6189 "(%d) - refusing to validate snapshot\n", curr_height);
6190 handle_invalid_snapshot();
6195 std::optional<CCoinsStats> maybe_ibd_stats;
6196 LogPrintf(
"[snapshot] computing UTXO stats for background chainstate to validate " 6197 "snapshot - this could take a few minutes\n");
6200 CoinStatsHashType::HASH_SERIALIZED,
6209 if (!maybe_ibd_stats) {
6210 LogPrintf(
"[snapshot] failed to generate stats for validation coins db\n");
6214 handle_invalid_snapshot();
6217 const auto& ibd_stats = *maybe_ibd_stats;
6226 LogPrintf(
"[snapshot] hash mismatch: actual=%s, expected=%s\n",
6227 ibd_stats.hashSerialized.ToString(),
6229 handle_invalid_snapshot();
6233 LogPrintf(
"[snapshot] snapshot beginning at %s has been fully validated\n",
6236 m_ibd_chainstate->m_disabled =
true;
6237 this->MaybeRebalanceCaches();
6245 assert(m_active_chainstate);
6246 return *m_active_chainstate;
6252 return m_snapshot_chainstate && m_active_chainstate == m_snapshot_chainstate.get();
6255 void ChainstateManager::MaybeRebalanceCaches()
6258 bool ibd_usable = this->
IsUsable(m_ibd_chainstate.get());
6259 bool snapshot_usable = this->
IsUsable(m_snapshot_chainstate.get());
6260 assert(ibd_usable || snapshot_usable);
6262 if (ibd_usable && !snapshot_usable) {
6267 else if (snapshot_usable && !ibd_usable) {
6269 LogPrintf(
"[snapshot] allocating all cache to the snapshot chainstate\n");
6273 else if (ibd_usable && snapshot_usable) {
6278 m_ibd_chainstate->ResizeCoinsCaches(
6280 m_snapshot_chainstate->ResizeCoinsCaches(
6283 m_snapshot_chainstate->ResizeCoinsCaches(
6285 m_ibd_chainstate->ResizeCoinsCaches(
6291 void ChainstateManager::ResetChainstates()
6293 m_ibd_chainstate.reset();
6294 m_snapshot_chainstate.reset();
6295 m_active_chainstate =
nullptr;
6305 if (!opts.check_block_index.has_value()) opts.
check_block_index = opts.chainparams.DefaultConsistencyChecks();
6306 if (!opts.minimum_chain_work.has_value()) opts.minimum_chain_work =
UintToArith256(opts.chainparams.GetConsensus().nMinimumChainWork);
6307 if (!opts.assumed_valid_block.has_value()) opts.assumed_valid_block = opts.chainparams.GetConsensus().defaultAssumeValid;
6308 return std::move(opts);
6313 m_interrupt{interrupt},
6314 m_options{
Flatten(std::move(options))},
6315 m_blockman{interrupt, std::move(blockman_options)},
6327 bool ChainstateManager::DetectSnapshotChainstate()
6329 assert(!m_snapshot_chainstate);
6335 if (!base_blockhash) {
6338 LogPrintf(
"[snapshot] detected active snapshot chainstate (%s) - loading\n",
6341 this->ActivateExistingSnapshot(*base_blockhash);
6347 assert(!m_snapshot_chainstate);
6348 m_snapshot_chainstate =
6349 std::make_unique<Chainstate>(
nullptr,
m_blockman, *
this, base_blockhash);
6350 LogPrintf(
"[snapshot] switching active chainstate to %s\n", m_snapshot_chainstate->ToString());
6353 Assert(m_active_chainstate->m_mempool->size() == 0);
6354 Assert(!m_snapshot_chainstate->m_mempool);
6355 m_snapshot_chainstate->m_mempool = m_active_chainstate->m_mempool;
6356 m_active_chainstate->m_mempool =
nullptr;
6357 m_active_chainstate = m_snapshot_chainstate.get();
6358 return *m_snapshot_chainstate;
6363 return (block_index.
nHeight==91842 && block_index.
GetBlockHash() ==
uint256{
"00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec"}) ||
6364 (block_index.
nHeight==91880 && block_index.
GetBlockHash() ==
uint256{
"00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"});
6369 return (block_index.
nHeight==91722 && block_index.
GetBlockHash() ==
uint256{
"00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e"}) ||
6370 (block_index.
nHeight==91812 && block_index.
GetBlockHash() ==
uint256{
"00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f"});
6377 assert(
cs.m_from_snapshot_blockhash);
6378 auto storage_path_maybe =
cs.CoinsDB().StoragePath();
6380 assert(storage_path_maybe);
6381 return *storage_path_maybe;
6391 auto invalid_path = snapshot_datadir +
"_INVALID";
6394 LogPrintf(
"[snapshot] renaming snapshot datadir %s to %s\n", dbpath, target);
6400 fs::rename(snapshot_datadir, invalid_path);
6401 }
catch (
const fs::filesystem_error& e) {
6405 LogPrintf(
"%s: error renaming file '%s' -> '%s': %s\n",
6406 __func__, src_str, dest_str, e.what());
6408 "Rename of '%s' -> '%s' failed. " 6409 "You should resolve this by manually moving or deleting the invalid " 6410 "snapshot directory %s, otherwise you will encounter the same error again " 6411 "on the next startup."),
6412 src_str, dest_str, src_str)};
6417 bool ChainstateManager::DeleteSnapshotChainstate()
6420 Assert(m_snapshot_chainstate);
6421 Assert(m_ibd_chainstate);
6425 LogPrintf(
"Deletion of %s failed. Please remove it manually to continue reindexing.\n",
6429 m_active_chainstate = m_ibd_chainstate.get();
6430 m_active_chainstate->m_mempool = m_snapshot_chainstate->m_mempool;
6431 m_snapshot_chainstate.reset();
6445 const CBlockIndex* ChainstateManager::GetSnapshotBaseBlock()
const 6447 return m_active_chainstate ? m_active_chainstate->SnapshotBase() :
nullptr;
6450 std::optional<int> ChainstateManager::GetSnapshotBaseHeight()
const 6452 const CBlockIndex* base = this->GetSnapshotBaseBlock();
6453 return base ? std::make_optional(base->
nHeight) :
std::nullopt;
6456 void ChainstateManager::RecalculateBestHeader()
6460 for (
auto& entry :
m_blockman.m_block_index) {
6461 if (!(entry.second.nStatus &
BLOCK_FAILED_MASK) && m_best_header->nChainWork < entry.second.nChainWork) {
6462 m_best_header = &entry.second;
6467 bool ChainstateManager::ValidatedSnapshotCleanup()
6471 if (!(chainstate && chainstate->HasCoinsViews())) {
6474 return chainstate->CoinsDB().StoragePath();
6476 std::optional<fs::path> ibd_chainstate_path_maybe = get_storage_path(m_ibd_chainstate);
6477 std::optional<fs::path> snapshot_chainstate_path_maybe = get_storage_path(m_snapshot_chainstate);
6486 if (!ibd_chainstate_path_maybe || !snapshot_chainstate_path_maybe) {
6487 LogPrintf(
"[snapshot] snapshot chainstate cleanup cannot happen with " 6488 "in-memory chainstates. You are testing, right?\n");
6492 const auto& snapshot_chainstate_path = *snapshot_chainstate_path_maybe;
6493 const auto& ibd_chainstate_path = *ibd_chainstate_path_maybe;
6501 this->ResetChainstates();
6506 LogPrintf(
"[snapshot] deleting background chainstate directory (now unnecessary) (%s)\n",
6509 fs::path tmp_old{ibd_chainstate_path +
"_todelete"};
6511 auto rename_failed_abort = [
this](
6514 const fs::filesystem_error& err) {
6515 LogError(
"[snapshot] Error renaming path (%s) -> (%s): %s\n",
6518 "Rename of '%s' -> '%s' failed. " 6519 "Cannot clean up the background chainstate leveldb directory."),
6524 fs::rename(ibd_chainstate_path, tmp_old);
6525 }
catch (
const fs::filesystem_error& e) {
6526 rename_failed_abort(ibd_chainstate_path, tmp_old, e);
6530 LogPrintf(
"[snapshot] moving snapshot chainstate (%s) to " 6531 "default chainstate directory (%s)\n",
6535 fs::rename(snapshot_chainstate_path, ibd_chainstate_path);
6536 }
catch (
const fs::filesystem_error& e) {
6537 rename_failed_abort(snapshot_chainstate_path, ibd_chainstate_path, e);
6544 LogPrintf(
"Deletion of %s failed. Please remove it manually, as the " 6545 "directory is now unnecessary.\n",
6548 LogPrintf(
"[snapshot] deleted background chainstate directory (%s)\n",
6554 Chainstate& ChainstateManager::GetChainstateForIndexing()
6559 return (this->
GetAll().size() > 1) ? *m_ibd_chainstate : *m_active_chainstate;
6562 std::pair<int, int> ChainstateManager::GetPruneRange(
const Chainstate& chainstate,
int last_height_can_prune)
6569 if (this->
GetAll().size() > 1 && m_snapshot_chainstate.get() == &chainstate) {
6572 prune_start = *
Assert(GetSnapshotBaseHeight()) + 1;
6575 int max_prune = std::max<int>(
6584 int prune_end = std::min(last_height_can_prune, max_prune);
6586 return {prune_start, prune_end};
std::optional< std::string > PaysForRBF(CAmount original_fees, CAmount replacement_fees, size_t replacement_vsize, CFeeRate relay_fee, const uint256 &txid)
The replacement transaction must pay more fees than the original transactions.
std::shared_ptr< const CTransaction > CTransactionRef
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
CoinsViewOptions coins_view
static unsigned int GetBlockScriptFlags(const CBlockIndex &block_index, const ChainstateManager &chainman)
std::string GetHex() const
CSHA256 & Write(const unsigned char *data, size_t len)
void PruneBlockFilesManual(Chainstate &active_chainstate, int nManualPruneHeight)
Prune block files up to a given height.
bool IsSpent() const
Either this coin never existed (see e.g.
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
const std::optional< uint256 > m_from_snapshot_blockhash
The blockhash which is the base of the snapshot this chainstate was created from. ...
std::optional< std::string > EntriesAndTxidsDisjoint(const CTxMemPool::setEntries &ancestors, const std::set< Txid > &direct_conflicts, const uint256 &txid)
Check the intersection between two sets of transactions (a set of mempool entries and a set of txids)...
const uint256 & AssumedValidBlock() const
static constexpr unsigned int LOCKTIME_VERIFY_SEQUENCE
Flags for nSequence and nLockTime locks.
std::optional< int > m_snapshot_height
The height of the base block of an assumeutxo snapshot, if one is in use.
virtual void warningUnset(Warning id)
fs::path path
Location in the filesystem where leveldb data will be stored.
const std::vector< std::string > CHECKLEVEL_DOC
Documentation for argument 'checklevel'.
std::vector< Coin > vprevout
void InvalidChainFound(CBlockIndex *pindexNew) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
std::string ToString() const
int64_t EndTime(const Consensus::Params ¶ms) const override
static constexpr std::chrono::hours MAX_FEE_ESTIMATION_TIP_AGE
Maximum age of our tip for us to be considered current for fee estimation.
CTxMemPool * m_mempool
Optional mempool that is kept in sync with the chain.
int32_t nSequenceId
(memory only) Sequential id assigned to distinguish order in which blocks are received.
bool ReplayBlocks()
Replay blocks that aren't fully applied to the database.
invalid by consensus rules
bool CheckTxInputs(const CTransaction &tx, TxValidationState &state, const CCoinsViewCache &inputs, int nSpendHeight, CAmount &txfee)
Check whether all inputs of this transaction are valid (no double spends and amounts) This does not m...
static bool CheckWitnessMalleation(const CBlock &block, bool expect_witness_commitment, BlockValidationState &state)
CheckWitnessMalleation performs checks for block malleation with regard to its witnesses.
bool HaveNumChainTxs() const
Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot ...
SignatureCache m_signature_cache
std::optional< std::string > PaysMoreThanConflicts(const CTxMemPool::setEntries &iters_conflicting, CFeeRate replacement_feerate, const uint256 &txid)
Check that the feerate of the replacement transaction(s) is higher than the feerate of each of the tr...
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams)
static GenTxid Wtxid(const uint256 &hash)
bool m_check_for_pruning
Global flag to indicate we should check to see if there are block/undo files that should be deleted...
SteadyClock::time_point m_last_flush
static MempoolAcceptResult FeeFailure(TxValidationState state, CFeeRate effective_feerate, const std::vector< Wtxid > &wtxids_fee_calculations)
static void FlushSnapshotToDisk(CCoinsViewCache &coins_cache, bool snapshot_loaded)
bool ProcessNewBlockHeaders(std::span< const CBlockHeader > headers, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr< const CBlock > &)
void UpdateBlockInfo(const CBlock &block, unsigned int nHeight, const FlatFilePos &pos)
Update blockfile info while processing a block during reindex.
bool Error(const std::string &reject_reason)
SynchronizationState
Current sync state passed to tip changed callbacks.
void BlockConnected(ChainstateRole, const std::shared_ptr< const CBlock > &, const CBlockIndex *pindex)
bool IsStandardTx(const CTransaction &tx, const std::optional< unsigned > &max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate &dust_relay_fee, std::string &reason)
Check for standard transaction types.
static const int WITNESS_SCALE_FACTOR
bool WriteBlockUndo(const CBlockUndo &blockundo, BlockValidationState &state, CBlockIndex &block) EXCLUSIVE_LOCKS_REQUIRED(FlatFilePos WriteBlock(const CBlock &block, int nHeight)
Store block on disk and update block file statistics.
bool IsPruneMode() const
Whether running in -prune mode.
void Finalize(Span< unsigned char > output)
std::string GetDebugMessage() const
Convenience class for initializing and passing the script execution cache and signature cache...
int64_t GetBlockTime() const
indexed_transaction_set::nth_index< 0 >::type::const_iterator txiter
int Threshold(const Consensus::Params ¶ms) const override
bool LoadGenesisBlock()
Ensures we have a genesis block in the block tree, possibly writing one to disk.
enum ScriptError_t ScriptError
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
descends from failed block
CBlockIndex * pprev
pointer to the index of the predecessor of this block
uint256 GetPackageHash(const std::vector< CTransactionRef > &transactions)
Get the hash of the concatenated wtxids of transactions, with wtxids treated as a little-endian numbe...
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or coinEmpty if not found.
ValidationSignals * signals
The package itself is invalid (e.g. too many transactions).
bool Flush()
Push the modifications applied to this cache to its base and wipe local state.
std::optional< std::string > HasNoNewUnconfirmed(const CTransaction &tx, const CTxMemPool &pool, const CTxMemPool::setEntries &iters_conflicting)
The replacement transaction may only include an unconfirmed input if that input was included in one o...
node::BlockManager & m_blockman
Reference to a BlockManager instance which itself is shared across all Chainstate instances...
bool exists(const GenTxid >xid) const
void UpdateTransactionsFromBlock(const std::vector< uint256 > &vHashesToUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs
UpdateTransactionsFromBlock is called when adding transactions from a disconnected block back to the ...
bool IsChildWithParents(const Package &package)
Context-free check that a package is exactly one child and its parents; not all parents need to be pr...
We don't have the previous block the checked one is built on.
int64_t BeginTime(const Consensus::Params ¶ms) const override
RecursiveMutex cs_LastBlockFile
The cache is at >= 90% capacity.
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
void BlockDisconnected(const std::shared_ptr< const CBlock > &, const CBlockIndex *pindex)
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Options struct containing limit options for a CTxMemPool.
An in-memory indexed chain of blocks.
bool CheckBlockDataAvailability(const CBlockIndex &upper_block LIFETIMEBOUND, const CBlockIndex &lower_block LIFETIMEBOUND) EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetFirstBlock(const CBlockIndex &upper_block LIFETIMEBOUND, uint32_t status_mask, const CBlockIndex *lower_block=nullptr) const EXCLUSIVE_LOCKS_REQUIRED(boo m_have_pruned)
Check if all blocks in the [upper_block, lower_block] range have data available.
bool ShouldCheckBlockIndex() const
size_t DynamicMemoryUsage() const
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, unsigned int flags, const BaseSignatureChecker &checker, ScriptError *serror)
static const int32_t VERSIONBITS_TOP_MASK
What bitmask determines whether versionbits is in use.
int Period(const Consensus::Params ¶ms) const override
bool DestroyDB(const std::string &path_str)
invalid proof of work or time too old
std::optional< uint256 > ReadSnapshotBaseBlockhash(fs::path chaindir)
size_t m_coinsdb_cache_size_bytes
The cache size of the on-disk coins view.
bool Condition(const CBlockIndex *pindex, const Consensus::Params ¶ms) const override
VerifyDBResult VerifyDB(Chainstate &chainstate, const Consensus::Params &consensus_params, CCoinsView &coinsview, int nCheckLevel, int nCheckDepth) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool SequenceLocks(const CTransaction &tx, int flags, std::vector< int > &prevHeights, const CBlockIndex &block)
Check if transaction is final per BIP 68 sequence numbers and can be included in a block...
size_t GetSerializeSize(const T &t)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
transaction was missing some of its inputs
std::unique_ptr< CoinsViews > m_coins_views
Manages the UTXO set, which is a reflection of the contents of m_chain.
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
bool MoneyRange(const CAmount &nValue)
int Height() const
Return the maximal height in the chain.
virtual void progress(const bilingual_str &title, int progress_percent, bool resume_possible)
size_t DynamicMemoryUsage() const
Calculate the size of the cache (in bytes)
std::unordered_map< uint256, CBlockIndex, BlockHasher > BlockMap
CTxOut out
unspent transaction output
const CChainParams & chainparams
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache &versionbitscache)
Determine if a deployment is active for the next block.
static constexpr size_t WARN_FLUSH_COINS_SIZE
Size threshold for warning about slow UTXO set flush to disk.
bool AcceptBlockHeader(const CBlockHeader &block, BlockValidationState &state, CBlockIndex **ppindex, bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
If a block header hasn't already been seen, call CheckBlockHeader on it, ensure that it doesn't desce...
stage after last reached validness failed
constexpr const std::byte * begin() const
bool CheckFinalTxAtTip(const CBlockIndex &active_chain_tip, const CTransaction &tx)
static constexpr size_t MINIMUM_WITNESS_COMMITMENT
Minimum size of a witness commitment structure.
unsigned int fCoinBase
whether containing transaction was a coinbase
static constexpr int MAX_SCRIPTCHECK_THREADS
Maximum number of dedicated script-checking threads allowed.
The coins cache is in immediate need of a flush.
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule) ...
bool HaveCoinInCache(const COutPoint &outpoint) const
Check if we have the given utxo already loaded in this cache.
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid...
void ResizeCache(size_t new_cache_size) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Dynamically alter the underlying leveldb cache size.
An options struct for ChainstateManager, more ergonomically referred to as ChainstateManager::Options...
bool ReadBlock(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
bool IsInterrupted(const T &result)
uint256 BlockWitnessMerkleRoot(const CBlock &block, bool *mutated)
std::vector< CTxOut > m_spent_outputs
std::set< txiter, CompareIteratorByHash > setEntries
std::string FormatISO8601DateTime(int64_t nTime)
ISO 8601 formatting is preferred.
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS
For convenience, standard but not mandatory verify flags.
static bool IsCurrentForFeeEstimation(Chainstate &active_chainstate) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
CBlockIndex * Genesis() const
Returns the index entry for the genesis block of this chain, or nullptr if none.
static fs::path GetSnapshotCoinsDBPath(Chainstate &cs) EXCLUSIVE_LOCKS_REQUIRED(
PerBlockConnectTrace()=default
std::set< CBlockIndex * > m_failed_blocks
In order to efficiently track invalidity of headers, we keep the set of blocks which we tried to conn...
Wrapper around an AutoFile& that implements a ring buffer to deserialize from.
size_t m_total_coinsdb_cache
The total number of bytes available for us to use across all leveldb coins databases.
int ApplyTxInUndo(Coin &&undo, CCoinsViewCache &view, const COutPoint &out)
Restore the UTXO in a Coin at a given COutPoint.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
User-controlled performance and debug options.
bool ConnectTip(BlockValidationState &state, CBlockIndex *pindexNew, const std::shared_ptr< const CBlock > &pblock, ConnectTrace &connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Connect a new block to m_chain.
violated mempool's fee/size/descendant/RBF/etc limits
the block header may be on a too-little-work chain
MempoolAcceptResult AcceptToMemoryPool(Chainstate &active_chainstate, const CTransactionRef &tx, int64_t accept_time, bool bypass_limits, bool test_accept)
Try to add a transaction to the mempool.
void Clear() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
bool contains(const Element &e, const bool erase) const
contains iterates through the hash locations for a given element and checks to see if it is present...
inputs (covered by txid) failed policy rules
undo data available in rev*.dat
memcpy(result.begin(), stream.data(), stream.size())
A hasher class for Bitcoin's 256-bit hash (double SHA-256).
ThresholdState
BIP 9 defines a finite-state-machine to deploy a softfork in multiple stages.
void MaybeUpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool fAddToMempool) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Make mempool consistent after a reorg, by re-adding or recursively erasing disconnected block transac...
const ResultType m_result_type
Result type.
std::optional< fs::path > FindSnapshotChainstateDir(const fs::path &data_dir)
Return a path to the snapshot-based chainstate dir, if one exists.
void InvalidBlockFound(CBlockIndex *pindex, const BlockValidationState &state) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
RAII-style controller object for a CCheckQueue that guarantees the passed queue is finished before co...
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
If sanity-checking is turned on, check makes sure the pool is consistent (does not contain two transa...
TRACEPOINT_SEMAPHORE(validation, block_connected)
transaction spends a coinbase too early, or violates locktime/sequence locks
void LoadExternalBlockFile(AutoFile &file_in, FlatFilePos *dbp=nullptr, std::multimap< uint256, FlatFilePos > *blocks_with_unknown_parent=nullptr)
Import blocks from an external file.
static constexpr int NO_WITNESS_COMMITMENT
Index marker for when no witness commitment is present in a coinbase transaction. ...
double GuessVerificationProgress(const CBlockIndex *pindex) const
Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip).
static bool ContextualCheckBlock(const CBlock &block, BlockValidationState &state, const ChainstateManager &chainman, const CBlockIndex *pindexPrev)
NOTE: This function is not currently invoked by ConnectBlock(), so we should consider upgrade issues ...
CChain m_chain
The current chain of blockheaders we consult and build on.
static bool CheckMerkleRoot(const CBlock &block, BlockValidationState &state)
static const unsigned int MAX_DISCONNECTED_TX_POOL_BYTES
Maximum bytes for transactions to store for processing during reorg.
consteval auto _(util::TranslatedLiteral str)
util::Result< void > PopulateAndValidateSnapshot(Chainstate &snapshot_chainstate, AutoFile &coins_file, const node::SnapshotMetadata &metadata)
Internal helper for ActivateSnapshot().
void ChainStateFlushed(ChainstateRole, const CBlockLocator &)
static const int64_t MAX_BLOCK_SIGOPS_COST
The maximum allowed number of signature check operations in a block (network rule) ...
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache &versionbitscache)
Determine if a deployment is active for this block.
void UnlinkPrunedFiles(const std::set< int > &setFilesToPrune) const
Actually unlink the specified files.
const char * what() const noexcept override
util::Result< CBlockIndex * > ActivateSnapshot(AutoFile &coins_file, const node::SnapshotMetadata &metadata, bool in_memory)
Construct and activate a Chainstate on the basis of UTXO snapshot data.
bool TestBlockValidity(BlockValidationState &state, const CChainParams &chainparams, Chainstate &chainstate, const CBlock &block, CBlockIndex *pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot)
Check a block is completely valid from start to finish (only works on top of our current best block) ...
Non-refcounted RAII wrapper for FILE*.
static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS
Standard script verification flags that standard transactions will comply with.
void SetTip(CBlockIndex &block)
Set/initialize a chain with a given tip.
std::optional< std::pair< std::string, CTransactionRef > > SingleTRUCChecks(const CTransactionRef &ptx, const CTxMemPool::setEntries &mempool_ancestors, const std::set< Txid > &direct_conflicts, int64_t vsize)
Must be called for every transaction, even if not TRUC.
static void LimitMempoolSize(CTxMemPool &pool, CCoinsViewCache &coins_cache) EXCLUSIVE_LOCKS_REQUIRED(
virtual void fatalError(const bilingual_str &message)
The fatal error notification is sent to notify the user when an error occurs in kernel code that can'...
bool SpendCoin(const COutPoint &outpoint, Coin *moveto=nullptr)
Spend a coin.
const std::vector< CTxIn > vin
std::map< uint256, uint32_t > script_flag_exceptions
Hashes of blocks that.
const util::SignalInterrupt & m_interrupt
bool IsWitnessStandard(const CTransaction &tx, const CCoinsViewCache &mapInputs)
Check if the transaction is over standard P2WSH resources limit: 3600bytes witnessScript size...
void removeForReorg(CChain &chain, std::function< bool(txiter)> filter_final_and_mature) EXCLUSIVE_LOCKS_REQUIRED(cs
After reorg, filter the entries that would no longer be valid in the next block, and update the entri...
CVerifyDB(kernel::Notifications ¬ifications)
std::vector< CBlockIndex * > GetAllBlockIndices() EXCLUSIVE_LOCKS_REQUIRED(std::multimap< CBlockIndex *, CBlockIndex * > m_blocks_unlinked
All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions.
arith_uint256 UintToArith256(const uint256 &a)
VersionBitsCache m_versionbitscache
Track versionbit status.
const Coin & AccessByTxid(const CCoinsViewCache &view, const Txid &txid)
Utility function to find any unspent output with a given txid.
constexpr unsigned char * begin()
CoinsViews(DBParams db_params, CoinsViewOptions options)
This constructor initializes CCoinsViewDB and CCoinsViewErrorCatcher instances, but it does not creat...
bool IsUsable(const Chainstate *const cs) const EXCLUSIVE_LOCKS_REQUIRED(
Return true if a chainstate is considered usable.
std::function< void()> snapshot_download_completed
Function to restart active indexes; set dynamically to avoid a circular dependency on base/index...
static const unsigned int MAX_BLOCK_WEIGHT
The maximum allowed weight for a block, see BIP 141 (network rule)
int nSubsidyHalvingInterval
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
std::optional< std::string > GetEntriesForConflicts(const CTransaction &tx, CTxMemPool &pool, const CTxMemPool::setEntries &iters_conflicting, CTxMemPool::setEntries &all_conflicts)
Get all descendants of iters_conflicting.
bool WriteSnapshotBaseBlockhash(Chainstate &snapshot_chainstate) EXCLUSIVE_LOCKS_REQUIRED(std::optional< uint256 > ReadSnapshotBaseBlockhash(fs::path chaindir) EXCLUSIVE_LOCKS_REQUIRED(constexpr std::string_view SNAPSHOT_CHAINSTATE_SUFFIX
Write out the blockhash of the snapshot base block that was used to construct this chainstate...
int64_t CAmount
Amount in satoshis (Can be negative)
void SetBestBlock(const uint256 &hashBlock)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
void PruneAndFlush()
Prune blockfiles from the disk if necessary and then flush chainstate changes if we pruned...
void UpdateTip(const CBlockIndex *pindexNew) EXCLUSIVE_LOCKS_REQUIRED(SteadyClock::time_poin m_last_write)
Check warning conditions and do some notifications on new chain tip set.
std::array< uint8_t, 4 > MessageStartChars
uint256 GetBlockHash() const
bool AreInputsStandard(const CTransaction &tx, const CCoinsViewCache &mapInputs)
Check transaction inputs to mitigate two potential denial-of-service attacks:
void FindFilesToPrune(std::set< int > &setFilesToPrune, int last_prune, const Chainstate &chain, ChainstateManager &chainman)
Prune block and undo files (blk???.dat and rev???.dat) so that the disk space used is less than a use...
void AddCoins(CCoinsViewCache &cache, const CTransaction &tx, int nHeight, bool check_for_overwrite)
Utility function to add all of a transaction's outputs to a cache.
uint32_t nHeight
at which height this containing transaction was included in the active block chain ...
void FindFilesToPruneManual(std::set< int > &setFilesToPrune, int nManualPruneHeight, const Chainstate &chain, ChainstateManager &chainman)
const fs::path SNAPSHOT_BLOCKHASH_FILENAME
The file in the snapshot chainstate dir which stores the base blockhash.
unsigned int GetCacheSize() const
Calculate the size of the cache (in number of transaction outputs)
CBlockLocator GetLocator() const
Return a CBlockLocator that refers to the tip in of this chain.
static const uint32_t MEMPOOL_HEIGHT
Fake height value used in Coin to signify they are only in the memory pool (since 0...
std::function< FILE *(const fs::path &, const char *)> FopenFn
bool IsBlockMutated(const CBlock &block, bool check_witness_root)
Check if a block has been mutated (with respect to its merkle root and witness commitments).
std::vector< int > GetAvailableSnapshotHeights() const
AssumeutxoHash hash_serialized
The expected hash of the deserialized UTXO set.
bool IsBIP30Repeat(const CBlockIndex &block_index)
Identifies blocks that overwrote an existing coinbase output in the UTXO set (see BIP30) ...
static void UpdateTipLog(const ChainstateManager &chainman, const CCoinsViewCache &coins_tip, const CBlockIndex *tip, const std::string &func_name, const std::string &prefix, const std::string &warning_messages) EXCLUSIVE_LOCKS_REQUIRED(
ChainstateManager & m_chainman
The chainstate manager that owns this chainstate.
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends...
bool DisconnectTip(BlockValidationState &state, DisconnectedBlockTransactions *disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Disconnect m_chain's tip.
bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(bool LoadBlockIndexDB(const std::optional< uint256 > &snapshot_blockhash) EXCLUSIVE_LOCKS_REQUIRED(void ScanAndUnlinkAlreadyPrunedFiles() EXCLUSIVE_LOCKS_REQUIRED(CBlockIndex * AddToBlockIndex(const CBlockHeader &block, CBlockIndex *&best_header) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Remove any pruned block & undo files that are still on disk.
static void SnapshotUTXOHashBreakpoint(const util::SignalInterrupt &interrupt)
An options struct for BlockManager, more ergonomically referred to as BlockManager::Options due to th...
bool HasValidProofOfWork(const std::vector< CBlockHeader > &headers, const Consensus::Params &consensusParams)
Check with the proof of work on each blockheader matches the value in nBits.
void Init(const T &tx, std::vector< CTxOut > &&spent_outputs, bool force=false)
Initialize this PrecomputedTransactionData with transaction data.
virtual void headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync)
bool BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The state of a background sync (for net processing)
void EmplaceCoinInternalDANGER(COutPoint &&outpoint, Coin &&coin)
Emplace a coin into cacheCoins without performing any checks, marking the emplaced coin as dirty...
bool IsSnapshotActive() const
static std::string PathToString(const path &path)
Convert path object to a byte string.
static decltype(CTransaction::version) constexpr TRUC_VERSION
Chainstate stores and provides an API to update our local knowledge of the current best chain...
bool Invalid(Result result, const std::string &reject_reason="", const std::string &debug_message="")
static void LimitValidationInterfaceQueue(ValidationSignals &signals) LOCKS_EXCLUDED(cs_main)
std::optional< LockPoints > CalculateLockPointsAtTip(CBlockIndex *tip, const CCoinsView &coins_view, const CTransaction &tx)
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
int64_t GetTransactionSigOpCost(const CTransaction &tx, const CCoinsViewCache &inputs, uint32_t flags)
Compute total signature operation cost of a transaction.
Abstract view on the open txout dataset.
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
this block was cached as being invalid and we didn't store the reason why
Validation result for package mempool acceptance.
std::atomic< bool > m_cached_finished_ibd
Whether initial block download has ended and IsInitialBlockDownload should return false from now on...
An input of a transaction.
bool ActivateBestChain(BlockValidationState &state, std::shared_ptr< const CBlock > pblock=nullptr) LOCKS_EXCLUDED(DisconnectResult DisconnectBlock(const CBlock &block, const CBlockIndex *pindex, CCoinsViewCache &view) EXCLUSIVE_LOCKS_REQUIRED(boo ConnectBlock)(const CBlock &block, BlockValidationState &state, CBlockIndex *pindex, CCoinsViewCache &view, bool fJustCheck=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Find the best known block, and make it the tip of the block chain.
std::vector< unsigned char > GenerateCoinbaseCommitment(CBlock &block, const CBlockIndex *pindexPrev) const
Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks...
uint64_t m_chain_tx_count
(memory only) Number of transactions in the chain up to and including this block. ...
static constexpr int PRUNE_LOCK_BUFFER
The number of blocks to keep below the deepest prune lock.
int64_t descendant_count
The maximum allowed number of transactions in a package including the entry and its descendants...
bool RollforwardBlock(const CBlockIndex *pindex, CCoinsViewCache &inputs) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Apply the effects of a block on the utxo cache, ignoring that it may already have been applied...
Removed for reorganization.
void ReceivedBlockTransactions(const CBlock &block, CBlockIndex *pindexNew, const FlatFilePos &pos) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS).
unsigned int GetNextWorkRequired(const CBlockIndex *pindexLast, const CBlockHeader *pblock, const Consensus::Params ¶ms)
std::string ToString() const
ValidationCache(size_t script_execution_cache_bytes, size_t signature_cache_bytes)
the block failed to meet one of our checkpoints
static bool DeleteCoinsDBFromDisk(const fs::path db_path, bool is_snapshot) EXCLUSIVE_LOCKS_REQUIRED(
void ActiveTipChange(const CBlockIndex &, bool)
bool LoadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Load the block tree and coins database from disk, initializing state if we're running with -reindex...
Chainstate(CTxMemPool *mempool, node::BlockManager &blockman, ChainstateManager &chainman, std::optional< uint256 > from_snapshot_blockhash=std::nullopt)
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
static feebumper::Result CheckFeeRate(const CWallet &wallet, const CMutableTransaction &mtx, const CFeeRate &newFeerate, const int64_t maxTxSize, CAmount old_fee, std::vector< bilingual_str > &errors)
Check if the user provided a valid feeRate.
kernel::Notifications & GetNotifications() const
const kernel::BlockManagerOpts m_opts
std::optional< std::pair< ScriptError, std::string > > operator()()
std::string ScriptErrorString(const ScriptError serror)
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
Abstract class that implements BIP9-style threshold logic, and caches results.
bool NeedsRedownload() const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Whether the chain state needs to be redownloaded due to lack of witness data.
ChainstateManager(const util::SignalInterrupt &interrupt, Options options, node::BlockManager::Options blockman_options)
Holds various statistics on transactions within a chain.
bool PreCheckEphemeralTx(const CTransaction &tx, CFeeRate dust_relay_rate, CAmount base_fee, CAmount mod_fee, TxValidationState &state)
These utility functions ensure that ephemeral dust is safely created and spent without unduly risking...
void Finalize(unsigned char hash[OUTPUT_SIZE])
bool LoadingBlocks() const
const std::vector< CTxOut > vout
void removeForBlock(const std::vector< CTransactionRef > &vtx)
Remove any entries that are in this block.
bool signet_blocks
If true, witness commitments contain a payload equal to a Bitcoin Script solution to the signet chall...
std::string ToString() const
bool TestLockPointValidity(CChain &active_chain, const LockPoints &lp)
Test whether the LockPoints height and time are still valid on the current chain. ...
const Consensus::Params & GetConsensus() const
arith_uint256 CalculateClaimedHeadersWork(std::span< const CBlockHeader > headers)
Return the sum of the claimed work on a given set of headers.
std::shared_ptr< const CBlock > pblock
arith_uint256 nLastPreciousChainwork
chainwork for the last block that preciousblock has been applied to.
bool ActivateBestChainStep(BlockValidationState &state, CBlockIndex *pindexMostWork, const std::shared_ptr< const CBlock > &pblock, bool &fInvalidFound, ConnectTrace &connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Try to make some progress towards making pindexMostWork the active block.
bool EvaluateSequenceLocks(const CBlockIndex &block, std::pair< int, int64_t > lockPair)
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
CCoinsViewDB & CoinsDB() EXCLUSIVE_LOCKS_REQUIRED(
#define LogPrintLevel(category, level,...)
CTxMemPool::txiter TxHandle
virtual std::vector< uint256 > GetHeadBlocks() const
Retrieve the range of blocks that may have been only partially written.
uint256 BlockMerkleRoot(const CBlock &block, bool *mutated)
static ChainstateManager::Options && Flatten(ChainstateManager::Options &&opts)
Apply default chain params to nullopt members.
void ForceFlushStateToDisk()
Unconditionally flush all changes to disk.
std::atomic_bool m_blockfiles_indexed
Whether all blockfiles have been added to the block tree database.
An output of a transaction.
virtual void warningSet(Warning id, const bilingual_str &message)
bool DetectSnapshotChainstate() EXCLUSIVE_LOCKS_REQUIRED(void ResetChainstates() EXCLUSIVE_LOCKS_REQUIRED(bool DeleteSnapshotChainstate() EXCLUSIVE_LOCKS_REQUIRED(Chainstate &ActivateExistingSnapshot(uint256 base_blockhash) EXCLUSIVE_LOCKS_REQUIRED(bool ValidatedSnapshotCleanup() EXCLUSIVE_LOCKS_REQUIRED(Chainstate &GetChainstateForIndexing() EXCLUSIVE_LOCKS_REQUIRED(std::pair< int, int > GetPruneRange(const Chainstate &chainstate, int last_height_can_prune) EXCLUSIVE_LOCKS_REQUIRED(std::optional< int > GetSnapshotBaseHeight() const EXCLUSIVE_LOCKS_REQUIRED(void RecalculateBestHeader() EXCLUSIVE_LOCKS_REQUIRED(CCheckQueue< CScriptCheck > & GetCheckQueue()
When starting up, search the datadir for a chainstate based on a UTXO snapshot that is in the process...
std::string ToString() const
bool LoadChainTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Update the chain tip based on database information, i.e.
bool CheckBlock(const CBlock &block, BlockValidationState &state, const Consensus::Params &consensusParams, bool fCheckPOW, bool fCheckMerkleRoot)
Functions for validating blocks and updating the block tree.
std::vector< uint256 > vHave
At least one tx is invalid.
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
uint32_t nMinerConfirmationWindow
CBlockIndex * FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Return the tip of the chain with the most work in it, that isn't known to be invalid (it's however fa...
Parameters that influence chain consensus.
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params ¶ms)
Check whether a block hash satisfies the proof-of-work requirement specified by nBits.
An outpoint - a combination of a transaction hash and an index n into its vout.
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
A base class defining functions for notifying about certain kernel events.
void TryAddBlockIndexCandidate(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
void AddTransactionsUpdated(unsigned int n)
size_t m_total_coinstip_cache
The total number of bytes available for us to use across all in-memory coins caches.
std::chrono::seconds max_tip_age
If the tip is older than this, the node is considered to be in initial block download.
constexpr bool IsNull() const
std::pair< int, int64_t > CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector< int > &prevHeights, const CBlockIndex &block)
Calculates the block height and previous block's median time past at which the transaction will be co...
fails some policy, but might be acceptable if submitted in a (different) package
DisconnectedBlockTransactions.
Chainstate &InitializeChainstate(CTxMemPool *mempool) EXCLUSIVE_LOCKS_REQUIRED(std::vector< Chainstate * GetAll)()
Instantiate a new chainstate.
Validation result for a transaction evaluated by MemPoolAccept (single or package).
bool CheckDiskSpace(const fs::path &dir, uint64_t additional_bytes)
bool CheckEphemeralSpends(const Package &package, CFeeRate dust_relay_rate, const CTxMemPool &tx_pool, TxValidationState &out_child_state, Wtxid &out_child_wtxid)
Must be called for each transaction(package) if any dust is in the package.
static MempoolAcceptResult MempoolTx(int64_t vsize, CAmount fees)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define Assume(val)
Assume is the identity function.
static MempoolAcceptResult MempoolTxDifferentWitness(const Wtxid &other_wtxid)
256-bit unsigned big integer.
int64_t GetMedianTimePast() const
int64_t ancestor_size_vbytes
The maximum allowed size in virtual bytes of an entry and its ancestors within a package.
block data in blk*.dat was received with a witness-enforcing client
void AddCoin(const COutPoint &outpoint, Coin &&coin, bool possible_overwrite)
Add a coin.
std::string FormatFullVersion()
void BlockConnected(CBlockIndex *pindex, std::shared_ptr< const CBlock > pblock)
int32_t ComputeBlockVersion(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Determine what nVersion a new block should use.
std::chrono::seconds PowTargetSpacing() const
FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(
constexpr int64_t count_seconds(std::chrono::seconds t)
Closure representing one script verification Note that this stores references to the spending transac...
ValidationCache m_validation_cache
static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST
The maximum number of sigops we're willing to relay/mine in a single tx.
static CTransactionRef MakeTransactionRef(Tx &&txIn)
void insert(Element e)
insert loops at most depth_limit times trying to insert a hash at various locations in the table via ...
static bool CheckBlockHeader(const CBlockHeader &block, BlockValidationState &state, const Consensus::Params &consensusParams, bool fCheckPOW=true)
int64_t DifficultyAdjustmentInterval() const
bool WriteSnapshotBaseBlockhash(Chainstate &snapshot_chainstate)
bool IsBIP30Unspendable(const CBlockIndex &block_index)
Identifies blocks which coinbase output was subsequently overwritten in the UTXO set (see BIP30) ...
const CBlockIndex *SnapshotBase() EXCLUSIVE_LOCKS_REQUIRED(std::set< CBlockIndex *, node::CBlockIndexWorkComparator > setBlockIndexCandidates
The base of the snapshot this chainstate was created from.
void InvalidateBlock(ChainstateManager &chainman, const uint256 block_hash)
uint256 GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
Transaction is missing a witness.
Helper class that manages an interrupt flag, and allows a thread or signal to interrupt another threa...
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
void CheckBlockIndex()
Make various assertions about the state of the block index.
int32_t nVersion
block header
static bool ComputeUTXOStats(CCoinsView *view, CCoinsStats &stats, T hash_obj, const std::function< void()> &interruption_point)
Calculate statistics about the unspent transaction output set.
const CChainParams & GetParams() const
std::string get_filesystem_error_message(const fs::filesystem_error &e)
invalid by consensus rules (excluding any below reasons)
CSHA256 ScriptExecutionCacheHasher() const
Return a copy of the pre-initialized hasher.
static time_point now() noexcept
Return current system time or mocked time, if set.
const CTransaction * ptxTo
bool IsWellFormedPackage(const Package &txns, PackageValidationState &state, bool require_sorted)
Context-free package policy checks:
const arith_uint256 & MinimumChainWork() const
bool enforce_BIP94
Enforce BIP94 timewarp attack mitigation.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::vector< CTransactionRef > vtx
const ChainTxData & TxData() const
kernel::Notifications & m_notifications
the block's data didn't match the data committed to by the PoW
Data structure storing a fee and size, ordered by increasing fee/size.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
#define LogDebug(category,...)
static bool ContextualCheckBlockHeader(const CBlockHeader &block, BlockValidationState &state, BlockManager &blockman, const ChainstateManager &chainman, const CBlockIndex *pindexPrev) EXCLUSIVE_LOCKS_REQUIRED(
Context-dependent validity checks.
bool CheckInputScripts(const CTransaction &tx, TxValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData &txdata, ValidationCache &validation_cache, std::vector< CScriptCheck > *pvChecks=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Check whether all of this transaction's input scripts succeed.
#define LOCKS_EXCLUDED(...)
static SynchronizationState GetSynchronizationState(bool init, bool blockfiles_indexed)
std::set< CBlockIndex * > m_dirty_blockindex
Dirty block index entries.
unsigned int GetLegacySigOpCount(const CTransaction &tx)
Auxiliary functions for transaction validation (ideally should not be exposed)
#define LogPrintLevel_(category, level, should_ratelimit,...)
The block chain is a tree shaped structure starting with the genesis block at the root...
Undo information for a CBlock.
Serialized script, used inside transaction inputs and outputs.
int64_t descendant_size_vbytes
The maximum allowed size in virtual bytes of an entry and its descendants within a package...
Undo information for a CTransaction.
std::vector< PerBlockConnectTrace > blocksConnected
CCoinsView backed by the coin database (chainstate/)
static constexpr unsigned int MIN_STANDARD_TX_NONWITNESS_SIZE
The minimum non-witness size for transactions we're willing to relay/mine: one larger than 64...
const ChainstateManager & m_chainman
void PruneBlockIndexCandidates()
Delete all entries in setBlockIndexCandidates that are worse than the current tip.
const fs::path blocks_dir
uint64_t m_chain_tx_count
Used to populate the m_chain_tx_count value, which is used during BlockManager::LoadBlockIndex().
#define TRACEPOINT(context,...)
static const int32_t VERSIONBITS_TOP_BITS
What bits to set in version for versionbits blocks.
bool m_spent_outputs_ready
Whether m_spent_outputs is initialized.
void Uncache(const COutPoint &outpoint)
Removes the UTXO with the given outpoint from the cache, if it is not modified.
A block this one builds on is invalid.
int worker_threads_num
Number of script check worker threads. Zero means no parallel verification.
std::string ToString() const
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network) ...
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept, const std::optional< CFeeRate > &client_maxfeerate)
Validate (and maybe submit) a package to the mempool.
virtual std::optional< Coin > GetCoin(const COutPoint &outpoint) const
Retrieve the Coin (unspent transaction output) for a given outpoint.
uint256 GetRandHash() noexcept
Generate a random uint256.
static bool CheckInputsFromMempoolAndCache(const CTransaction &tx, TxValidationState &state, const CCoinsViewCache &view, const CTxMemPool &pool, unsigned int flags, PrecomputedTransactionData &txdata, CCoinsViewCache &coins_tip, ValidationCache &validation_cache) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Checks to avoid mempool polluting consensus critical paths since cached signature and script validity...
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
static constexpr std::chrono::hours DATABASE_WRITE_INTERVAL
Time to wait between writing blocks/block index to disk.
int ActiveHeight() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
bool RaiseValidity(enum BlockStatus nUpTo) EXCLUSIVE_LOCKS_REQUIRED(
Raise the validity level of this block index entry.
std::optional< std::string > PackageTRUCChecks(const CTransactionRef &ptx, int64_t vsize, const Package &package, const CTxMemPool::setEntries &mempool_ancestors)
Must be called for every transaction that is submitted within a package, even if not TRUC...
Application-specific storage settings.
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
bool m_checked_witness_commitment
Holds configuration for use during UTXO snapshot load and validation.
#define AssertLockNotHeld(cs)
bilingual_str ErrorString(const Result< T > &result)
bool AcceptBlock(const std::shared_ptr< const CBlock > &pblock, BlockValidationState &state, CBlockIndex **ppindex, bool fRequested, const FlatFilePos *dbp, bool *fNewBlock, bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Sufficiently validate a block for disk storage (and store on disk).
void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)
int MinBIP9WarningHeight
Don't warn about unknown BIP 9 activations below this height.
bool FlushChainstateBlockFile(int tip_height)
this node does not have a mempool so can't validate the transaction
A mutable version of CTransaction.
unsigned char * UCharCast(char *c)
uint32_t nRuleChangeActivationThreshold
Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period...
block timestamp was > 2 hours in the future (or our clock is bad)
size_t m_coinstip_cache_size_bytes
The cache size of the in-memory coins view.
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
Check if transaction is final and can be included in a block with the specified height and time...
bool CheckSequenceLocksAtTip(CBlockIndex *tip, const LockPoints &lock_points)
Check if transaction will be BIP68 final in the next block to be created on top of tip...
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE
The maximum allowed size for a serialized block, in bytes (only for buffer size limits) ...
Mutex m_chainstate_mutex
The ChainState Mutex A lock that must be held when modifying this ChainState - held in ActivateBestCh...
arith_uint256 GetBlockProof(const CBlockIndex &block)
static MempoolAcceptResult Failure(TxValidationState state)
size_t script_execution_cache_bytes
bool FatalError(Notifications ¬ifications, BlockValidationState &state, const bilingual_str &message)
static constexpr int64_t MAX_FUTURE_BLOCK_TIME
Maximum amount of time that a block timestamp is allowed to exceed the current time before the block ...
bool NotifyHeaderTip() LOCKS_EXCLUDED(GetMutex())
std::list< CTransactionRef > take()
Clear all data structures and return the list of transactions.
The basic transaction that is broadcasted on the network and contained in blocks. ...
void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
int nHeight
height of the entry in the chain. The genesis block has height 0
WarningBitsConditionChecker(const ChainstateManager &chainman, int bit)
std::optional< uint256 > SnapshotBlockhash() const
const Consensus::Params & GetConsensus() const
int64_t ancestor_count
The maximum allowed number of transactions in a package including the entry and its ancestors...
std::optional< std::pair< DiagramCheckError, std::string > > ImprovesFeerateDiagram(CTxMemPool::ChangeSet &changeset)
The replacement transaction must improve the feerate diagram of the mempool.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
std::vector< PerBlockConnectTrace > & GetBlocksConnected()
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
std::string GetRejectReason() const
full block available in blk*.dat
#define LOG_TIME_MILLIS_WITH_CATEGORY(end_msg, log_category)
static bool exists(const path &p)
CuckooCache::cache< uint256, SignatureCacheHasher > m_script_execution_cache
int GetWitnessCommitmentIndex(const CBlock &block)
Compute at which vout of the block's coinbase transaction the witness commitment occurs, or -1 if not found.
A hasher class for SHA-256.
int64_t GetTime()
DEPRECATED, see GetTime.
std::vector< CTxUndo > vtxundo
static int64_t GetBlockWeight(const CBlock &block)
std::optional< int32_t > check_block_index
std::optional< AssumeutxoData > AssumeutxoForHeight(int height) const
static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS
Used as the flags parameter to sequence and nLocktime checks in non-consensus code.
static const int32_t VERSIONBITS_NUM_BITS
Total bits available for versionbits.
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
bool CheckTransaction(const CTransaction &tx, TxValidationState &state)
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
bool PreciousBlock(BlockValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(bool InvalidateBlock(BlockValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(void SetBlockFailureFlags(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(voi ResetBlockFailureFlags)(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Mark a block as precious and reorganize.
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
const CBlockIndex * FindFork(const CBlockIndex *pindex) const
Find the last common block between this chain and a block index entry.
std::vector< CTransactionRef > AddTransactionsFromBlock(const std::vector< CTransactionRef > &vtx)
Add transactions from the block, iterating through vtx in reverse order.
CCoinsView that brings transactions from a mempool into view.
Tx already in mempool or conflicts with a tx in the chain (if it conflicts with another tx in mempool...
void ReportHeadersPresync(const arith_uint256 &work, int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
void removeForBlock(const std::vector< CTransactionRef > &vtx, unsigned int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(cs)
Called when a block is connected.
CHash256 & Write(Span< const unsigned char > input)
otherwise didn't meet our local policy rules
int32_t nBlockReverseSequenceId
Decreasing counter (used by subsequent preciousblock calls).
#define LOG_TIME_MILLIS_WITH_CATEGORY_MSG_ONCE(end_msg, log_category)
SignatureCache * m_signature_cache
bool Sync()
Push the modifications applied to this cache to its base while retaining the contents of this cache (...
unsigned int nTx
Number of transactions in this block.
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
static constexpr unsigned int EXTRA_DESCENDANT_TX_SIZE_LIMIT
An extra transaction can be added to a package, as long as it only has one ancestor and is no larger ...
static GenTxid Txid(const uint256 &hash)
CTxMemPool * GetMempool()
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
std::string ToString(const T &t)
Locale-independent version of std::to_string.
bool IsSnapshotValidated() const EXCLUSIVE_LOCKS_REQUIRED(
Is there a snapshot in use and has it been fully validated?
static constexpr std::chrono::hours DATABASE_FLUSH_INTERVAL
Time to wait between flushing chainstate to disk.
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it...
virtual InterruptResult blockTip(SynchronizationState state, CBlockIndex &index)
void UpdateCoins(const CTransaction &tx, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight)
#define Assert(val)
Identity function.
std::shared_ptr< Chain::Notifications > m_notifications
const Txid & GetHash() const LIFETIMEBOUND
bool m_checked_merkle_root
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
static MempoolAcceptResult Success(std::list< CTransactionRef > &&replaced_txns, int64_t vsize, CAmount fees, CFeeRate effective_feerate, const std::vector< Wtxid > &wtxids_fee_calculations)
void BlockChecked(const CBlock &, const BlockValidationState &)
static constexpr TransactionSerParams TX_WITH_WITNESS
static constexpr TransactionSerParams TX_NO_WITNESS
bool CheckSignetBlockSolution(const CBlock &block, const Consensus::Params &consensusParams)
Extract signature and check whether a block has a valid solution.
Used to track blocks whose transactions were applied to the UTXO state as a part of a single Activate...
bool ReadBlockUndo(CBlockUndo &blockundo, const CBlockIndex &index) const
static constexpr int64_t MAX_TIMEWARP
Maximum number of seconds that the timestamp of the first block of a difficulty adjustment period is ...
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
static constexpr CAmount COIN
The amount of satoshis in one BTC.
const uint256 * phashBlock
pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
PrecomputedTransactionData * txdata
Threshold condition checker that triggers when unknown versionbits are seen on the network...