LCOV - code coverage report
Current view: top level - src - validation.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 1866 2176 85.8 %
Date: 2025-04-02 01:23:23 Functions: 99 101 98.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2015 The Bitcoin developers
       3             : // Copyright (c) 2014-2015 The Dash developers
       4             : // Copyright (c) 2011-2013 The PPCoin developers
       5             : // Copyright (c) 2013-2014 The NovaCoin Developers
       6             : // Copyright (c) 2014-2018 The BlackCoin Developers
       7             : // Copyright (c) 2015-2022 The PIVX Core developers
       8             : // Distributed under the MIT software license, see the accompanying
       9             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
      10             : 
      11             : #include "validation.h"
      12             : 
      13             : #include "addrman.h"
      14             : #include "blocksignature.h"
      15             : #include "budget/budgetmanager.h"
      16             : #include "chainparams.h"
      17             : #include "checkpoints.h"
      18             : #include "checkqueue.h"
      19             : #include "consensus/consensus.h"
      20             : #include "consensus/merkle.h"
      21             : #include "consensus/tx_verify.h"
      22             : #include "consensus/validation.h"
      23             : #include "consensus/zerocoin_verify.h"
      24             : #include "evo/evodb.h"
      25             : #include "evo/specialtx_validation.h"
      26             : #include "flatfile.h"
      27             : #include "guiinterface.h"
      28             : #include "interfaces/handler.h"
      29             : #include "invalid.h"
      30             : #include "kernel.h"
      31             : #include "legacy/validation_zerocoin_legacy.h"
      32             : #include "llmq/quorums_chainlocks.h"
      33             : #include "masternode-payments.h"
      34             : #include "masternodeman.h"
      35             : #include "policy/policy.h"
      36             : #include "pow.h"
      37             : #include "reverse_iterate.h"
      38             : #include "script/sigcache.h"
      39             : #include "shutdown.h"
      40             : #include "spork.h"
      41             : #include "sporkdb.h"
      42             : #include "tiertwo/tiertwo_sync_state.h"
      43             : #include "txdb.h"
      44             : #include "undo.h"
      45             : #include "util/blockstatecatcher.h"
      46             : #include "util/system.h"
      47             : #include "util/validation.h"
      48             : #include "utilmoneystr.h"
      49             : #include "validationinterface.h"
      50             : #include "warnings.h"
      51             : #include "zpiv/zpivmodule.h"
      52             : 
      53             : #include <future>
      54             : 
      55             : #include <boost/algorithm/string/replace.hpp>
      56             : #include <boost/thread.hpp>
      57             : #include <atomic>
      58             : #include <queue>
      59             : 
      60             : 
      61             : #if defined(NDEBUG)
      62             : #error "PIVX cannot be compiled without assertions."
      63             : #endif
      64             : 
      65             : /**
      66             :  * Global state
      67             :  */
      68             : 
      69             : 
      70             : /**
      71             :  * Mutex to guard access to validation specific variables, such as reading
      72             :  * or changing the chainstate.
      73             :  *
      74             :  * This may also need to be locked when updating the transaction pool, e.g. on
      75             :  * AcceptToMemoryPool. See CTxMemPool::cs comment for details.
      76             :  *
      77             :  * The transaction pool has a separate lock to allow reading from it and the
      78             :  * chainstate at the same time.
      79             :  */
      80             : RecursiveMutex cs_main;
      81             : 
      82             : BlockMap mapBlockIndex;
      83             : PrevBlockMap mapPrevBlockIndex;
      84             : CChain chainActive;
      85             : CBlockIndex* pindexBestHeader = nullptr;
      86             : 
      87             : // Best block section
      88             : Mutex g_best_block_mutex;
      89             : std::condition_variable g_best_block_cv;
      90             : uint256 g_best_block;
      91             : int64_t g_best_block_time = 0;
      92             : 
      93             : int nScriptCheckThreads = 0;
      94             : std::atomic<bool> fImporting{false};
      95             : std::atomic<bool> fReindex{false};
      96             : bool fTxIndex = true;
      97             : bool fRequireStandard = true;
      98             : bool fCheckBlockIndex = false;
      99             : size_t nCoinCacheUsage = 5000 * 300;
     100             : 
     101             : /* If the tip is older than this (in seconds), the node is considered to be in initial block download. */
     102             : int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
     103             : 
     104             : /** Fees smaller than this (in upiv) are considered zero fee (for relaying, mining and transaction creation)
     105             :  * We are ~100 times smaller then bitcoin now (2015-06-23), set minRelayTxFee only 10 times higher
     106             :  * so it's still 10 times lower comparing to bitcoin.
     107             :  */
     108             : CFeeRate minRelayTxFee = CFeeRate(10000);
     109             : 
     110             : CTxMemPool mempool(::minRelayTxFee);
     111             : 
     112             : std::map<uint256, int64_t> mapRejectedBlocks;
     113             : 
     114             : CMoneySupply MoneySupply;
     115             : 
     116             : static void CheckBlockIndex();
     117             : 
     118             : /** Constant stuff for coinbase transactions we create: */
     119             : CScript COINBASE_FLAGS;
     120             : 
     121             : // Internal stuff
     122             : namespace
     123             : {
     124             : struct CBlockIndexWorkComparator {
     125    93818860 :     bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const
     126             :     {
     127             :         // First sort by most total work, ...
     128    93818860 :         if (pa->nChainWork > pb->nChainWork) return false;
     129    62356820 :         if (pa->nChainWork < pb->nChainWork) return true;
     130             : 
     131             :         // ... then by earliest time received, ...
     132      493823 :         if (pa->nSequenceId < pb->nSequenceId) return false;
     133      493293 :         if (pa->nSequenceId > pb->nSequenceId) return true;
     134             : 
     135             :         // Use pointer address as tie breaker (should only happen with blocks
     136             :         // loaded from disk, as those all have id 0).
     137      492846 :         if (pa < pb) return false;
     138      492787 :         if (pa > pb) return true;
     139             : 
     140             :         // Identical blocks.
     141             :         return false;
     142             :     }
     143             : };
     144             : 
     145             : CBlockIndex* pindexBestInvalid;
     146             : 
     147             : /**
     148             :  * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and
     149             :  * as good as our current tip or better. Entries may be failed, though.
     150             :  */
     151             : std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates;
     152             : 
     153             : /**
     154             :  * the ChainState Mutex
     155             :  * A lock that must be held when modifying this ChainState - held in ActivateBestChain()
     156             :  */
     157             : Mutex m_cs_chainstate;
     158             : 
     159             : /** All pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions. */
     160             : std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
     161             : 
     162             : RecursiveMutex cs_LastBlockFile;
     163             : std::vector<CBlockFileInfo> vinfoBlockFile;
     164             : int nLastBlockFile = 0;
     165             : 
     166             : /**
     167             :      * Every received block is assigned a unique and increasing identifier, so we
     168             :      * know which one to give priority in case of a fork.
     169             :      */
     170             : RecursiveMutex cs_nBlockSequenceId;
     171             : /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
     172             : uint32_t nBlockSequenceId = 1;
     173             : 
     174             : /** Dirty block index entries. */
     175             : std::set<CBlockIndex*> setDirtyBlockIndex;
     176             : 
     177             : /** Dirty block file entries. */
     178             : std::set<int> setDirtyFileInfo;
     179             : } // anon namespace
     180             : 
     181        1524 : CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator)
     182             : {
     183        1524 :     AssertLockHeld(cs_main);
     184             :     // Find the first block the caller has in the main chain
     185        2718 :     for (const uint256& hash : locator.vHave) {
     186        2417 :         CBlockIndex* pindex = LookupBlockIndex(hash);
     187        3711 :         if (pindex && chain.Contains(pindex)) {
     188        1223 :             return pindex;
     189             :         }
     190             :     }
     191         301 :     return chain.Genesis();
     192             : }
     193             : 
     194        1049 : CBlockIndex* GetChainTip()
     195             : {
     196        2098 :     LOCK(cs_main);
     197        2098 :     CBlockIndex* p = chainActive.Tip();
     198        1049 :     if (!p)
     199             :         return nullptr;
     200             :     // Do not pass in the chain active tip, because it can change.
     201             :     // Instead pass the blockindex directly from mapblockindex, which is const
     202        1049 :     return mapBlockIndex.at(p->GetBlockHash());
     203             : }
     204             : 
     205             : std::unique_ptr<CCoinsViewDB> pcoinsdbview;
     206             : std::unique_ptr<CCoinsViewCache> pcoinsTip;
     207             : std::unique_ptr<CBlockTreeDB> pblocktree;
     208             : std::unique_ptr<CZerocoinDB> zerocoinDB;
     209             : std::unique_ptr<CSporkDB> pSporkDB;
     210             : std::unique_ptr<AccumulatorCache> accumulatorCache;
     211             : 
     212             : enum FlushStateMode {
     213             :     FLUSH_STATE_NONE,
     214             :     FLUSH_STATE_IF_NEEDED,
     215             :     FLUSH_STATE_PERIODIC,
     216             :     FLUSH_STATE_ALWAYS
     217             : };
     218             : 
     219             : // See definition for documentation
     220             : bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode);
     221             : static FlatFileSeq BlockFileSeq();
     222             : static FlatFileSeq UndoFileSeq();
     223             : 
     224     1172837 : bool CheckFinalTx(const CTransactionRef& tx, int flags)
     225             : {
     226     1172837 :     AssertLockHeld(cs_main);
     227             : 
     228             :     // By convention a negative value for flags indicates that the
     229             :     // current network-enforced consensus rules should be used. In
     230             :     // a future soft-fork scenario that would mean checking which
     231             :     // rules would be enforced for the next block and setting the
     232             :     // appropriate flags. At the present time no soft-forks are
     233             :     // scheduled, so no flags are set.
     234     1172837 :     flags = std::max(flags, 0);
     235             : 
     236             :     // CheckFinalTx() uses chainActive.Height()+1 to evaluate
     237             :     // nLockTime because when IsFinalTx() is called within
     238             :     // CBlock::AcceptBlock(), the height of the block *being*
     239             :     // evaluated is what is used. Thus if we want to know if a
     240             :     // transaction can be part of the *next* block, we need to call
     241             :     // IsFinalTx() with one more than chainActive.Height().
     242     1172837 :     const int nBlockHeight = chainActive.Height() + 1;
     243             : 
     244             :     // BIP113 will require that time-locked transactions have nLockTime set to
     245             :     // less than the median time of the previous block they're contained in.
     246             :     // When the next block is created its previous block will be the current
     247             :     // chain tip, so we use that to calculate the median time passed to
     248             :     // IsFinalTx() if LOCKTIME_MEDIAN_TIME_PAST is set.
     249     1365849 :     const int64_t nBlockTime = (flags & LOCKTIME_MEDIAN_TIME_PAST) ? chainActive.Tip()->GetMedianTimePast() : GetAdjustedTime();
     250             : 
     251     1172837 :     return IsFinalTx(tx, nBlockHeight, nBlockTime);
     252             : }
     253             : 
     254      119359 : void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) {
     255      119359 :     int expired = pool.Expire(GetTime() - age);
     256      119359 :     if (expired != 0)
     257           0 :         LogPrint(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired);
     258             : 
     259      119359 :     std::vector<COutPoint> vNoSpendsRemaining;
     260      119359 :     pool.TrimToSize(limit, &vNoSpendsRemaining);
     261      119359 :     for (const COutPoint& removed: vNoSpendsRemaining)
     262           0 :         pcoinsTip->Uncache(removed);
     263      119359 : }
     264             : 
     265      149669 : CAmount GetMinRelayFee(const CTransaction& tx, const CTxMemPool& pool, unsigned int nBytes)
     266             : {
     267      149669 :     if (tx.IsShieldedTx()) {
     268        2179 :         return GetShieldedTxMinFee(tx);
     269             :     }
     270      147490 :     uint256 hash = tx.GetHash();
     271      147490 :     CAmount nFeeDelta = 0;
     272      147490 :     pool.ApplyDelta(hash, nFeeDelta);
     273      147490 :     if (nFeeDelta > 0)
     274             :         return 0;
     275             : 
     276      147489 :     return GetMinRelayFee(nBytes);
     277             : }
     278             : 
     279      250537 : CAmount GetMinRelayFee(unsigned int nBytes)
     280             : {
     281      250537 :     CAmount nMinFee = ::minRelayTxFee.GetFee(nBytes);
     282      250537 :     if (!Params().GetConsensus().MoneyRange(nMinFee)) {
     283           0 :         nMinFee = Params().GetConsensus().nMaxMoneyOut;
     284             :     }
     285      250537 :     return nMinFee;
     286             : }
     287             : 
     288        5397 : CAmount GetShieldedTxMinFee(const CTransaction& tx)
     289             : {
     290        5397 :     assert (tx.IsShieldedTx());
     291        5397 :     unsigned int K = DEFAULT_SHIELDEDTXFEE_K;   // Fixed (100) for now
     292        5397 :     CAmount nMinFee = ::minRelayTxFee.GetFee(tx.GetTotalSize()) * K;
     293        5397 :     if (!Params().GetConsensus().MoneyRange(nMinFee))
     294           0 :         nMinFee = Params().GetConsensus().nMaxMoneyOut;
     295        5397 :     return nMinFee;
     296             : }
     297             : 
     298             : /* Make mempool consistent after a reorg, by re-adding or recursively erasing
     299             :  * disconnected block transactions from the mempool, and also removing any
     300             :  * other transactions from the mempool that are no longer valid given the new
     301             :  * tip/height.
     302             :  *
     303             :  * Note: we assume that disconnectpool only contains transactions that are NOT
     304             :  * confirmed in the current chain nor already in the mempool (otherwise,
     305             :  * in-mempool descendants of such transactions would be removed).
     306             :  *
     307             :  * Passing fAddToMempool=false will skip trying to add the transactions back,
     308             :  * and instead just erase from the mempool as needed.
     309             :  */
     310             : 
     311          63 : static void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool fAddToMempool) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
     312             : {
     313          63 :     AssertLockHeld(cs_main);
     314          63 :     AssertLockHeld(mempool.cs);
     315          63 :     std::vector<uint256> vHashUpdate;
     316             :     // disconnectpool's insertion_order index sorts the entries from
     317             :     // oldest to newest, but the oldest entry will be the last tx from the
     318             :     // latest mined block that was disconnected.
     319             :     // Iterate disconnectpool in reverse, so that we add transactions
     320             :     // back to the mempool starting with the earliest transaction that had
     321             :     // been previously seen in a block.
     322          63 :     auto it = disconnectpool.queuedTx.get<insertion_order>().rbegin();
     323       39939 :     while (it != disconnectpool.queuedTx.get<insertion_order>().rend()) {
     324             :         // if we are resurrecting a ProReg tx, we need to evict any special transaction that
     325             :         // depends on it (which would not be accepted in the mempool, with the current chain)
     326       79752 :         if ((*it)->IsProRegTx()) {
     327           8 :             mempool.removeProTxReferences((*it)->GetHash(), MemPoolRemovalReason::REORG);
     328             :         }
     329             :         // ignore validation errors in resurrected transactions
     330       39876 :         CValidationState stateDummy;
     331      158993 :         if (!fAddToMempool || (*it)->IsCoinBase() || (*it)->IsCoinStake() ||
     332       39606 :                 !AcceptToMemoryPool(mempool, stateDummy, *it, false, nullptr, true)) {
     333             :             // If the transaction doesn't make it in to the mempool, remove any
     334             :             // transactions that depend on it (which would now be orphans).
     335       24220 :             mempool.removeRecursive(**it, MemPoolRemovalReason::REORG);
     336       55532 :         } else if (mempool.exists((*it)->GetHash())) {
     337       55532 :             vHashUpdate.emplace_back((*it)->GetHash());
     338             :         }
     339       79752 :         ++it;
     340             :     }
     341          63 :     disconnectpool.queuedTx.clear();
     342             :     // AcceptToMemoryPool/addUnchecked all assume that new mempool entries have
     343             :     // no in-mempool children, which is generally not true when adding
     344             :     // previously-confirmed transactions back to the mempool.
     345             :     // UpdateTransactionsFromBlock finds descendants of any transactions in
     346             :     // the disconnectpool that were added back and cleans up the mempool state.
     347          63 :     mempool.UpdateTransactionsFromBlock(vHashUpdate);
     348             : 
     349             :     // We also need to remove any now-immature transactions
     350         126 :     mempool.removeForReorg(pcoinsTip.get(), chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
     351             :     // Re-limit mempool size, in case we added any transactions
     352         189 :     LimitMempoolSize(mempool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000,
     353         126 :                               gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
     354          63 : }
     355             : 
     356      147065 : static bool IsCurrentForFeeEstimation()
     357             : {
     358      147065 :     AssertLockHeld(cs_main);
     359      147065 :     if (IsInitialBlockDownload())
     360             :         return false;
     361      294000 :     if (chainActive.Tip()->GetBlockTime() < (GetTime() - MAX_FEE_ESTIMATION_TIP_AGE))
     362             :         return false;
     363      146909 :     if (chainActive.Height() < pindexBestHeader->nHeight - 1)
     364       27670 :         return false;
     365             :     return true;
     366             : }
     367             : 
     368      159079 : static bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const CTransactionRef& _tx, bool fLimitFree,
     369             :                               bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, bool fRejectAbsurdFee, bool ignoreFees,
     370             :                               std::vector<COutPoint>& coins_to_uncache) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
     371             : {
     372      159079 :     AssertLockHeld(cs_main);
     373      159079 :     const CTransaction& tx = *_tx;
     374             : 
     375             :     // Coinbase is only valid in a block, not as a loose transaction
     376      159079 :     if (tx.IsCoinBase())
     377           0 :         return state.DoS(100, false, REJECT_INVALID, "coinbase");
     378             : 
     379             :     // Coinstake is also only valid in a block, not as a loose transaction
     380      159079 :     if (tx.IsCoinStake())
     381           0 :         return state.DoS(100, false, REJECT_INVALID, "coinstake");
     382             : 
     383             :     // LLMQ final commitment too, not valid as a loose transaction
     384      159079 :     if (tx.IsQuorumCommitmentTx())
     385          20 :         return state.DoS(100, false, REJECT_INVALID, "llmqcomm");
     386             : 
     387      159069 :     if (pfMissingInputs)
     388      119443 :         *pfMissingInputs = false;
     389             : 
     390             :     // Check maintenance mode
     391      159069 :     if (sporkManager.IsSporkActive(SPORK_20_SAPLING_MAINTENANCE) && tx.IsShieldedTx())
     392           3 :         return state.DoS(10, error("%s : Shielded transactions are temporarily disabled for maintenance",
     393             :                 __func__), REJECT_INVALID, "bad-tx-sapling-maintenance");
     394             : 
     395      159068 :     const CChainParams& params = Params();
     396      159068 :     const Consensus::Params& consensus = params.GetConsensus();
     397      159068 :     int chainHeight = chainActive.Height();
     398             : 
     399             :     // Check transaction
     400      159068 :     bool fColdStakingActive = !sporkManager.IsSporkActive(SPORK_19_COLDSTAKING_MAINTENANCE);
     401      159068 :     if (!CheckTransaction(tx, state, fColdStakingActive))
     402           3 :         return error("%s : transaction checks for %s failed with %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));
     403             : 
     404      159067 :     int nextBlockHeight = chainHeight + 1;
     405             :     // Check transaction contextually against consensus rules at block height
     406      159067 :     if (!ContextualCheckTransaction(_tx, state, params, nextBlockHeight, false /* isMined */, IsInitialBlockDownload())) {
     407           4 :         return error("AcceptToMemoryPool: ContextualCheckTransaction failed");
     408             :     }
     409             : 
     410      159063 :     if (pool.existsProviderTxConflict(tx)) {
     411          10 :         return state.DoS(0, false, REJECT_DUPLICATE, "protx-dup");
     412             :     }
     413             : 
     414             :     // Only accept nLockTime-using transactions that can be mined in the next
     415             :     // block; we don't want our mempool filled up with transactions that can't
     416             :     // be mined yet.
     417      159058 :     if (!CheckFinalTx(_tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
     418           4 :         return state.DoS(0, false, REJECT_NONSTANDARD, "non-final");
     419             : 
     420             :     // Rather not work on nonstandard transactions
     421      318135 :     std::string reason;
     422      159056 :     if (fRequireStandard && !IsStandardTx(_tx, nextBlockHeight, reason))
     423           3 :         return state.DoS(0, false, REJECT_NONSTANDARD, reason);
     424             :     // is it already in the memory pool?
     425      159055 :     const uint256& hash = tx.GetHash();
     426      159055 :     if (pool.exists(hash)) {
     427           0 :         return state.Invalid(false, REJECT_ALREADY_KNOWN, "txn-already-in-mempool");
     428             :     }
     429             : 
     430             :     // Check for conflicts with in-memory transactions
     431             : 
     432      159055 :     {
     433      159055 :         LOCK(pool.cs); // protect pool.mapNextTx
     434      462903 :         for (const auto& in : tx.vin) {
     435      303849 :             COutPoint outpoint = in.prevout;
     436      607697 :             if (pool.mapNextTx.count(outpoint)) {
     437             :                 // Disable replacement feature for now
     438           2 :                 return state.Invalid(false, REJECT_CONFLICT, "txn-mempool-conflict");
     439             :             }
     440             :         }
     441             :     }
     442             : 
     443             :     // Check sapling nullifiers
     444      159054 :     if (tx.IsShieldedTx()) {
     445        2320 :         for (const auto& sd : tx.sapData->vShieldedSpend) {
     446         140 :             if (pool.nullifierExists(sd.nullifier))
     447           4 :                 return state.Invalid(false, REJECT_INVALID, "bad-txns-nullifier-double-spent");
     448             :         }
     449             :     }
     450             : 
     451      159052 :     {
     452           0 :         CCoinsView dummy;
     453      306117 :         CCoinsViewCache view(&dummy);
     454             : 
     455      159052 :         CAmount nValueIn = 0;
     456             : 
     457      306117 :         LOCK(pool.cs);
     458      306117 :         CCoinsViewMemPool viewMemPool(pcoinsTip.get(), pool);
     459      159052 :         view.SetBackend(viewMemPool);
     460             : 
     461             :         // do we already have it?
     462      601972 :         for (size_t out = 0; out < tx.vout.size(); out++) {
     463      442922 :             COutPoint outpoint(hash, out);
     464      442922 :             bool had_coin_in_cache = pcoinsTip->HaveCoinInCache(outpoint);
     465      442922 :             if (view.HaveCoin(outpoint)) {
     466           2 :                 if (!had_coin_in_cache) {
     467           0 :                     coins_to_uncache.push_back(outpoint);
     468             :                 }
     469           4 :                 return state.Invalid(false, REJECT_ALREADY_KNOWN, "txn-already-known");
     470             :             }
     471             :         }
     472             : 
     473             :         // do all inputs exist?
     474      445491 :         for (const CTxIn& txin : tx.vin) {
     475      295818 :             if (!pcoinsTip->HaveCoinInCache(txin.prevout)) {
     476       40770 :                 coins_to_uncache.push_back(txin.prevout);
     477             :             }
     478      295818 :             if (!view.HaveCoin(txin.prevout)) {
     479        9377 :                 if (pfMissingInputs) {
     480         134 :                     *pfMissingInputs = true;
     481             :                 }
     482        9377 :                 return false; // fMissingInputs and !state.IsInvalid() is used to detect this condition, don't set state.Invalid()
     483             :             }
     484             :         }
     485             : 
     486             :         // Sapling: are the sapling spends' requirements met in tx(valid anchors/nullifiers)?
     487      149673 :         if (!view.HaveShieldedRequirements(tx))
     488           2 :             return state.Invalid(error("AcceptToMemoryPool: shielded requirements not met"),
     489             :                                  REJECT_DUPLICATE, "bad-txns-shielded-requirements-not-met");
     490             : 
     491      299344 :         if (!CheckSpecialTx(tx, chainActive.Tip(), &view, state)) {
     492             :             // pass the state returned by the function above
     493             :             return false;
     494             :         }
     495             : 
     496             :         // Bring the best block into scope
     497      149671 :         view.GetBestBlock();
     498             : 
     499      149671 :         nValueIn = view.GetValueIn(tx);
     500             : 
     501             :         // we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool
     502      149671 :         view.SetBackend(dummy);
     503             : 
     504             :         // Check for non-standard pay-to-script-hash in inputs
     505      149671 :         if (fRequireStandard && !AreInputsStandard(tx, view))
     506           0 :             return state.Invalid(false, REJECT_NONSTANDARD, "bad-txns-nonstandard-inputs");
     507             : 
     508             :         // Check that the transaction doesn't have an excessive number of
     509             :         // sigops, making it impossible to mine. Since the coinbase transaction
     510             :         // itself can contain sigops MAX_TX_SIGOPS is less than
     511             :         // MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
     512             :         // merely non-standard transaction.
     513      149671 :         unsigned int nSigOps = GetLegacySigOpCount(tx);
     514      149671 :         unsigned int nMaxSigOps = MAX_TX_SIGOPS_CURRENT;
     515      149671 :         nSigOps += GetP2SHSigOpCount(tx, view);
     516      149671 :         if(nSigOps > nMaxSigOps)
     517           6 :             return state.DoS(0, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops", false,
     518           4 :                 strprintf("%d > %d", nSigOps, nMaxSigOps));
     519             : 
     520      149669 :         CAmount nValueOut = tx.GetValueOut();
     521      149669 :         CAmount nFees = nValueIn - nValueOut;
     522      149669 :         bool fSpendsCoinbaseOrCoinstake = false;
     523             : 
     524             :         // Keep track of transactions that spend a coinbase, which we re-scan
     525             :         // during reorgs to ensure COINBASE_MATURITY is still met.
     526      431464 :         for (const CTxIn &txin : tx.vin) {
     527      284816 :             const Coin &coin = view.AccessCoin(txin.prevout);
     528      284816 :             if (coin.IsCoinBase() || coin.IsCoinStake()) {
     529             :                 fSpendsCoinbaseOrCoinstake = true;
     530             :                 break;
     531             :             }
     532             :         }
     533             : 
     534      149669 :         CTxMemPoolEntry entry(_tx, nFees, nAcceptTime, chainHeight,
     535      296734 :                               fSpendsCoinbaseOrCoinstake, nSigOps);
     536      149669 :         unsigned int nSize = entry.GetTxSize();
     537             : 
     538             :         // Don't accept it if it can't get into a block
     539      149669 :         if (!ignoreFees) {
     540      149669 :             const CAmount txMinFee = GetMinRelayFee(tx, pool, nSize);
     541      149669 :             if (fLimitFree && nFees < txMinFee) {
     542          21 :                 return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient fee", false,
     543          14 :                     strprintf("%d < %d", nFees, txMinFee));
     544             :             }
     545             : 
     546             :             // No transactions are allowed below minRelayTxFee except from disconnected blocks
     547      149662 :             if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize)) {
     548           0 :                 return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "min relay fee not met");
     549             :             }
     550             :         }
     551             : 
     552      149662 :         if (fRejectAbsurdFee) {
     553      208248 :             const CAmount nMaxFee = tx.IsShieldedTx() ? GetShieldedTxMinFee(tx) * 100 :
     554      103046 :                                                         GetMinRelayFee(nSize) * 10000;
     555      104124 :             if (nFees > nMaxFee)
     556           0 :                 return state.Invalid(false, REJECT_HIGHFEE, "absurdly-high-fee",
     557           0 :                                      strprintf("%d > %d", nFees, nMaxFee));
     558             :         }
     559             : 
     560             :         // Calculate in-mempool ancestors, up to a limit.
     561      296727 :         CTxMemPool::setEntries setAncestors;
     562      149662 :         size_t nLimitAncestors = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
     563      149662 :         size_t nLimitAncestorSize = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000;
     564      149662 :         size_t nLimitDescendants = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
     565      149662 :         size_t nLimitDescendantSize = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000;
     566      296727 :         std::string errString;
     567      149662 :         if (!pool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) {
     568        7749 :             return state.DoS(0, error("%s : %s", __func__, errString), REJECT_NONSTANDARD, "too-long-mempool-chain", false);
     569             :         }
     570             : 
     571      147079 :         bool fCLTVIsActivated = consensus.NetworkUpgradeActive(chainHeight, Consensus::UPGRADE_BIP65);
     572      147079 :         bool exchangeAddrActivated = consensus.NetworkUpgradeActive(chainHeight, Consensus::UPGRADE_V5_6);
     573             :         // Check against previous transactions
     574             :         // This is done last to help prevent CPU exhaustion denial-of-service attacks.
     575      147079 :         int flags = STANDARD_SCRIPT_VERIFY_FLAGS;
     576      147079 :         if (fCLTVIsActivated)
     577      147079 :             flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
     578      147079 :         if (exchangeAddrActivated)
     579      130125 :             flags |= SCRIPT_VERIFY_EXCHANGEADDR;
     580             : 
     581             : 
     582      147079 :         PrecomputedTransactionData precomTxData(tx);
     583      147079 :         if (!CheckInputs(tx, state, view, true, flags, true, precomTxData)) {
     584             :             return false;
     585             :         }
     586             : 
     587             :         // Check again against just the consensus-critical mandatory script
     588             :         // verification flags, in case of bugs in the standard flags that cause
     589             :         // transactions to pass as valid when they're actually invalid. For
     590             :         // instance the STRICTENC flag was incorrectly allowing certain
     591             :         // CHECKSIG NOT scripts to pass, even though they were invalid.
     592             :         //
     593             :         // There is a similar check in CreateNewBlock() to prevent creating
     594             :         // invalid blocks, however allowing such transactions into the mempool
     595             :         // can be exploited as a DoS attack.
     596      147065 :         flags = MANDATORY_SCRIPT_VERIFY_FLAGS;
     597      147065 :         if (fCLTVIsActivated)
     598      147065 :             flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
     599      147065 :         if (exchangeAddrActivated)
     600      130122 :             flags |= SCRIPT_VERIFY_EXCHANGEADDR;
     601      147065 :         if (!CheckInputs(tx, state, view, true, flags, true, precomTxData)) {
     602           0 :             return error("%s: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s, %s",
     603           0 :                     __func__, hash.ToString(), FormatStateMessage(state));
     604             :         }
     605             :         // todo: pool.removeStaged for all conflicting entries
     606             : 
     607             :         // This transaction should only count for fee estimation if
     608             :         // the node is not behind and it is not dependent on any other
     609             :         // transactions in the mempool
     610      147065 :         bool validForFeeEstimation = IsCurrentForFeeEstimation() && pool.HasNoInputsOf(tx);
     611             : 
     612             :         // Store transaction in memory
     613      147065 :         pool.addUnchecked(hash, entry, setAncestors, validForFeeEstimation);
     614             : 
     615             :         // trim mempool and check if tx was trimmed
     616      147065 :         if (!fOverrideMempoolLimit) {
     617      238592 :             LimitMempoolSize(pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
     618      119296 :             if (!pool.exists(hash))
     619           0 :                 return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool full");
     620             :         }
     621             : 
     622      147065 :         pool.TrimToSize(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
     623      147065 :         if (!pool.exists(tx.GetHash()))
     624           0 :             return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool full");
     625             :     }
     626             : 
     627      147065 :     GetMainSignals().TransactionAddedToMempool(_tx);
     628             : 
     629             :     return true;
     630             : }
     631             : 
     632      159079 : bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef& tx, bool fLimitFree,
     633             :                         bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, bool fRejectAbsurdFee, bool fIgnoreFees)
     634             : {
     635      159079 :     AssertLockHeld(cs_main);
     636             : 
     637      159079 :     std::vector<COutPoint> coins_to_uncache;
     638      159079 :     bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, fOverrideMempoolLimit, fRejectAbsurdFee, fIgnoreFees, coins_to_uncache);
     639      159079 :     if (!res) {
     640       26721 :         for (const COutPoint& outpoint: coins_to_uncache)
     641       14707 :             pcoinsTip->Uncache(outpoint);
     642             :     }
     643             :     // After we've (potentially) uncached entries, ensure our coins cache is still within its size limits
     644      318158 :     CValidationState stateDummy;
     645      159079 :     FlushStateToDisk(stateDummy, FLUSH_STATE_PERIODIC);
     646      318158 :     return res;
     647             : }
     648             : 
     649      159056 : bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransactionRef& tx,
     650             :                         bool fLimitFree, bool* pfMissingInputs, bool fOverrideMempoolLimit,
     651             :                         bool fRejectInsaneFee, bool ignoreFees)
     652             : {
     653      159056 :     return AcceptToMemoryPoolWithTime(pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), fOverrideMempoolLimit, fRejectInsaneFee, ignoreFees);
     654             : }
     655             : 
     656           0 : bool GetOutput(const uint256& hash, unsigned int index, CValidationState& state, CTxOut& out)
     657             : {
     658           0 :     CTransactionRef txPrev;
     659           0 :     uint256 hashBlock;
     660           0 :     if (!GetTransaction(hash, txPrev, hashBlock, true)) {
     661           0 :         return state.DoS(100, error("Output not found"));
     662             :     }
     663           0 :     if (index > txPrev->vout.size()) {
     664           0 :         return state.DoS(100, error("Output not found, invalid index %d for %s",index, hash.GetHex()));
     665             :     }
     666           0 :     out = txPrev->vout[index];
     667           0 :     return true;
     668             : }
     669             : 
     670             : /** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */
     671      204226 : bool GetTransaction(const uint256& hash, CTransactionRef& txOut, uint256& hashBlock, bool fAllowSlow, CBlockIndex* blockIndex)
     672             : {
     673      204226 :     CBlockIndex* pindexSlow = blockIndex;
     674             : 
     675      408452 :     LOCK(cs_main);
     676             : 
     677      204226 :     if (!blockIndex) {
     678             : 
     679      204223 :         CTransactionRef ptx = mempool.get(hash);
     680      204223 :         if (ptx) {
     681         160 :             txOut = ptx;
     682      204383 :             return true;
     683             :         }
     684             : 
     685      204063 :         if (fTxIndex) {
     686      204063 :             CDiskTxPos postx;
     687      204063 :             if (pblocktree->ReadTxIndex(hash, postx)) {
     688      408104 :                 CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
     689      204052 :                 if (file.IsNull())
     690           0 :                     return error("%s: OpenBlockFile failed", __func__);
     691      204052 :                 CBlockHeader header;
     692      204052 :                 try {
     693      204052 :                     file >> header;
     694      204052 :                     fseek(file.Get(), postx.nTxOffset, SEEK_CUR);
     695      204052 :                     file >> txOut;
     696           0 :                 } catch (const std::exception& e) {
     697           0 :                     return error("%s : Deserialize or I/O error - %s", __func__, e.what());
     698             :                 }
     699      204052 :                 hashBlock = header.GetHash();
     700      204052 :                 if (txOut->GetHash() != hash)
     701           0 :                     return error("%s : txid mismatch", __func__);
     702             :                 return true;
     703             :             }
     704             : 
     705             :             // transaction not found in the index, nothing more can be done
     706             :             return false;
     707             :         }
     708             : 
     709           0 :         if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it
     710           0 :             const Coin& coin = AccessByTxid(*pcoinsTip, hash);
     711           0 :             if (!coin.IsSpent()) pindexSlow = chainActive[coin.nHeight];
     712             :         }
     713             :     }
     714             : 
     715           3 :     if (pindexSlow) {
     716           4 :         CBlock block;
     717           3 :         if (ReadBlockFromDisk(block, pindexSlow)) {
     718           6 :             for (const auto& tx : block.vtx) {
     719           5 :                 if (tx->GetHash() == hash) {
     720           2 :                     txOut = tx;
     721           2 :                     hashBlock = pindexSlow->GetBlockHash();
     722           2 :                     return true;
     723             :                 }
     724             :             }
     725             :         }
     726             :     }
     727             : 
     728             :     return false;
     729             : }
     730             : 
     731             : 
     732             : //////////////////////////////////////////////////////////////////////////////
     733             : //
     734             : // CBlock and CBlockIndex
     735             : //
     736             : 
     737       40810 : bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos)
     738             : {
     739             :     // Open history file to append
     740       81620 :     CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
     741       40810 :     if (fileout.IsNull())
     742           0 :         return error("WriteBlockToDisk : OpenBlockFile failed");
     743             : 
     744             :     // Write index header
     745       40810 :     unsigned int nSize = GetSerializeSize(block, fileout.GetVersion());
     746       40810 :     fileout << Params().MessageStart() << nSize;
     747             : 
     748             :     // Write block
     749       40810 :     long fileOutPos = ftell(fileout.Get());
     750       40810 :     if (fileOutPos < 0)
     751           0 :         return error("WriteBlockToDisk : ftell failed");
     752       40810 :     pos.nPos = (unsigned int)fileOutPos;
     753       40810 :     fileout << block;
     754             : 
     755             :     return true;
     756             : }
     757             : 
     758       82272 : bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos)
     759             : {
     760       82272 :     block.SetNull();
     761             : 
     762             :     // Open history file to read
     763      164544 :     CAutoFile filein(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION);
     764       82272 :     if (filein.IsNull())
     765           7 :         return error("ReadBlockFromDisk : OpenBlockFile failed");
     766             : 
     767             :     // Read block
     768       82265 :     try {
     769       82265 :         filein >> block;
     770           0 :     } catch (const std::exception& e) {
     771           0 :         return error("%s : Deserialize or I/O error - %s", __func__, e.what());
     772             :     }
     773             : 
     774             :     // Check the header
     775       82265 :     if (block.IsProofOfWork()) {
     776       73676 :         if (!CheckProofOfWork(block.GetHash(), block.nBits))
     777           0 :             return error("ReadBlockFromDisk : Errors in block header");
     778             :     }
     779             : 
     780             :     return true;
     781             : }
     782             : 
     783       82272 : bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
     784             : {
     785      246816 :     FlatFilePos blockPos = WITH_LOCK(cs_main, return pindex->GetBlockPos(); );
     786       82272 :     if (!ReadBlockFromDisk(block, blockPos)) {
     787             :         return false;
     788             :     }
     789       82265 :     if (block.GetHash() != pindex->GetBlockHash()) {
     790           0 :         LogPrintf("%s : block=%s index=%s\n", __func__, block.GetHash().GetHex(), pindex->GetBlockHash().GetHex());
     791           0 :         return error("ReadBlockFromDisk(CBlock&, CBlockIndex*) : GetHash() doesn't match index");
     792             :     }
     793             :     return true;
     794             : }
     795             : 
     796             : 
     797           0 : double ConvertBitsToDouble(unsigned int nBits)
     798             : {
     799           0 :     int nShift = (nBits >> 24) & 0xff;
     800             : 
     801           0 :     double dDiff =
     802           0 :         (double)0x0000ffff / (double)(nBits & 0x00ffffff);
     803             : 
     804           0 :     while (nShift < 29) {
     805           0 :         dDiff *= 256.0;
     806           0 :         nShift++;
     807             :     }
     808           0 :     while (nShift > 29) {
     809           0 :         dDiff /= 256.0;
     810           0 :         nShift--;
     811             :     }
     812             : 
     813           0 :     return dDiff;
     814             : }
     815             : 
     816      359707 : CAmount GetBlockValue(int nHeight)
     817             : {
     818             :     // Set V5.5 upgrade block for regtest as well as testnet and mainnet
     819      359707 :     const int nLast = Params().GetConsensus().vUpgrades[Consensus::UPGRADE_V5_5].nActivationHeight;
     820             : 
     821             :     // Regtest block reward reduction schedule
     822      359707 :     if (Params().IsRegTestNet()) {
     823             :         // Reduce regtest block value after V5.5 upgrade
     824      100499 :         if (nHeight > nLast) return 10 * COIN;
     825       80761 :         return 250 * COIN;
     826             :     }
     827             :     // Testnet high-inflation blocks [2, 200] with value 250k PIV
     828      259208 :     const bool isTestnet = Params().IsTestnet();
     829      259208 :     if (isTestnet && nHeight < 201 && nHeight > 1) {
     830             :         return 250000 * COIN;
     831             :     }
     832             :     // Mainnet/Testnet block reward reduction schedule
     833      259207 :     const int nZerocoinV2 = Params().GetConsensus().vUpgrades[Consensus::UPGRADE_ZC_V2].nActivationHeight;
     834      259207 :     if (nHeight > nLast) return 10 * COIN;
     835      259205 :     if (nHeight > nZerocoinV2) return 5 * COIN;
     836      259201 :     if (nHeight > 648000) return 4.5 * COIN;
     837      259201 :     if (nHeight > 604800) return 9 * COIN;
     838      259201 :     if (nHeight > 561600) return 13.5 * COIN;
     839      259201 :     if (nHeight > 518400) return 18 * COIN;
     840      259201 :     if (nHeight > 475200) return 22.5 * COIN;
     841      259201 :     if (nHeight > 432000) return 27 * COIN;
     842      259201 :     if (nHeight > 388800) return 31.5 * COIN;
     843      259201 :     if (nHeight > 345600) return 36 * COIN;
     844      259201 :     if (nHeight > 302400) return 40.5 * COIN;
     845      259201 :     if (nHeight > 151200) return 45 * COIN;
     846      151201 :     if (nHeight > 86400) return 225 * COIN;
     847       86401 :     if (nHeight != 1) return 250 * COIN;
     848             :     // Premine for 6 masternodes at block 1
     849             :     return 60001 * COIN;
     850             : }
     851             : 
     852       14606 : int64_t GetMasternodePayment(int nHeight)
     853             : {
     854       14606 :     if (nHeight > Params().GetConsensus().vUpgrades[Consensus::UPGRADE_V5_5].nActivationHeight) {
     855       10432 :         return Params().GetConsensus().nNewMNBlockReward;
     856             :     }
     857             : 
     858             :     // Future: refactor function callers to use this line directly.
     859        4174 :     return Params().GetConsensus().nMNBlockReward;
     860             : }
     861             : 
     862     4629439 : bool IsInitialBlockDownload()
     863             : {
     864             :     // Once this function has returned false, it must remain false.
     865     4629439 :     static std::atomic<bool> latchToFalse{false};
     866             :     // Optimization: pre-test latch before taking the lock.
     867     4629439 :     if (latchToFalse.load(std::memory_order_relaxed))
     868             :         return false;
     869             : 
     870     4804374 :     LOCK(cs_main);
     871      174934 :     if (latchToFalse.load(std::memory_order_relaxed))
     872             :          return false;
     873      174934 :     const int chainHeight = chainActive.Height();
     874      174934 :     if (fImporting || fReindex || chainHeight < Checkpoints::GetTotalBlocksEstimate())
     875        2991 :         return true;
     876      171943 :     bool state = (chainHeight < pindexBestHeader->nHeight - 24 * 6 ||
     877      171943 :             pindexBestHeader->GetBlockTime() < GetTime() - nMaxTipAge);
     878         285 :     if (!state) {
     879         285 :         LogPrintf("Leaving InitialBlockDownload (latching to false)\n");
     880      174934 :         latchToFalse.store(true, std::memory_order_relaxed);
     881             :     }
     882             :     return state;
     883             : }
     884             : 
     885             : CBlockIndex *pindexBestForkTip = nullptr, *pindexBestForkBase = nullptr;
     886             : 
     887           2 : static void AlertNotify(const std::string& strMessage)
     888             : {
     889           2 :     uiInterface.NotifyAlertChanged();
     890           5 :     std::string strCmd = gArgs.GetArg("-alertnotify", "");
     891           2 :     if (strCmd.empty()) return;
     892             : 
     893             :     // Alert text should be plain ascii coming from a trusted source, but to
     894             :     // be safe we first strip anything not in safeChars, then add single quotes around
     895             :     // the whole string before passing it to the shell:
     896           2 :     std::string singleQuote("'");
     897           2 :     std::string safeStatus = SanitizeString(strMessage);
     898           2 :     safeStatus = singleQuote+safeStatus+singleQuote;
     899           1 :     boost::replace_all(strCmd, "%s", safeStatus);
     900             : 
     901           2 :     std::thread t(runCommand, strCmd);
     902           1 :     t.detach(); // thread runs free
     903             : }
     904             : 
     905       41345 : void CheckForkWarningConditions()
     906             : {
     907       41345 :     AssertLockHeld(cs_main);
     908             :     // Before we get past initial download, we cannot reliably alert about forks
     909             :     // (we assume we don't get stuck on a fork before the last checkpoint)
     910       41345 :     if (IsInitialBlockDownload())
     911             :         return;
     912             : 
     913       81908 :     const CBlockIndex* pChainTip = chainActive.Tip();
     914       40563 :     if (!pChainTip)
     915             :         return;
     916             : 
     917             :     // If our best fork is no longer within 72 blocks (+/- 3 hours if no one mines it)
     918             :     // of our head, drop it
     919       40563 :     if (pindexBestForkTip && pChainTip->nHeight - pindexBestForkTip->nHeight >= 72)
     920           0 :         pindexBestForkTip = nullptr;
     921             : 
     922       41119 :     if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > pChainTip->nChainWork + (GetBlockProof(*pChainTip) * 6))) {
     923           0 :         if (!GetfLargeWorkForkFound() && pindexBestForkBase) {
     924           0 :             if (pindexBestForkBase->phashBlock) {
     925           0 :                 std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") +
     926           0 :                                       pindexBestForkBase->phashBlock->ToString() + std::string("'");
     927           0 :                 AlertNotify(warning);
     928             :             }
     929             :         }
     930           0 :         if (pindexBestForkTip && pindexBestForkBase) {
     931           0 :             if (pindexBestForkBase->phashBlock) {
     932           0 :                 LogPrintf("CheckForkWarningConditions: Warning: Large valid fork found\n  forking the chain at height %d (%s)\n  lasting to height %d (%s).\nChain state database corruption likely.\n",
     933           0 :                     pindexBestForkBase->nHeight, pindexBestForkBase->phashBlock->ToString(),
     934           0 :                     pindexBestForkTip->nHeight, pindexBestForkTip->phashBlock->ToString());
     935           0 :                 SetfLargeWorkForkFound(true);
     936             :             }
     937             :         } else {
     938           0 :             LogPrintf("CheckForkWarningConditions: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n");
     939           0 :             SetfLargeWorkInvalidChainFound(true);
     940             :         }
     941             :     } else {
     942       40563 :         SetfLargeWorkForkFound(false);
     943       40563 :         SetfLargeWorkInvalidChainFound(false);
     944             :     }
     945             : }
     946             : 
     947          45 : void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
     948             : {
     949          45 :     AssertLockHeld(cs_main);
     950             :     // If we are on a fork that is sufficiently large, set a warning flag
     951          45 :     CBlockIndex* pfork = pindexNewForkTip;
     952          45 :     CBlockIndex* plonger = chainActive.Tip();
     953          87 :     while (pfork && pfork != plonger) {
     954          42 :         while (plonger && plonger->nHeight > pfork->nHeight)
     955           0 :             plonger = plonger->pprev;
     956          42 :         if (pfork == plonger)
     957             :             break;
     958          42 :         pfork = pfork->pprev;
     959             :     }
     960             : 
     961             :     // We define a condition which we should warn the user about as a fork of at least 7 blocks
     962             :     // who's tip is within 72 blocks (+/- 3 hours if no one mines it) of ours
     963             :     // or a chain that is entirely longer than ours and invalid (note that this should be detected by both)
     964             :     // We use 7 blocks rather arbitrarily as it represents just under 10% of sustained network
     965             :     // hash rate operating on the fork.
     966             :     // We define it this way because it allows us to only store the highest fork tip (+ base) which meets
     967             :     // the 7-block condition and from this always have the most-likely-to-cause-warning fork
     968          45 :     if (pfork && (!pindexBestForkTip || (pindexBestForkTip && pindexNewForkTip->nHeight > pindexBestForkTip->nHeight)) &&
     969          90 :         pindexNewForkTip->nChainWork - pfork->nChainWork > (GetBlockProof(*pfork) * 7) &&
     970           0 :         chainActive.Height() - pindexNewForkTip->nHeight < 72) {
     971           0 :         pindexBestForkTip = pindexNewForkTip;
     972           0 :         pindexBestForkBase = pfork;
     973             :     }
     974             : 
     975          45 :     CheckForkWarningConditions();
     976          45 : }
     977             : 
     978         120 : void static InvalidChainFound(CBlockIndex* pindexNew)
     979             : {
     980         120 :     if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork)
     981          48 :         pindexBestInvalid = pindexNew;
     982             : 
     983         240 :     LogPrintf("InvalidChainFound: invalid block=%s  height=%d  log2_work=%.16f  date=%s\n",
     984           0 :         pindexNew->GetBlockHash().ToString(), pindexNew->nHeight,
     985         240 :         log(pindexNew->nChainWork.getdouble()) / log(2.0), FormatISO8601DateTime(pindexNew->GetBlockTime()));
     986             : 
     987         120 :     const CBlockIndex* pChainTip = chainActive.Tip();
     988         120 :     assert(pChainTip);
     989         240 :     LogPrintf("InvalidChainFound:  current best=%s  height=%d  log2_work=%.16f  date=%s\n",
     990         240 :         pChainTip->GetBlockHash().GetHex(), pChainTip->nHeight, log(pChainTip->nChainWork.getdouble()) / log(2.0),
     991         120 :         FormatISO8601DateTime(pChainTip->GetBlockTime()));
     992             : 
     993         120 :     CheckForkWarningConditions();
     994         120 : }
     995             : 
     996          45 : void static InvalidBlockFound(CBlockIndex* pindex, const CValidationState& state)
     997             : {
     998          45 :     if (!state.CorruptionPossible()) {
     999          45 :         pindex->nStatus |= BLOCK_FAILED_VALID;
    1000          45 :         setDirtyBlockIndex.insert(pindex);
    1001          45 :         setBlockIndexCandidates.erase(pindex);
    1002          45 :         InvalidChainFound(pindex);
    1003             :     }
    1004          45 : }
    1005             : 
    1006      396700 : static bool SkipInvalidUTXOS(int nHeight)
    1007             : {
    1008      396700 :     const Consensus::Params& consensus = Params().GetConsensus();
    1009      396700 :     return Params().NetworkIDString() == CBaseChainParams::MAIN &&
    1010      396700 :            consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_ZC) &&
    1011      396700 :            nHeight <= consensus.height_last_invalid_UTXO;
    1012             : }
    1013             : 
    1014     2954040 : void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo& txundo, int nHeight, bool fSkipInvalid)
    1015             : {
    1016             :     // mark inputs spent
    1017     2954040 :     if (!tx.IsCoinBase() && !tx.HasZerocoinSpendInputs()) {
    1018     2894130 :         txundo.vprevout.reserve(tx.vin.size());
    1019     6993925 :         for (const CTxIn& txin : tx.vin) {
    1020     4099805 :             txundo.vprevout.emplace_back();
    1021     4099805 :             inputs.SpendCoin(txin.prevout, &txundo.vprevout.back());
    1022             :         }
    1023             :     }
    1024             : 
    1025             :     // update spent nullifiers
    1026     2954040 :     inputs.SetNullifiers(tx, true);
    1027             : 
    1028             :     // add outputs
    1029     2954040 :     AddCoins(inputs, tx, nHeight, false, fSkipInvalid);
    1030     2954040 : }
    1031             : 
    1032     2521320 : void UpdateCoins(const CTransaction& tx, CCoinsViewCache &inputs, int nHeight, bool fSkipInvalid)
    1033             : {
    1034     2521320 :     CTxUndo txundo;
    1035     2521320 :     UpdateCoins(tx, inputs, txundo, nHeight, fSkipInvalid);
    1036     2521320 : }
    1037             : 
    1038     1184203 : bool CScriptCheck::operator()()
    1039             : {
    1040     1184203 :     const CScript& scriptSig = ptxTo->vin[nIn].scriptSig;
    1041     2356173 :     return VerifyScript(scriptSig, m_tx_out.scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, m_tx_out.nValue, cacheStore, *precomTxData), ptxTo->GetRequiredSigVersion(), &error);
    1042             : }
    1043             : 
    1044     3156246 : int GetSpendHeight(const CCoinsViewCache& inputs)
    1045             : {
    1046     3156246 :     LOCK(cs_main);
    1047     3156246 :     CBlockIndex* pindexPrev = LookupBlockIndex(inputs.GetBestBlock());
    1048     6312482 :     return pindexPrev->nHeight + 1;
    1049             : }
    1050             : 
    1051             : namespace Consensus {
    1052     3156246 : bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight)
    1053             : {
    1054             :     // This doesn't trigger the DoS code on purpose; if it did, it would make it easier
    1055             :     // for an attacker to attempt to split the network.
    1056     3156246 :     if (!inputs.HaveInputs(tx))
    1057           0 :         return state.Invalid(false, 0, "", "Inputs unavailable");
    1058             : 
    1059             :     // are the Sapling's requirements met?
    1060     3156246 :     if (!inputs.HaveShieldedRequirements(tx))
    1061           0 :         return state.Invalid(error("CheckInputs(): %s Sapling requirements not met", tx.GetHash().ToString()));
    1062             : 
    1063     3156246 :     const Consensus::Params& consensus = ::Params().GetConsensus();
    1064     3156246 :     CAmount nValueIn = 0;
    1065     3156246 :     CAmount nFees = 0;
    1066     7784245 :     for (unsigned int i = 0; i < tx.vin.size(); i++) {
    1067     4628009 :         const COutPoint &prevout = tx.vin[i].prevout;
    1068     4628009 :         const Coin& coin = inputs.AccessCoin(prevout);
    1069     4628009 :         assert(!coin.IsSpent());
    1070             : 
    1071             :         // If prev is coinbase, check that it's matured
    1072     4628009 :         if (coin.IsCoinBase() || coin.IsCoinStake()) {
    1073       23217 :             if ((signed long)nSpendHeight - coin.nHeight < (signed long)consensus.nCoinbaseMaturity)
    1074          26 :                 return state.Invalid(false, REJECT_INVALID, "bad-txns-premature-spend-of-coinbase-coinstake",
    1075          26 :                         strprintf("tried to spend coinbase/coinstake at depth %d", nSpendHeight - coin.nHeight));
    1076             :         }
    1077             : 
    1078             :         // Check for negative or overflow input values
    1079     4627999 :         nValueIn += coin.out.nValue;
    1080    13884047 :         if (!consensus.MoneyRange(coin.out.nValue) || !consensus.MoneyRange(nValueIn))
    1081           0 :             return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");
    1082             :     }
    1083             : 
    1084             :     // Sapling
    1085     3156226 :     nValueIn += tx.GetShieldedValueIn();
    1086             : 
    1087     3156226 :     if (!tx.IsCoinStake()) {
    1088     3147842 :         if (nValueIn < tx.GetValueOut())
    1089           6 :             return state.DoS(100, false, REJECT_INVALID, "bad-txns-in-belowout", false,
    1090           4 :                     strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(tx.GetValueOut())));
    1091             : 
    1092             :         // Tally transaction fees
    1093     3147842 :         CAmount nTxFee = nValueIn - tx.GetValueOut();
    1094     3147842 :         if (nTxFee < 0)
    1095           0 :             return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-negative");
    1096     3147842 :         nFees += nTxFee;
    1097     3156246 :         if (!consensus.MoneyRange(nFees))
    1098           0 :             return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange");
    1099             :     }
    1100             :     return true;
    1101             : }
    1102             : }// namespace Consensus
    1103             : 
    1104     3156246 : bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& precomTxData, std::vector<CScriptCheck> *pvChecks)
    1105             : {
    1106     3156246 :     if (!tx.IsCoinBase() && !tx.HasZerocoinSpendInputs()) {
    1107             : 
    1108     3156246 :         if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs)))
    1109             :             return false;
    1110             : 
    1111     3156226 :         if (pvChecks)
    1112      340769 :             pvChecks->reserve(tx.vin.size());
    1113             : 
    1114             :         // The first loop above does all the inexpensive checks.
    1115             :         // Only if ALL inputs pass do we perform expensive ECDSA signature checks.
    1116             :         // Helps prevent CPU exhaustion attacks.
    1117             : 
    1118             :         // Skip ECDSA signature verification when connecting blocks
    1119             :         // before the last block chain checkpoint. This is safe because block merkle hashes are
    1120             :         // still computed and checked, and any change will be caught at the next checkpoint.
    1121     3156226 :         if (fScriptChecks) {
    1122     1814535 :             for (unsigned int i = 0; i < tx.vin.size(); i++) {
    1123     1179639 :                 const COutPoint& prevout = tx.vin[i].prevout;
    1124     1179639 :                 const Coin& coin = inputs.AccessCoin(prevout);
    1125     1179639 :                 assert(!coin.IsSpent());
    1126             : 
    1127             :                 // We very carefully only pass in things to CScriptCheck which
    1128             :                 // are clearly committed to by tx' witness hash. This provides
    1129             :                 // a sanity check that our caching is not introducing consensus
    1130             :                 // failures through additional data in, eg, the coins being
    1131             :                 // spent being checked as a part of CScriptCheck.
    1132             : 
    1133             :                 // Verify signature
    1134     2359268 :                 CScriptCheck check(coin.out, tx, i, flags, cacheStore, &precomTxData);
    1135     1179639 :                 if (pvChecks) {
    1136      619406 :                     pvChecks->emplace_back();
    1137      619406 :                     check.swap(pvChecks->back());
    1138      560229 :                 } else if (!check()) {
    1139           3 :                     if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) {
    1140             :                         // Check whether the failure was caused by a
    1141             :                         // non-mandatory script verification check, such as
    1142             :                         // non-standard DER encodings or non-null dummy
    1143             :                         // arguments; if so, don't trigger DoS protection to
    1144             :                         // avoid splitting the network between upgraded and
    1145             :                         // non-upgraded nodes.
    1146           3 :                         CScriptCheck check2(coin.out, tx, i,
    1147           6 :                             flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &precomTxData);
    1148           3 :                         if (check2())
    1149           0 :                             return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
    1150             :                     }
    1151             :                     // Failures of other flags indicate a transaction that is
    1152             :                     // invalid in new blocks, e.g. a invalid P2SH. We DoS ban
    1153             :                     // such nodes as they are not following the protocol. That
    1154             :                     // said during an upgrade careful thought should be taken
    1155             :                     // as to the correct behavior - we may want to continue
    1156             :                     // peering with non-upgraded nodes even after a soft-fork
    1157             :                     // super-majority vote has passed.
    1158           9 :                     return state.DoS(100, false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError())));
    1159             :                 }
    1160             :             }
    1161             :         }
    1162             :     }
    1163             : 
    1164             :     return true;
    1165             : }
    1166             : 
    1167             : /** Abort with a message */
    1168           1 : static bool AbortNode(const std::string& strMessage, const std::string& userMessage="")
    1169             : {
    1170           1 :     SetMiscWarning(strMessage);
    1171           1 :     LogPrintf("*** %s\n", strMessage);
    1172           1 :     uiInterface.ThreadSafeMessageBox(
    1173           2 :         userMessage.empty() ? _("Error: A fatal internal error occurred, see debug.log for details") : userMessage,
    1174             :         "", CClientUIInterface::MSG_ERROR);
    1175           1 :     StartShutdown();
    1176           1 :     return false;
    1177             : }
    1178             : 
    1179           1 : static bool AbortNode(CValidationState& state, const std::string& strMessage, const std::string& userMessage="")
    1180             : {
    1181           1 :     AbortNode(strMessage, userMessage);
    1182           3 :     return state.Error(strMessage);
    1183             : }
    1184             : 
    1185             : namespace {
    1186             : 
    1187       40744 : bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock)
    1188             : {
    1189             :     // Open history file to append
    1190       81488 :     CAutoFile fileout(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION);
    1191       40744 :     if (fileout.IsNull())
    1192           0 :         return error("%s : OpenUndoFile failed", __func__);
    1193             : 
    1194             :     // Write index header
    1195       40744 :     unsigned int nSize = GetSerializeSize(blockundo, fileout.GetVersion());
    1196       40744 :     fileout << Params().MessageStart() << nSize;
    1197             : 
    1198             :     // Write undo data
    1199       40744 :     long fileOutPos = ftell(fileout.Get());
    1200       40744 :     if (fileOutPos < 0)
    1201           0 :         return error("%s : ftell failed", __func__);
    1202       40744 :     pos.nPos = (unsigned int)fileOutPos;
    1203       40744 :     fileout << blockundo;
    1204             : 
    1205             :     // calculate & write checksum
    1206       40744 :     CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
    1207       40744 :     hasher << hashBlock;
    1208       40744 :     hasher << blockundo;
    1209       81488 :     fileout << hasher.GetHash();
    1210             : 
    1211       40744 :     return true;
    1212             : }
    1213             : 
    1214        2541 : bool UndoReadFromDisk(CBlockUndo& blockundo, const FlatFilePos& pos, const uint256& hashBlock)
    1215             : {
    1216             :     // Open history file to read
    1217        5082 :     CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION);
    1218        2541 :     if (filein.IsNull())
    1219           1 :         return error("%s : OpenBlockFile failed", __func__);
    1220             : 
    1221             :     // Read block
    1222        2540 :     uint256 hashChecksum;
    1223        2540 :     CHashVerifier<CAutoFile> verifier(&filein); // We need a CHashVerifier as reserializing may lose data
    1224        2540 :     try {
    1225        2540 :         verifier << hashBlock;
    1226        2540 :         verifier >> blockundo;
    1227        2539 :         filein >> hashChecksum;
    1228           1 :     } catch (const std::exception& e) {
    1229           1 :         return error("%s : Deserialize or I/O error - %s", __func__, e.what());
    1230             :     }
    1231             : 
    1232             :     // Verify checksum
    1233        5078 :     if (hashChecksum != verifier.GetHash())
    1234           0 :         return error("%s : Checksum mismatch", __func__);
    1235             : 
    1236             :     return true;
    1237             : }
    1238             : 
    1239             : } // anon namespace
    1240             : 
    1241             : enum DisconnectResult
    1242             : {
    1243             :     DISCONNECT_OK,      // All good.
    1244             :     DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block.
    1245             :     DISCONNECT_FAILED   // Something else went wrong.
    1246             : };
    1247             : 
    1248             : /**
    1249             :  * Restore the UTXO in a Coin at a given COutPoint
    1250             :  * @param undo The Coin to be restored.
    1251             :  * @param view The coins view to which to apply the changes.
    1252             :  * @param out The out point that corresponds to the tx input.
    1253             :  * @return A DisconnectResult as an int
    1254             :  */
    1255      121053 : int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out)
    1256             : {
    1257      121053 :     bool fClean = true;
    1258             : 
    1259      121053 :     if (view.HaveCoin(out)) fClean = false; // overwriting transaction output
    1260             : 
    1261      121053 :     if (undo.nHeight == 0) {
    1262             :         // Missing undo metadata (height and coinbase/coinstake). Older versions included this
    1263             :         // information only in undo records for the last spend of a transactions'
    1264             :         // outputs. This implies that it must be present for some other output of the same tx.
    1265           0 :         const Coin& alternate = AccessByTxid(view, out.hash);
    1266           0 :         if (!alternate.IsSpent()) {
    1267           0 :             undo.nHeight = alternate.nHeight;
    1268           0 :             undo.fCoinBase = alternate.fCoinBase;
    1269           0 :             undo.fCoinStake = alternate.fCoinStake;
    1270             :         } else {
    1271             :             return DISCONNECT_FAILED; // adding output for transaction without known metadata
    1272             :         }
    1273             :     }
    1274             :     // The potential_overwrite parameter to AddCoin is only allowed to be false if we know for
    1275             :     // sure that the coin did not already exist in the cache. As we have queried for that above
    1276             :     // using HaveCoin, we don't need to guess. When fClean is false, a coin already existed and
    1277             :     // it is an overwrite.
    1278      121053 :     view.AddCoin(out, std::move(undo), !fClean);
    1279             : 
    1280      121053 :     return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
    1281             : }
    1282             : 
    1283             : 
    1284             : /** Undo the effects of this block (with given index) on the UTXO set represented by coins.
    1285             :  *  When FAILED is returned, view is left in an indeterminate state. */
    1286        1405 : DisconnectResult DisconnectBlock(CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view)
    1287             : {
    1288        1405 :     AssertLockHeld(cs_main);
    1289             : 
    1290        1405 :     bool fDIP3Active = Params().GetConsensus().NetworkUpgradeActive(pindex->nHeight, Consensus::UPGRADE_V6_0);
    1291        1405 :     bool fHasBestBlock = evoDb->VerifyBestBlock(pindex->GetBlockHash());
    1292             : 
    1293        1405 :     if (fDIP3Active && !fHasBestBlock) {
    1294           0 :         AbortNode("Found EvoDB inconsistency, you must reindex to continue");
    1295           0 :         return DISCONNECT_FAILED;
    1296             :     }
    1297             : 
    1298        1405 :     bool fClean = true;
    1299             : 
    1300        2810 :     CBlockUndo blockUndo;
    1301        1405 :     FlatFilePos pos = pindex->GetUndoPos();
    1302        1405 :     if (pos.IsNull()) {
    1303           0 :         error("%s: no undo data available", __func__);
    1304             :         return DISCONNECT_FAILED;
    1305             :     }
    1306        1405 :     if (!UndoReadFromDisk(blockUndo, pos, pindex->pprev->GetBlockHash())) {
    1307           1 :         error("%s: failure reading undo data", __func__);
    1308             :         return DISCONNECT_FAILED;
    1309             :     }
    1310             : 
    1311        1404 :     if (blockUndo.vtxundo.size() + 1 != block.vtx.size()) {
    1312           0 :         error("%s: block and undo data inconsistent", __func__);
    1313             :         return DISCONNECT_FAILED;
    1314             :     }
    1315             : 
    1316        1404 :     if (!UndoSpecialTxsInBlock(block, pindex)) {
    1317             :         return DISCONNECT_FAILED;
    1318             :     }
    1319             : 
    1320             :     // undo transactions in reverse order
    1321       62580 :     for (int i = block.vtx.size() - 1; i >= 0; i--) {
    1322       61176 :         const CTransaction& tx = *block.vtx[i];
    1323             : 
    1324       61176 :         if (!DisconnectZerocoinTx(tx))
    1325             :             return DISCONNECT_FAILED;
    1326             : 
    1327       61176 :         const uint256& hash = tx.GetHash();
    1328             : 
    1329             :         // if tx is a budget collateral tx, remove relative object
    1330       61176 :         g_budgetman.RemoveByFeeTxId(hash);
    1331             : 
    1332             :         // Check that all outputs are available and match the outputs in the block itself
    1333             :         // exactly.
    1334      228250 :         for (size_t o = 0; o < tx.vout.size(); o++) {
    1335      501214 :             if (!tx.vout[o].scriptPubKey.IsUnspendable() && !tx.vout[o].IsZerocoinMint()) {
    1336      167066 :                 COutPoint out(hash, o);
    1337      334132 :                 Coin coin;
    1338      167066 :                 view.SpendCoin(out, &coin);
    1339      167066 :                 if (tx.vout[o] != coin.out) {
    1340           0 :                     fClean = false; // transaction output mismatch
    1341             :                 }
    1342             :             }
    1343             :         }
    1344             : 
    1345             :         // not coinbases or zerocoinspend because they dont have traditional inputs
    1346       61176 :         if (tx.IsCoinBase() || tx.HasZerocoinSpendInputs())
    1347        1404 :             continue;
    1348             : 
    1349             :         // Sapling, update unspent nullifiers
    1350       59772 :         view.SetNullifiers(tx, false);
    1351             : 
    1352             :         // restore inputs
    1353       59772 :         CTxUndo& txundo = blockUndo.vtxundo[i - 1];
    1354       59772 :         if (txundo.vprevout.size() != tx.vin.size()) {
    1355           0 :             error("%s: transaction and undo data inconsistent - txundo.vprevout.siz=%d tx.vin.siz=%d",
    1356           0 :                     __func__, txundo.vprevout.size(), tx.vin.size());
    1357           0 :             return DISCONNECT_FAILED;
    1358             :         }
    1359      179060 :         for (unsigned int j = tx.vin.size(); j-- > 0;) {
    1360      119288 :             const COutPoint& out = tx.vin[j].prevout;
    1361      119288 :             int res = ApplyTxInUndo(std::move(txundo.vprevout[j]), view, out);
    1362      119288 :             if (res == DISCONNECT_FAILED) return DISCONNECT_FAILED;
    1363      119288 :             fClean = fClean && res != DISCONNECT_UNCLEAN;
    1364             :         }
    1365             :         // At this point, all of txundo.vprevout should have been moved out.
    1366             :     }
    1367             : 
    1368        1404 :     const Consensus::Params& consensus = Params().GetConsensus();
    1369             : 
    1370             :     // set the old best Sapling anchor back
    1371             :     // We can get this from the `hashFinalSaplingRoot` of the last block
    1372             :     // However, this is only reliable if the last block was on or after
    1373             :     // the Sapling activation height. Otherwise, the last anchor was the
    1374             :     // empty root.
    1375        1404 :     if (consensus.NetworkUpgradeActive(pindex->pprev->nHeight, Consensus::UPGRADE_V5_0)) {
    1376         281 :         view.PopAnchor(pindex->pprev->hashFinalSaplingRoot);
    1377             :     } else {
    1378        2246 :         view.PopAnchor(SaplingMerkleTree::empty_root());
    1379             :     }
    1380             : 
    1381             :     // move best block pointer to prevout block
    1382        1404 :     view.SetBestBlock(pindex->pprev->GetBlockHash());
    1383        1404 :     evoDb->WriteBestBlock(pindex->pprev->GetBlockHash());
    1384             : 
    1385        1404 :     if (consensus.NetworkUpgradeActive(pindex->nHeight, Consensus::UPGRADE_ZC_V2) &&
    1386          15 :             pindex->nHeight <= consensus.height_last_ZC_AccumCheckpoint) {
    1387             :         // Legacy Zerocoin DB: If Accumulators Checkpoint is changed, remove changed checksums
    1388           0 :         CacheAccChecksum(pindex, false);
    1389             :     }
    1390             : 
    1391        1404 :     return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
    1392             : }
    1393             : 
    1394         803 : void static FlushBlockFile(bool fFinalize = false)
    1395             : {
    1396         803 :     LOCK(cs_LastBlockFile);
    1397             : 
    1398         803 :     FlatFilePos block_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nSize);
    1399         803 :     FlatFilePos undo_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nUndoSize);
    1400             : 
    1401         803 :     bool status = true;
    1402         803 :     status &= BlockFileSeq().Flush(block_pos_old, fFinalize);
    1403         803 :     status &= UndoFileSeq().Flush(undo_pos_old, fFinalize);
    1404         803 :     if (!status) {
    1405           0 :         AbortNode("Flushing block file to disk failed. This is likely the result of an I/O error.");
    1406             :     }
    1407         803 : }
    1408             : 
    1409             : bool FindUndoPos(CValidationState& state, int nFile, FlatFilePos& pos, unsigned int nAddSize);
    1410             : 
    1411             : static CCheckQueue<CScriptCheck> scriptcheckqueue(128);
    1412             : 
    1413        2868 : void ThreadScriptCheck()
    1414             : {
    1415        2868 :     util::ThreadRename("pivx-scriptch");
    1416        2868 :     scriptcheckqueue.Thread();
    1417           0 : }
    1418             : 
    1419             : static int64_t nTimeVerify = 0;
    1420             : static int64_t nTimeProcessSpecial = 0;
    1421             : static int64_t nTimeConnect = 0;
    1422             : static int64_t nTimeIndex = 0;
    1423             : static int64_t nTimeTotal = 0;
    1424             : 
    1425             : /** Apply the effects of this block (with given index) on the UTXO set represented by coins.
    1426             :  *  Validity checks that depend on the UTXO set are also done; ConnectBlock()
    1427             :  *  can fail if those validity checks fail (among other reasons). */
    1428       56242 : static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    1429             : {
    1430       56242 :     AssertLockHeld(cs_main);
    1431             :     // Check it again in case a previous version let a bad block in
    1432       56242 :     if (!CheckBlock(block, state, !fJustCheck, !fJustCheck, !fJustCheck)) {
    1433           0 :         if (state.CorruptionPossible()) {
    1434             :             // We don't write down blocks to disk if they may have been
    1435             :             // corrupted, so this should be impossible unless we're having hardware
    1436             :             // problems.
    1437           0 :             return AbortNode(state, "Corrupt block found indicating potential hardware failure; shutting down");
    1438             :         }
    1439           0 :         return error("%s: CheckBlock failed for %s: %s", __func__, block.GetHash().ToString(), FormatStateMessage(state));
    1440             :     }
    1441             : 
    1442       56242 :     if (pindex->pprev && pindex->phashBlock && llmq::chainLocksHandler->HasConflictingChainLock(pindex->nHeight, pindex->GetBlockHash())) {
    1443           0 :         return state.DoS(10, error("%s: conflicting with chainlock", __func__), REJECT_INVALID, "bad-chainlock");
    1444             :     }
    1445             :     // verify that the view's current state corresponds to the previous block
    1446       56242 :     uint256 hashPrevBlock = pindex->pprev == nullptr ? UINT256_ZERO : pindex->pprev->GetBlockHash();
    1447       56242 :     if (hashPrevBlock != view.GetBestBlock())
    1448           0 :         LogPrintf("%s: hashPrev=%s view=%s\n", __func__, hashPrevBlock.GetHex(), view.GetBestBlock().GetHex());
    1449       56242 :     assert(hashPrevBlock == view.GetBestBlock());
    1450             : 
    1451       56242 :     const bool isPoSBlock = block.IsProofOfStake();
    1452       56242 :     const Consensus::Params& consensus = Params().GetConsensus();
    1453       56242 :     const bool isPoSActive = consensus.NetworkUpgradeActive(pindex->nHeight, Consensus::UPGRADE_POS);
    1454       56242 :     const bool isV5UpgradeEnforced = consensus.NetworkUpgradeActive(pindex->nHeight, Consensus::UPGRADE_V5_0);
    1455       56242 :     const bool isV6UpgradeEnforced = consensus.NetworkUpgradeActive(pindex->nHeight, Consensus::UPGRADE_V6_0);
    1456             : 
    1457             :     // Coinbase output should be empty if proof-of-stake block (before v6 enforcement)
    1458       56242 :     if (!isV6UpgradeEnforced && isPoSBlock && (block.vtx[0]->vout.size() != 1 || !block.vtx[0]->vout[0].IsEmpty()))
    1459           0 :         return state.DoS(100, false, REJECT_INVALID, "bad-cb-pos", false, "coinbase output not empty for proof-of-stake block");
    1460             : 
    1461       56242 :     if (pindex->pprev) {
    1462       55924 :         bool fHasBestBlock = evoDb->VerifyBestBlock(hashPrevBlock);
    1463             : 
    1464       55924 :         if (isV6UpgradeEnforced && !fHasBestBlock) {
    1465           0 :             return AbortNode(state, "Found EvoDB inconsistency, you must reindex to continue");
    1466             :         }
    1467             :     }
    1468             : 
    1469             :     // Special case for the genesis block, skipping connection of its transactions
    1470             :     // (its coinbase is unspendable)
    1471       56242 :     if (block.GetHash() == consensus.hashGenesisBlock) {
    1472         318 :         if (!fJustCheck) {
    1473         318 :             view.SetBestBlock(pindex->GetBlockHash());
    1474             :         }
    1475         318 :         return true;
    1476             :     }
    1477             : 
    1478       55924 :     if (!isPoSActive && isPoSBlock)
    1479           0 :         return state.DoS(100, error("ConnectBlock() : PoS period not active"),
    1480             :             REJECT_INVALID, "PoS-early");
    1481             : 
    1482       55924 :     if (isPoSActive && !isPoSBlock)
    1483           0 :         return state.DoS(100, error("ConnectBlock() : PoW period ended"),
    1484             :             REJECT_INVALID, "PoW-ended");
    1485             : 
    1486             :     // Sapling
    1487             :     // Reject a block that results in a negative shielded value pool balance.
    1488             :     // Description under ZIP209 turnstile violation.
    1489             : 
    1490             :     // If we've reached ConnectBlock, we have all transactions of
    1491             :     // parents and can expect nChainSaplingValue not to be boost::none.
    1492             :     // However, the miner and mining RPCs may not have populated this
    1493             :     // value and will call `TestBlockValidity`. So, we act
    1494             :     // conditionally.
    1495       55924 :     if (pindex->nChainSaplingValue) {
    1496       40974 :         if (*pindex->nChainSaplingValue < 0) {
    1497           0 :             return state.DoS(100, error("%s: turnstile violation in Sapling shielded value pool: val: %d", __func__, *pindex->nChainSaplingValue),
    1498             :                              REJECT_INVALID, "turnstile-violation-sapling-shielded-pool");
    1499             :         }
    1500             :     }
    1501             : 
    1502       55924 :     bool fScriptChecks = pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate();
    1503             : 
    1504             :     // If scripts won't be checked anyways, don't bother seeing if CLTV is activated
    1505       55924 :     bool fCLTVIsActivated = false;
    1506       55924 :     bool exchangeAddrActivated = false;
    1507       55924 :     if (fScriptChecks && pindex->pprev) {
    1508       55924 :         fCLTVIsActivated = consensus.NetworkUpgradeActive(pindex->pprev->nHeight, Consensus::UPGRADE_BIP65);
    1509       55924 :         exchangeAddrActivated = consensus.NetworkUpgradeActive(pindex->pprev->nHeight, Consensus::UPGRADE_V5_6);
    1510             :     }
    1511             : 
    1512      112166 :     CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : nullptr);
    1513             : 
    1514       55924 :     int64_t nTimeStart = GetTimeMicros();
    1515       55924 :     CAmount nFees = 0;
    1516       55924 :     int nInputs = 0;
    1517       55924 :     unsigned int nSigOps = 0;
    1518       56040 :     CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
    1519      111848 :     std::vector<std::pair<uint256, CDiskTxPos> > vPos;
    1520       55924 :     std::vector<std::pair<CBigNum, uint256> > vSpends;
    1521       55924 :     vPos.reserve(block.vtx.size());
    1522      111848 :     CBlockUndo blockundo;
    1523       55924 :     blockundo.vtxundo.reserve(block.vtx.size() - 1);
    1524       55924 :     CAmount nValueOut = 0;
    1525       55924 :     CAmount nValueIn = 0;
    1526       55924 :     unsigned int nMaxBlockSigOps = MAX_BLOCK_SIGOPS_CURRENT;
    1527             : 
    1528             :     // Sapling
    1529      111848 :     SaplingMerkleTree sapling_tree;
    1530       55924 :     assert(view.GetSaplingAnchorAt(view.GetBestAnchor(), sapling_tree));
    1531             : 
    1532      111848 :     std::vector<PrecomputedTransactionData> precomTxData;
    1533       55924 :     precomTxData.reserve(block.vtx.size()); // Required so that pointers to individual precomTxData don't get invalidated
    1534       55924 :     bool fInitialBlockDownload = IsInitialBlockDownload();
    1535       55924 :     bool fSaplingMaintenance =  (block.nTime > sporkManager.GetSporkValue(SPORK_20_SAPLING_MAINTENANCE));
    1536      452617 :     for (unsigned int i = 0; i < block.vtx.size(); i++) {
    1537      396714 :         const CTransaction& tx = *block.vtx[i];
    1538             : 
    1539      396714 :         nInputs += tx.vin.size();
    1540      396714 :         nSigOps += GetLegacySigOpCount(tx);
    1541      396714 :         if (nSigOps > nMaxBlockSigOps)
    1542           2 :             return state.DoS(100, error("ConnectBlock() : too many sigops"), REJECT_INVALID, "bad-blk-sigops");
    1543             : 
    1544             :         // Check maintenance mode
    1545      396713 :         if (!fInitialBlockDownload && fSaplingMaintenance && tx.IsShieldedTx()) {
    1546           2 :             return state.DoS(100, error("%s : shielded transactions are currently in maintenance mode", __func__));
    1547             :         }
    1548             : 
    1549             :         // When v5 is enforced ContextualCheckTransaction rejects zerocoin transactions.
    1550             :         // Therefore no need to call HasZerocoinSpendInputs after the enforcement.
    1551      396712 :         if (!isV5UpgradeEnforced && tx.HasZerocoinSpendInputs()) {
    1552           0 :             if (!ParseAndValidateZerocoinSpends(consensus, tx, pindex->nHeight, state, vSpends)) {
    1553             :                 return false; // Invalidity/DoS is handled by the function.
    1554             :             }
    1555      396712 :         } else if (!tx.IsCoinBase()) {
    1556      340788 :             if (!view.HaveInputs(tx)) {
    1557          42 :                 return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-missingorspent");
    1558             :             }
    1559             :             // Sapling: are the sapling spends' requirements met in tx(valid anchors/nullifiers)?
    1560      340774 :             if (!view.HaveShieldedRequirements(tx))
    1561           3 :                 return state.DoS(100, error("%s: spends requirements not met", __func__),
    1562             :                                  REJECT_INVALID, "bad-txns-sapling-requirements-not-met");
    1563             : 
    1564             :             // Add in sigops done by pay-to-script-hash inputs;
    1565             :             // this is to prevent a "rogue miner" from creating
    1566             :             // an incredibly-expensive-to-validate block.
    1567      340773 :             nSigOps += GetP2SHSigOpCount(tx, view);
    1568      340773 :             if (nSigOps > nMaxBlockSigOps)
    1569           0 :                 return state.DoS(100, error("ConnectBlock() : too many sigops"), REJECT_INVALID, "bad-blk-sigops");
    1570             : 
    1571             :         }
    1572             : 
    1573             :         // Cache the sig ser hashes
    1574      396697 :         precomTxData.emplace_back(tx);
    1575             : 
    1576      396697 :         CAmount txValueOut = tx.GetValueOut();
    1577      396697 :         if (!tx.IsCoinBase()) {
    1578      340773 :             CAmount txValueIn = view.GetValueIn(tx);
    1579      340773 :             if (!tx.IsCoinStake())
    1580      332385 :                 nFees += txValueIn - txValueOut;
    1581      340773 :             nValueIn += txValueIn;
    1582             : 
    1583      340773 :             std::vector<CScriptCheck> vChecks;
    1584      340773 :             unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG;
    1585      340773 :             if (fCLTVIsActivated)
    1586      340773 :                 flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
    1587      340773 :             if (exchangeAddrActivated)
    1588      265120 :                 flags |= SCRIPT_VERIFY_EXCHANGEADDR;
    1589             : 
    1590      340773 :             bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
    1591      340773 :             if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, precomTxData[i], nScriptCheckThreads ? &vChecks : nullptr))
    1592          12 :                 return error("%s: Check inputs on %s failed with %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));
    1593      681538 :             control.Add(vChecks);
    1594             :         }
    1595      396693 :         nValueOut += txValueOut;
    1596             : 
    1597      793386 :         CTxUndo undoDummy;
    1598      396693 :         if (i > 0) {
    1599      340769 :             blockundo.vtxundo.emplace_back();
    1600             :         }
    1601      396693 :         const bool fSkipInvalid = SkipInvalidUTXOS(pindex->nHeight);
    1602      396693 :         UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight, fSkipInvalid);
    1603             : 
    1604             :         // Sapling update tree
    1605      398845 :         if (tx.IsShieldedTx() && !tx.sapData->vShieldedOutput.empty()) {
    1606        4577 :             for(const OutputDescription &outputDescription : tx.sapData->vShieldedOutput) {
    1607        2428 :                 sapling_tree.append(outputDescription.cmu);
    1608             :             }
    1609             :         }
    1610             : 
    1611      396693 :         vPos.emplace_back(tx.GetHash(), pos);
    1612      396693 :         pos.nTxOffset += ::GetSerializeSize(tx, CLIENT_VERSION);
    1613             :     }
    1614             : 
    1615             :     // Push new tree anchor
    1616       55903 :     view.PushAnchor(sapling_tree);
    1617             : 
    1618             :     // Verify header correctness
    1619       55903 :     if (isV5UpgradeEnforced) {
    1620             :         // If Sapling is active, block.hashFinalSaplingRoot must be the
    1621             :         // same as the root of the Sapling tree
    1622       24254 :         if (block.hashFinalSaplingRoot != sapling_tree.root()) {
    1623           0 :             return state.DoS(100,
    1624           0 :                              error("ConnectBlock(): block's hashFinalSaplingRoot is incorrect (should be Sapling tree root)"),
    1625             :                              REJECT_INVALID, "bad-sapling-root-in-block");
    1626             :         }
    1627             :     }
    1628             : 
    1629             :     // track mint amount info
    1630       55903 :     assert(nFees >= 0);
    1631       55903 :     const int64_t nMint = (nValueOut - nValueIn) + nFees;
    1632             : 
    1633       55903 :     int64_t nTime1 = GetTimeMicros();
    1634       55903 :     nTimeConnect += nTime1 - nTimeStart;
    1635       55903 :     LogPrint(BCLog::BENCHMARK, "      - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs - 1), nTimeConnect * 0.000001);
    1636             : 
    1637             :     //PoW phase redistributed fees to miner. PoS stage destroys fees.
    1638       55903 :     CAmount nExpectedMint = GetBlockValue(pindex->nHeight);
    1639       55903 :     if (!isPoSBlock)
    1640       47515 :         nExpectedMint += nFees;
    1641             : 
    1642             :     //Check that the block does not overmint
    1643       55903 :     CAmount nBudgetAmt = 0;     // If this is a superblock, amount to be paid to the winning proposal, otherwise 0
    1644       55903 :     if (!IsBlockValueValid(pindex->nHeight, nExpectedMint, nMint, nBudgetAmt)) {
    1645          24 :         return state.DoS(100, error("%s: reward pays too much (actual=%s vs limit=%s)",
    1646          12 :                                     __func__, FormatMoney(nMint), FormatMoney(nExpectedMint)),
    1647             :                          REJECT_INVALID, "bad-blk-amount");
    1648             :     }
    1649             : 
    1650             :     // Masternode/Budget payments
    1651             :     // !TODO: after transition to DMN is complete, check this also during IBD
    1652       55897 :     if (!fInitialBlockDownload) {
    1653       55253 :         if (!IsBlockPayeeValid(block, pindex->pprev)) {
    1654           5 :             mapRejectedBlocks.emplace(block.GetHash(), GetTime());
    1655          15 :             return state.DoS(0, false, REJECT_INVALID, "bad-cb-payee", false, "Couldn't find masternode/budget payment");
    1656             :         }
    1657             :     }
    1658             : 
    1659             :     // After v6 enforcement: Check that the coinbase pays the exact amount
    1660       55892 :     if (isPoSBlock && isV6UpgradeEnforced && !IsCoinbaseValueValid(block.vtx[0], nBudgetAmt, state)) {
    1661             :         // pass the state returned by the function above
    1662             :         return false;
    1663             :     }
    1664             : 
    1665      111784 :     if (!control.Wait())
    1666           3 :         return state.DoS(100, error("%s: CheckQueue failed", __func__), REJECT_INVALID, "block-validation-failed");
    1667       55891 :     int64_t nTime2 = GetTimeMicros();
    1668       55891 :     nTimeVerify += nTime2 - nTimeStart;
    1669       55891 :     LogPrint(BCLog::BENCHMARK, "    - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs]\n", nInputs - 1, 0.001 * (nTime2 - nTimeStart), nInputs <= 1 ? 0 : 0.001 * (nTime2 - nTimeStart) / (nInputs - 1), nTimeVerify * 0.000001);
    1670             : 
    1671       55891 :     if (!ProcessSpecialTxsInBlock(block, pindex, &view, state, fJustCheck)) {
    1672          27 :         return error("%s: Special tx processing failed with %s", __func__, FormatStateMessage(state));
    1673             :     }
    1674       55876 :     int64_t nTime3 = GetTimeMicros();
    1675       55876 :     nTimeProcessSpecial += nTime3 - nTime2;
    1676       55876 :     LogPrint(BCLog::BENCHMARK, "    - Process special tx: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeProcessSpecial * 0.000001);
    1677             : 
    1678             :     //IMPORTANT NOTE: Nothing before this point should actually store to disk (or even memory)
    1679       55876 :     if (fJustCheck)
    1680             :         return true;
    1681             : 
    1682             :     // Write undo information to disk
    1683       40929 :     if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS)) {
    1684       40744 :         if (pindex->GetUndoPos().IsNull()) {
    1685       40744 :             FlatFilePos diskPosBlock;
    1686       40744 :             if (!FindUndoPos(state, pindex->nFile, diskPosBlock, ::GetSerializeSize(blockundo, CLIENT_VERSION) + 40))
    1687           0 :                 return error("ConnectBlock() : FindUndoPos failed");
    1688       40744 :             if (!UndoWriteToDisk(blockundo, diskPosBlock, pindex->pprev->GetBlockHash()))
    1689           0 :                 return AbortNode(state, "Failed to write undo data");
    1690             : 
    1691             :             // update nUndoPos in block index
    1692       40744 :             pindex->nUndoPos = diskPosBlock.nPos;
    1693       40744 :             pindex->nStatus |= BLOCK_HAVE_UNDO;
    1694             :         }
    1695             : 
    1696       40744 :         pindex->RaiseValidity(BLOCK_VALID_SCRIPTS);
    1697       40744 :         setDirtyBlockIndex.insert(pindex);
    1698             :     }
    1699             : 
    1700             :     // Flush spend/mint info to disk
    1701       40929 :     if (!vSpends.empty() && !zerocoinDB->WriteCoinSpendBatch(vSpends))
    1702           0 :         return AbortNode(state, "Failed to record coin serials to database");
    1703             : 
    1704       40929 :     if (fTxIndex)
    1705       40929 :         if (!pblocktree->WriteTxIndex(vPos))
    1706           0 :             return AbortNode(state, "Failed to write transaction index");
    1707             : 
    1708             :     // add this block to the view's block chain
    1709       40929 :     view.SetBestBlock(pindex->GetBlockHash());
    1710       40929 :     evoDb->WriteBestBlock(pindex->GetBlockHash());
    1711             : 
    1712       40929 :     int64_t nTime4 = GetTimeMicros();
    1713       40929 :     nTimeIndex += nTime4 - nTime3;
    1714       40929 :     LogPrint(BCLog::BENCHMARK, "    - Index writing: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeIndex * 0.000001);
    1715             : 
    1716       40929 :     if (consensus.NetworkUpgradeActive(pindex->nHeight, Consensus::UPGRADE_ZC_V2) &&
    1717        4981 :             pindex->nHeight < consensus.height_last_ZC_AccumCheckpoint) {
    1718             :         // Legacy Zerocoin DB: If Accumulators Checkpoint is changed, cache the checksums
    1719         248 :         CacheAccChecksum(pindex, true);
    1720             :         // Clean coinspends cache every 50k blocks, so it does not grow unnecessarily
    1721         248 :         if (pindex->nHeight % 50000 == 0) {
    1722           0 :             ZPIVModule::CleanCoinSpendsCache();
    1723             :         }
    1724       40681 :     } else if (accumulatorCache && pindex->nHeight > consensus.height_last_ZC_AccumCheckpoint + 100) {
    1725             :         // 100 blocks After last Checkpoint block, wipe the checksum database and cache
    1726          20 :         accumulatorCache->Wipe();
    1727          20 :         accumulatorCache.reset();
    1728          20 :         ZPIVModule::CleanCoinSpendsCache();
    1729             :     }
    1730             : 
    1731             :     // 100 blocks after the last invalid out, clean the map contents
    1732       40929 :     if (pindex->nHeight == consensus.height_last_invalid_UTXO + 100) {
    1733       56083 :         invalid_out::setInvalidOutPoints.clear();
    1734             :     }
    1735             : 
    1736             :     return true;
    1737             : }
    1738             : 
    1739             : /**
    1740             :  * Update the on-disk chain state.
    1741             :  * The caches and indexes are flushed if either they're too large, forceWrite is set, or
    1742             :  * fast is not set and it's been a while since the last write.
    1743             :  * Full flush also updates the money supply from disk (except during shutdown)
    1744             :  */
    1745      242422 : bool static FlushStateToDisk(CValidationState& state, FlushStateMode mode)
    1746             : {
    1747      242422 :     int64_t nMempoolUsage = mempool.DynamicMemoryUsage();
    1748      484844 :     LOCK(cs_main);
    1749      242422 :     static int64_t nLastWrite = 0;
    1750      242422 :     static int64_t nLastFlush = 0;
    1751      242422 :     static int64_t nLastSetChain = 0;
    1752      242422 :     try {
    1753      242422 :         int64_t nNow = GetTimeMicros();
    1754             :         // Avoid writing/flushing immediately after startup.
    1755      242422 :         if (nLastWrite == 0) {
    1756         390 :             nLastWrite = nNow;
    1757             :         }
    1758      242422 :         if (nLastFlush == 0) {
    1759         390 :             nLastFlush = nNow;
    1760             :         }
    1761      242422 :         if (nLastSetChain == 0) {
    1762         390 :             nLastSetChain = nNow;
    1763             :         }
    1764      242422 :         int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
    1765      242422 :         int64_t cacheSize = pcoinsTip->DynamicMemoryUsage();
    1766      242422 :         int64_t nTotalSpace = nCoinCacheUsage + std::max<int64_t>(nMempoolSizeMax - nMempoolUsage, 0);
    1767             :         // The cache is large and we're within 10% and 10 MiB of the limit, but we have time now
    1768             :         // (not in the middle of a block processing).
    1769      242422 :         bool fCacheLarge = mode == FLUSH_STATE_PERIODIC &&
    1770      400183 :                 cacheSize > std::max((9 * nTotalSpace) / 10, nTotalSpace - MAX_BLOCK_COINSDB_USAGE * 1024 * 1024);
    1771             :         // The cache is over the limit, we have to write now.
    1772      242422 :         bool fCacheCritical = mode == FLUSH_STATE_IF_NEEDED && (unsigned) cacheSize > nCoinCacheUsage;
    1773             :         // The evoDB cache is too large, time to write
    1774      242422 :         bool fEvoDbCacheCritical = mode == FLUSH_STATE_IF_NEEDED && evoDb != nullptr && evoDb->GetMemoryUsage() >= (64 << 20);
    1775             :         // It's been a while since we wrote the block index to disk.
    1776             :         // Do this frequently, so we don't need to redownload after a crash.
    1777      242422 :         bool fPeriodicWrite = mode == FLUSH_STATE_PERIODIC && nNow > nLastWrite + (int64_t)DATABASE_WRITE_INTERVAL * 1000000;
    1778             :         // It's been very long since we flushed the cache. Do this infrequently, to optimize cache usage.
    1779      242422 :         bool fPeriodicFlush = mode == FLUSH_STATE_PERIODIC && nNow > nLastFlush + (int64_t)DATABASE_FLUSH_INTERVAL * 1000000;
    1780             :         // Combine all conditions that result in a full cache flush.
    1781      242422 :         bool fDoFullFlush = (mode == FLUSH_STATE_ALWAYS) || fCacheLarge || fCacheCritical || fEvoDbCacheCritical || fPeriodicFlush;
    1782             :         // Write blocks and block index to disk.
    1783      242422 :         if (fDoFullFlush || fPeriodicWrite) {
    1784             :             // Depend on nMinDiskSpace to ensure we can write block index
    1785         802 :             if (!CheckDiskSpace(GetBlocksDir())) {
    1786           0 :                 return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!"));
    1787             :             }
    1788             :             // First make sure all block and undo data is flushed to disk.
    1789         802 :             FlushBlockFile();
    1790             :             // Then update all block file information (which may refer to block and undo files).
    1791         802 :             {
    1792         802 :                 std::vector<std::pair<int, const CBlockFileInfo*> > vFiles;
    1793         802 :                 vFiles.reserve(setDirtyFileInfo.size());
    1794        1128 :                 for (std::set<int>::iterator it = setDirtyFileInfo.begin(); it != setDirtyFileInfo.end(); ) {
    1795         326 :                     vFiles.emplace_back(*it, &vinfoBlockFile[*it]);
    1796         326 :                     setDirtyFileInfo.erase(it++);
    1797             :                 }
    1798        1604 :                 std::vector<const CBlockIndex*> vBlocks;
    1799         802 :                 vBlocks.reserve(setDirtyBlockIndex.size());
    1800       39671 :                 for (std::set<CBlockIndex*>::iterator it = setDirtyBlockIndex.begin(); it != setDirtyBlockIndex.end(); ) {
    1801       38869 :                     vBlocks.push_back(*it);
    1802       38869 :                     setDirtyBlockIndex.erase(it++);
    1803             :                 }
    1804         802 :                 if (!pblocktree->WriteBatchSync(vFiles, nLastBlockFile, vBlocks)) {
    1805           0 :                     return AbortNode(state, "Files to write to block index database");
    1806             :                 }
    1807             :             }
    1808             :             // Flush zerocoin accumulator checkpoints cache
    1809         802 :             if (accumulatorCache) accumulatorCache->Flush();
    1810             : 
    1811         802 :             nLastWrite = nNow;
    1812             :         }
    1813             : 
    1814             :         // Flush best chain related state. This can only be done if the blocks / block index write was also done.
    1815      243224 :         if (fDoFullFlush && !pcoinsTip->GetBestBlock().IsNull()) {
    1816             :             // Typical Coin structures on disk are around 48 bytes in size.
    1817             :             // Pushing a new one to the database can cause it to be written
    1818             :             // twice (once in the log, and once in the tables). This is already
    1819             :             // an overestimation, as most will delete an existing entry or
    1820             :             // overwrite one. Still, use a conservative safety factor of 2.
    1821         802 :             if (!CheckDiskSpace(GetDataDir(), 48 * 2 * 2 * pcoinsTip->GetCacheSize())) {
    1822           0 :                 return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!"));
    1823             :             }
    1824             :             // Flush the chainstate (which may refer to block index entries).
    1825         802 :             if (!pcoinsTip->Flush())
    1826           0 :                 return AbortNode(state, "Failed to write to coin database");
    1827         802 :             if (!evoDb->CommitRootTransaction()) {
    1828           0 :                 return AbortNode(state, "Failed to commit EvoDB");
    1829             :             }
    1830         802 :             nLastFlush = nNow;
    1831             :             // Update money supply on memory, reading data from disk
    1832         802 :             if (!ShutdownRequested() && !IsInitialBlockDownload()) {
    1833          87 :                 MoneySupply.Update(pcoinsTip->GetTotalAmount(), chainActive.Height());
    1834             :             }
    1835             :         }
    1836      242422 :         if ((mode == FLUSH_STATE_ALWAYS || mode == FLUSH_STATE_PERIODIC) && nNow > nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000) {
    1837             :             // Update best block in wallet (so we can detect restored wallets).
    1838           0 :             GetMainSignals().SetBestChain(chainActive.GetLocator());
    1839           0 :             nLastSetChain = nNow;
    1840             :         }
    1841             : 
    1842           0 :     } catch (const std::runtime_error& e) {
    1843           0 :         return AbortNode(state, std::string("System error while flushing: ") + e.what());
    1844             :     }
    1845             :     return true;
    1846             : }
    1847             : 
    1848         800 : void FlushStateToDisk()
    1849             : {
    1850         800 :     CValidationState state;
    1851         800 :     FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
    1852         800 : }
    1853             : 
    1854             : /** Update chainActive and related internal data structures. */
    1855       41529 : void static UpdateTip(CBlockIndex* pindexNew)
    1856             : {
    1857       41529 :     AssertLockHeld(cs_main);
    1858       41529 :     chainActive.SetTip(pindexNew);
    1859             : 
    1860             :     // New best block
    1861       41529 :     mempool.AddTransactionsUpdated(1);
    1862             : 
    1863       41529 :     {
    1864       41529 :         LOCK(g_best_block_mutex);
    1865       41529 :         g_best_block = pindexNew->GetBlockHash();
    1866       41529 :         g_best_block_time = pindexNew->GetBlockTime();
    1867       41529 :         g_best_block_cv.notify_all();
    1868             :     }
    1869             : 
    1870       41529 :     const CBlockIndex* pChainTip = chainActive.Tip();
    1871       41529 :     assert(pChainTip != nullptr);
    1872       83058 :     LogPrintf("%s: new best=%s  height=%d version=%d  log2_work=%.16f  tx=%lu  date=%s progress=%f  cache=%.1fMiB(%utxo)  evodb_cache=%.1fMiB\n",
    1873             :               __func__,
    1874       83058 :               pChainTip->GetBlockHash().GetHex(), pChainTip->nHeight, pChainTip->nVersion, log(pChainTip->nChainWork.getdouble()) / log(2.0), (unsigned long)pChainTip->nChainTx,
    1875       41529 :               FormatISO8601DateTime(pChainTip->GetBlockTime()),
    1876       41529 :               Checkpoints::GuessVerificationProgress(pChainTip), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize(),
    1877       41529 :               evoDb->GetMemoryUsage() * (1.0 / (1<<20)));
    1878             : 
    1879             :     // Check the version of the last 100 blocks to see if we need to upgrade:
    1880       41529 :     static bool fWarned = false;
    1881       41529 :     if (!IsInitialBlockDownload() && !fWarned) {
    1882       40723 :         int nUpgraded = 0;
    1883       40723 :         const CBlockIndex* pindex = pChainTip;
    1884     3350083 :         for (int i = 0; i < 100 && pindex != nullptr; i++) {
    1885     3309365 :             if (pindex->nVersion > CBlock::CURRENT_VERSION)
    1886        2652 :                 ++nUpgraded;
    1887     3309365 :             pindex = pindex->pprev;
    1888             :         }
    1889       40723 :         if (nUpgraded > 0)
    1890         102 :             LogPrintf("SetBestChain: %d of last 100 blocks above version %d\n", nUpgraded, (int)CBlock::CURRENT_VERSION);
    1891       40723 :         if (nUpgraded > 100 / 2) {
    1892           4 :             std::string strWarning = _("Warning: This version is obsolete, upgrade required!");
    1893           2 :             SetMiscWarning(strWarning);
    1894           2 :             if (!fWarned) {
    1895           2 :                 AlertNotify(strWarning);
    1896           2 :                 fWarned = true;
    1897             :             }
    1898             :         }
    1899             :     }
    1900       41529 : }
    1901             : 
    1902             : /** Disconnect chainActive's tip.
    1903             :   * After calling, the mempool will be in an inconsistent state, with
    1904             :   * transactions from disconnected blocks being added to disconnectpool.  You
    1905             :   * should make the mempool consistent again by calling UpdateMempoolForReorg.
    1906             :   * with cs_main held.
    1907             :   *
    1908             :   * If disconnectpool is nullptr, then no disconnected transactions are added to
    1909             :   * disconnectpool (note that the caller is responsible for mempool consistency
    1910             :   * in any case).
    1911             :   */
    1912         283 : bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool)
    1913             : {
    1914         283 :     AssertLockHeld(cs_main);
    1915         283 :     AssertLockHeld(mempool.cs);
    1916         283 :     CBlockIndex* pindexDelete = chainActive.Tip();
    1917         283 :     assert(pindexDelete);
    1918             :     // Read block from disk.
    1919         566 :     std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
    1920         283 :     CBlock& block = *pblock;
    1921         283 :     if (!ReadBlockFromDisk(block, pindexDelete))
    1922           0 :         return error("%s: Failed to read block", __func__);
    1923             :     // Apply the block atomically to the chain state.
    1924         283 :     const uint256& saplingAnchorBeforeDisconnect = pcoinsTip->GetBestAnchor();
    1925         283 :     int64_t nStart = GetTimeMicros();
    1926         283 :     {
    1927         565 :         auto dbTx = evoDb->BeginTransaction();
    1928             : 
    1929         565 :         CCoinsViewCache view(pcoinsTip.get());
    1930         283 :         assert(view.GetBestBlock() == pindexDelete->GetBlockHash());
    1931         283 :         if (DisconnectBlock(block, pindexDelete, view) != DISCONNECT_OK)
    1932           2 :             return error("DisconnectTip() : DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
    1933         282 :         bool flushed = view.Flush();
    1934         282 :         assert(flushed);
    1935         282 :         dbTx->Commit();
    1936             :     }
    1937         282 :     LogPrint(BCLog::BENCHMARK, "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
    1938         282 :     const uint256& saplingAnchorAfterDisconnect = pcoinsTip->GetBestAnchor();
    1939             :     // Write the chain state to disk, if necessary.
    1940         282 :     if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
    1941             :         return false;
    1942         282 :     if (disconnectpool) {
    1943             :         // Save transactions to re-add to mempool at end of reorg
    1944       40234 :         for (auto it = block.vtx.rbegin(); it != block.vtx.rend(); ++it) {
    1945       39952 :             disconnectpool->addTransaction(*it);
    1946             :         }
    1947         303 :         while (disconnectpool->DynamicMemoryUsage() > MAX_DISCONNECTED_TX_POOL_SIZE * 1000) {
    1948             :             // Drop the earliest entry, and remove its children from the mempool.
    1949          21 :             auto it = disconnectpool->queuedTx.get<insertion_order>().begin();
    1950          21 :             mempool.removeRecursive(**it, MemPoolRemovalReason::REORG);
    1951          21 :             disconnectpool->removeEntry(it);
    1952             :         }
    1953             :     }
    1954             : 
    1955             :     // Evict from mempool if the anchor changes
    1956         282 :     if (saplingAnchorBeforeDisconnect != saplingAnchorAfterDisconnect) {
    1957             :         // The anchor may not change between block disconnects,
    1958             :         // in which case we don't want to evict from the mempool yet!
    1959           4 :         mempool.removeWithAnchor(saplingAnchorBeforeDisconnect);
    1960             :     }
    1961             :     // Update chainActive and related variables.
    1962         282 :     UpdateTip(pindexDelete->pprev);
    1963             :     // Let wallets know transactions went from 1-confirmed to
    1964             :     // 0-confirmed or conflicted:
    1965         282 :     GetMainSignals().BlockDisconnected(pblock, pindexDelete->GetBlockHash(), pindexDelete->nHeight, pindexDelete->GetBlockTime());
    1966             : 
    1967             :     // Update MN manager cache
    1968         282 :     deterministicMNManager->SetTipIndex(pindexDelete->pprev);
    1969             :     // replace the cached hash of pindexDelete with the hash of the block
    1970             :     // at depth CACHED_BLOCK_HASHES if it exists, or empty hash otherwise.
    1971         282 :     if ((unsigned) pindexDelete->nHeight >= CACHED_BLOCK_HASHES) {
    1972         232 :         mnodeman.CacheBlockHash(chainActive[pindexDelete->nHeight - CACHED_BLOCK_HASHES]);
    1973             :     } else {
    1974         166 :         mnodeman.UncacheBlockHash(pindexDelete);
    1975             :     }
    1976             : 
    1977             :     return true;
    1978             : }
    1979             : 
    1980             : static int64_t nTimeReadFromDisk = 0;
    1981             : static int64_t nTimeConnectTotal = 0;
    1982             : static int64_t nTimeFlush = 0;
    1983             : static int64_t nTimeChainState = 0;
    1984             : static int64_t nTimePostConnect = 0;
    1985             : 
    1986      165450 : struct PerBlockConnectTrace {
    1987             :     CBlockIndex* pindex = nullptr;
    1988             :     std::shared_ptr<const CBlock> pblock;
    1989       82934 :     PerBlockConnectTrace() {}
    1990             : };
    1991             : /**
    1992             :  * Used to track blocks whose transactions were applied to the UTXO state as a
    1993             :  * part of a single ActivateBestChainStep call.
    1994             :  *
    1995             :  * This class is single-use, once you call GetBlocksConnected() you have to throw
    1996             :  * it away and make a new one.
    1997             :  */
    1998         461 : class ConnectTrace {
    1999             : private:
    2000             :     std::vector<PerBlockConnectTrace> blocksConnected;
    2001             : 
    2002             : public:
    2003       83374 :     ConnectTrace() : blocksConnected(1) {}
    2004             : 
    2005       41247 :     void BlockConnected(CBlockIndex* pindex, std::shared_ptr<const CBlock> pblock) {
    2006       41247 :         assert(!blocksConnected.back().pindex);
    2007       41247 :         assert(pindex);
    2008       41247 :         assert(pblock);
    2009       41247 :         blocksConnected.back().pindex = pindex;
    2010       41247 :         blocksConnected.back().pblock = std::move(pblock);
    2011       41247 :         blocksConnected.emplace_back();
    2012       41247 :     }
    2013             : 
    2014       41225 :     std::vector<PerBlockConnectTrace>& GetBlocksConnected() {
    2015             :         // We always keep one extra block at the end of our list because
    2016             :         // blocks are added after all the conflicted transactions have
    2017             :         // been filled in. Thus, the last entry should always be an empty
    2018             :         // one waiting for the transactions from the next block. We pop
    2019             :         // the last entry here to make sure the list we return is sane.
    2020       41225 :         assert(!blocksConnected.back().pindex);
    2021       41225 :         blocksConnected.pop_back();
    2022       41225 :         return blocksConnected;
    2023             :     }
    2024             : };
    2025             : 
    2026             : /**
    2027             :  * Connect a new block to chainActive. pblock is either nullptr or a pointer to a CBlock
    2028             :  * corresponding to pindexNew, to bypass loading it again from disk.
    2029             :  *
    2030             :  * The block is added to connectTrace if connection succeeds.
    2031             :  */
    2032       41292 : bool static ConnectTip(CValidationState& state, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    2033             : {
    2034       41292 :     AssertLockHeld(cs_main);
    2035       41292 :     AssertLockHeld(mempool.cs);
    2036       82266 :     assert(pindexNew->pprev == chainActive.Tip());
    2037             : 
    2038             :     // Read block from disk.
    2039       41292 :     int64_t nTime1 = GetTimeMicros();
    2040       41292 :     std::shared_ptr<const CBlock> pthisBlock;
    2041       41292 :     if (!pblock) {
    2042        1134 :         std::shared_ptr<CBlock> pblockNew = std::make_shared<CBlock>();
    2043         567 :         if (!ReadBlockFromDisk(*pblockNew, pindexNew))
    2044           0 :             return AbortNode(state, "Failed to read block");
    2045         567 :         pthisBlock = pblockNew;
    2046             :     } else {
    2047       40725 :         pthisBlock = pblock;
    2048             :     }
    2049       41292 :     const CBlock& blockConnecting = *pthisBlock;
    2050             : 
    2051             :     // Apply the block atomically to the chain state.
    2052       41292 :     int64_t nTime2 = GetTimeMicros();
    2053       41292 :     nTimeReadFromDisk += nTime2 - nTime1;
    2054       41292 :     int64_t nTime3;
    2055       41292 :     LogPrint(BCLog::BENCHMARK, "  - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001);
    2056       41292 :     {
    2057       82539 :         auto dbTx = evoDb->BeginTransaction();
    2058             : 
    2059       82539 :         CCoinsViewCache view(pcoinsTip.get());
    2060       41292 :         bool rv = ConnectBlock(blockConnecting, state, pindexNew, view, false);
    2061       41292 :         GetMainSignals().BlockChecked(blockConnecting, state);
    2062       41292 :         if (!rv) {
    2063          45 :             if (state.IsInvalid())
    2064          45 :                 InvalidBlockFound(pindexNew, state);
    2065         124 :             return error("%s: ConnectBlock %s failed, %s", __func__, pindexNew->GetBlockHash().ToString(), FormatStateMessage(state));
    2066             :         }
    2067       41247 :         nTime3 = GetTimeMicros();
    2068       41247 :         nTimeConnectTotal += nTime3 - nTime2;
    2069       41247 :         LogPrint(BCLog::BENCHMARK, "  - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001);
    2070       41247 :         bool flushed = view.Flush();
    2071       41247 :         assert(flushed);
    2072       41247 :         dbTx->Commit();
    2073             :     }
    2074       41247 :     int64_t nTime4 = GetTimeMicros();
    2075       41247 :     nTimeFlush += nTime4 - nTime3;
    2076       41247 :     LogPrint(BCLog::BENCHMARK, "  - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001);
    2077             : 
    2078             :     // Write the chain state to disk, if necessary. Always write to disk if this is the first of a new file.
    2079       41247 :     FlushStateMode flushMode = FLUSH_STATE_IF_NEEDED;
    2080       41247 :     if (pindexNew->pprev && (pindexNew->GetBlockPos().nFile != pindexNew->pprev->GetBlockPos().nFile))
    2081             :         flushMode = FLUSH_STATE_ALWAYS;
    2082       41247 :     if (!FlushStateToDisk(state, flushMode))
    2083             :         return false;
    2084       41247 :     int64_t nTime5 = GetTimeMicros();
    2085       41247 :     nTimeChainState += nTime5 - nTime4;
    2086       41247 :     LogPrint(BCLog::BENCHMARK, "  - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001);
    2087             : 
    2088             :     // Remove conflicting transactions from the mempool.
    2089       41247 :     mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight);
    2090       41247 :     disconnectpool.removeForBlock(blockConnecting.vtx);
    2091             :     // Update chainActive & related variables.
    2092       41247 :     UpdateTip(pindexNew);
    2093             :     // Update TierTwo managers
    2094       41247 :     mnodeman.SetBestHeight(pindexNew->nHeight);
    2095       41247 :     g_budgetman.SetBestHeight(pindexNew->nHeight);
    2096             :     // Update MN manager cache
    2097       41247 :     mnodeman.CacheBlockHash(pindexNew);
    2098       41247 :     mnodeman.CheckSpentCollaterals(blockConnecting.vtx);
    2099       41247 :     deterministicMNManager->SetTipIndex(pindexNew);
    2100             : 
    2101       41247 :     int64_t nTime6 = GetTimeMicros();
    2102       41247 :     nTimePostConnect += nTime6 - nTime5;
    2103       41247 :     nTimeTotal += nTime6 - nTime1;
    2104       41247 :     LogPrint(BCLog::BENCHMARK, "  - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
    2105       41247 :     LogPrint(BCLog::BENCHMARK, "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001);
    2106             : 
    2107       41247 :     connectTrace.BlockConnected(pindexNew, std::move(pthisBlock));
    2108       41247 :     return true;
    2109             : }
    2110             : 
    2111             : /**
    2112             :  * Return the tip of the chain with the most work in it, that isn't
    2113             :  * known to be invalid (it's however far from certain to be valid).
    2114             :  */
    2115       41521 : static CBlockIndex* FindMostWorkChain()
    2116             : {
    2117       41527 :     do {
    2118       41524 :         CBlockIndex* pindexNew = nullptr;
    2119             : 
    2120             :         // Find the best candidate header.
    2121       41524 :         {
    2122       41524 :             std::set<CBlockIndex*, CBlockIndexWorkComparator>::reverse_iterator it = setBlockIndexCandidates.rbegin();
    2123       41524 :             if (it == setBlockIndexCandidates.rend())
    2124             :                 return nullptr;
    2125       41524 :             pindexNew = *it;
    2126             :         }
    2127             : 
    2128             :         // Check whether all blocks on the path between the currently active chain and the candidate are valid.
    2129             :         // Just going until the active chain is an optimization, as we know all blocks in it are valid already.
    2130       41524 :         CBlockIndex* pindexTest = pindexNew;
    2131       41524 :         bool fInvalidAncestor = false;
    2132      165334 :         while (pindexTest && !chainActive.Contains(pindexTest)) {
    2133       41305 :             assert(pindexTest->nChainTx || pindexTest->nHeight == 0);
    2134             : 
    2135             :             // Pruned nodes may have entries in setBlockIndexCandidates for
    2136             :             // which block files have been deleted.  Remove those as candidates
    2137             :             // for the most work chain if we come across them; we can't switch
    2138             :             // to a chain unless we have all the non-active-chain parent blocks.
    2139       41305 :             bool fFailedChain = pindexTest->nStatus & BLOCK_FAILED_MASK;
    2140       41305 :             bool fMissingData = !(pindexTest->nStatus & BLOCK_HAVE_DATA);
    2141       41305 :             if (fFailedChain || fMissingData) {
    2142             :                 // Candidate chain is not usable (either invalid or missing data)
    2143           3 :                 if (fFailedChain && (pindexBestInvalid == nullptr || pindexNew->nChainWork > pindexBestInvalid->nChainWork))
    2144           0 :                     pindexBestInvalid = pindexNew;
    2145           3 :                 CBlockIndex* pindexFailed = pindexNew;
    2146             :                 // Remove the entire chain from the set.
    2147           6 :                 while (pindexTest != pindexFailed) {
    2148           3 :                     if (fFailedChain) {
    2149           3 :                         pindexFailed->nStatus |= BLOCK_FAILED_CHILD;
    2150           0 :                     } else if (fMissingData) {
    2151             :                         // If we're missing data, then add back to mapBlocksUnlinked,
    2152             :                         // so that if the block arrives in the future we can try adding
    2153             :                         // to setBlockIndexCandidates again.
    2154           0 :                         mapBlocksUnlinked.emplace(pindexFailed->pprev, pindexFailed);
    2155             :                     }
    2156           3 :                     setBlockIndexCandidates.erase(pindexFailed);
    2157           3 :                     pindexFailed = pindexFailed->pprev;
    2158             :                 }
    2159           3 :                 setBlockIndexCandidates.erase(pindexTest);
    2160           3 :                 fInvalidAncestor = true;
    2161           3 :                 break;
    2162             :             }
    2163       41302 :             pindexTest = pindexTest->pprev;
    2164             :         }
    2165           3 :         if (!fInvalidAncestor)
    2166           3 :             return pindexNew;
    2167             :     } while (true);
    2168             : }
    2169             : 
    2170             : /** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */
    2171       41404 : static void PruneBlockIndexCandidates()
    2172             : {
    2173             :     // Note that we can't delete the current block itself, as we may need to return to it later in case a
    2174             :     // reorganization to a better block fails.
    2175       41404 :     std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin();
    2176      229916 :     while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.Tip())) {
    2177       73554 :         setBlockIndexCandidates.erase(it++);
    2178             :     }
    2179             :     // Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates.
    2180       41404 :     assert(!setBlockIndexCandidates.empty());
    2181       41404 : }
    2182             : 
    2183             : /**
    2184             :  * Try to make some progress towards making pindexMostWork the active block.
    2185             :  * pblock is either nullptr or a pointer to a CBlock corresponding to pindexMostWork.
    2186             :  */
    2187       41226 : static bool ActivateBestChainStep(CValidationState& state, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    2188             : {
    2189       41226 :     AssertLockHeld(cs_main);
    2190       41226 :     AssertLockHeld(mempool.cs);
    2191       41226 :     const CBlockIndex* pindexOldTip = chainActive.Tip();
    2192       41226 :     const CBlockIndex* pindexFork = chainActive.FindFork(pindexMostWork);
    2193             : 
    2194             :     // Disconnect active blocks which are no longer in the best chain.
    2195       41226 :     bool fBlocksDisconnected = false;
    2196       41226 :     DisconnectedBlockTransactions disconnectpool;
    2197       41299 :     while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
    2198          74 :         if (!DisconnectTip(state, Params(), &disconnectpool)) {
    2199             :             // This is likely a fatal error, but keep the mempool consistent,
    2200             :             // just in case. Only remove from the mempool in this case.
    2201           1 :             UpdateMempoolForReorg(disconnectpool, false);
    2202             : 
    2203             :             // If we're unable to disconnect a block during normal operation,
    2204             :             // then that is a failure of our local system -- we should abort
    2205             :             // rather than stay on a less work chain.
    2206           2 :             return AbortNode(state, "Failed to disconnect block; see debug.log for details");
    2207             :         }
    2208             :         fBlocksDisconnected = true;
    2209             :     }
    2210             : 
    2211             :     // Build list of new blocks to connect.
    2212       82451 :     std::vector<CBlockIndex*> vpindexToConnect;
    2213       41225 :     bool fContinue = true;
    2214       41225 :     int nHeight = pindexFork ? pindexFork->nHeight : -1;
    2215       82450 :     while (fContinue && nHeight != pindexMostWork->nHeight) {
    2216             :         // Don't iterate the entire list of potential improvements toward the best tip, as we likely only need
    2217             :         // a few blocks along the way.
    2218       41225 :         int nTargetHeight = std::min(nHeight + 32, pindexMostWork->nHeight);
    2219       41225 :         vpindexToConnect.clear();
    2220       41225 :         vpindexToConnect.reserve(nTargetHeight - nHeight);
    2221       41225 :         CBlockIndex* pindexIter = pindexMostWork->GetAncestor(nTargetHeight);
    2222       86476 :         while (pindexIter && pindexIter->nHeight != nHeight) {
    2223       45251 :             vpindexToConnect.push_back(pindexIter);
    2224       45251 :             pindexIter = pindexIter->pprev;
    2225             :         }
    2226       41225 :         nHeight = nTargetHeight;
    2227             : 
    2228             :         // Connect new blocks.
    2229       41295 :         for (CBlockIndex* pindexConnect : reverse_iterate(vpindexToConnect)) {
    2230      123309 :             if (!ConnectTip(state, pindexConnect, (pindexConnect == pindexMostWork) ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool)) {
    2231          45 :                 if (state.IsInvalid()) {
    2232             :                     // The block violates a consensus rule.
    2233          45 :                     if (!state.CorruptionPossible()) {
    2234          45 :                         InvalidChainFound(vpindexToConnect.front());
    2235             :                     }
    2236          45 :                     state = CValidationState();
    2237          45 :                     fInvalidFound = true;
    2238          45 :                     fContinue = false;
    2239          45 :                     break;
    2240             :                 } else {
    2241             :                     // A system error occurred (disk space, database error, ...).
    2242             :                     // Make the mempool consistent with the current tip, just in case
    2243             :                     // any observers try to use it before shutdown.
    2244           0 :                     UpdateMempoolForReorg(disconnectpool, false);
    2245           0 :                     return false;
    2246             :                 }
    2247             :             } else {
    2248       41247 :                 PruneBlockIndexCandidates();
    2249       82176 :                 if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) {
    2250             :                     // We're in a better position than we were. Return temporarily to release the lock.
    2251             :                     fContinue = false;
    2252             :                     break;
    2253             :                 }
    2254             :             }
    2255             :         }
    2256             :     }
    2257             : 
    2258       41225 :     if (fBlocksDisconnected) {
    2259             :         // If any blocks were disconnected, disconnectpool may be non empty.  Add
    2260             :         // any disconnected transactions back to the mempool.
    2261          32 :         UpdateMempoolForReorg(disconnectpool, true);
    2262             :     }
    2263       41225 :     mempool.check(pcoinsTip.get());
    2264             : 
    2265             :     // Callbacks/notifications for a new best chain.
    2266       41225 :     if (fInvalidFound)
    2267          45 :         CheckForkWarningConditionsOnNewFork(vpindexToConnect.back());
    2268             :     else
    2269       41180 :         CheckForkWarningConditions();
    2270             : 
    2271             :     return true;
    2272             : }
    2273             : 
    2274             : /**
    2275             :  * Make the best chain active, in multiple steps. The result is either failure
    2276             :  * or an activated best chain. pblock is either nullptr or a pointer to a block
    2277             :  * that is already loaded (to avoid loading it again from disk).
    2278             :  */
    2279             : 
    2280       41476 : bool ActivateBestChain(CValidationState& state, std::shared_ptr<const CBlock> pblock)
    2281             : {
    2282             :     // Note that while we're often called here from ProcessNewBlock, this is
    2283             :     // far from a guarantee. Things in the P2P/RPC will often end up calling
    2284             :     // us in the middle of ProcessNewBlock - do not assume pblock is set
    2285             :     // sanely for performance or correctness!
    2286       41476 :     AssertLockNotHeld(cs_main);
    2287             : 
    2288             :     // ABC maintains a fair degree of expensive-to-calculate internal state
    2289             :     // because this function periodically releases cs_main so that it does not lock up other threads for too long
    2290             :     // during large connects - and to allow for e.g. the callback queue to drain
    2291             :     // we use m_cs_chainstate to enforce mutual exclusion so that only one caller may execute this function at a time
    2292       82952 :     LOCK(m_cs_chainstate);
    2293             : 
    2294             :     CBlockIndex* pindexNewTip = nullptr;
    2295             :     CBlockIndex* pindexMostWork = nullptr;
    2296       41681 :     do {
    2297       41681 :         boost::this_thread::interruption_point();
    2298             : 
    2299       41681 :         if (GetMainSignals().CallbacksPending() > 10) {
    2300             :             // Block until the validation queue drains. This should largely
    2301             :             // never happen in normal operation, however may happen during
    2302             :             // reindex, causing memory blowup  if we run too far ahead.
    2303         210 :             SyncWithValidationInterfaceQueue();
    2304             :         }
    2305             : 
    2306       41681 :         {
    2307       41681 :             LOCK(cs_main);
    2308       82900 :             LOCK(mempool.cs); // Lock transaction pool for at least as long as it takes for connectTrace to be consumed
    2309       41681 :             CBlockIndex* starting_tip = chainActive.Tip();
    2310       41681 :             bool blocks_connected = false;
    2311       41687 :             do {
    2312             :                 // We absolutely may not unlock cs_main until we've made forward progress
    2313             :                 // (with the exception of shutdown due to hardware issues, low disk space, etc).
    2314       41687 :                 ConnectTrace connectTrace; // Destructed before cs_main is unlocked
    2315             : 
    2316       41687 :                 if (pindexMostWork == nullptr) {
    2317       41521 :                     pindexMostWork = FindMostWorkChain();
    2318             :                 }
    2319             : 
    2320             :                 // Whether we have anything to do at all.
    2321       83374 :                 if (pindexMostWork == nullptr || pindexMostWork == chainActive.Tip()) {
    2322             :                     break;
    2323             :                 }
    2324             : 
    2325       41226 :                 bool fInvalidFound = false;
    2326       41225 :                 std::shared_ptr<const CBlock> nullBlockPtr;
    2327       41232 :                 if (!ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : nullBlockPtr, fInvalidFound, connectTrace))
    2328           1 :                     return false;
    2329       41225 :                 blocks_connected = true;
    2330             : 
    2331       41225 :                 if (fInvalidFound) {
    2332             :                     // Wipe cache, we may need another branch now.
    2333          45 :                     pindexMostWork = nullptr;
    2334             :                 }
    2335       41225 :                 pindexNewTip = chainActive.Tip();
    2336             : 
    2337       82472 :                 for (const PerBlockConnectTrace& trace : connectTrace.GetBlocksConnected()) {
    2338       41247 :                     assert(trace.pblock && trace.pindex);
    2339       41247 :                     GetMainSignals().BlockConnected(trace.pblock, trace.pindex);
    2340             :                 }
    2341       41225 :             } while (!chainActive.Tip() || (starting_tip && CBlockIndexWorkComparator()(chainActive.Tip(), starting_tip)));
    2342       41680 :             if (!blocks_connected) return true;
    2343             : 
    2344       41219 :             const CBlockIndex* pindexFork = chainActive.FindFork(starting_tip);
    2345       41219 :             bool fInitialDownload = IsInitialBlockDownload();
    2346             : 
    2347             :             // Notify external listeners about the new tip.
    2348             :             // Enqueue while holding cs_main to ensure that UpdatedBlockTip is called in the order in which blocks are connected
    2349       41219 :             if (pindexFork != pindexNewTip) {
    2350             :                 // Notify ValidationInterface subscribers
    2351       41174 :                 GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);
    2352             : 
    2353             :                 // Always notify the UI if a new block tip was connected
    2354       41174 :                 uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip);
    2355             :             }
    2356             :         }
    2357             : 
    2358             :         // We check shutdown only after giving ActivateBestChainStep a chance to run once so that we
    2359             :         // never shutdown before connecting the genesis block during LoadChainTip(). Previously this
    2360             :         // caused an assert() failure during shutdown in such cases as the UTXO DB flushing checks
    2361             :         // that the best block hash is non-null.
    2362       41219 :         if (ShutdownRequested())
    2363             :             break;
    2364       82370 :     } while (pindexMostWork != chainActive.Tip());
    2365             : 
    2366       41014 :     CheckBlockIndex();
    2367             : 
    2368             :     // Write changes periodically to disk, after relay.
    2369       41014 :     if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC)) {
    2370           0 :         return false;
    2371             :     }
    2372             : 
    2373             :     return true;
    2374             : }
    2375             : 
    2376          30 : bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex)
    2377             : {
    2378          30 :     AssertLockHeld(cs_main);
    2379             :     // Mark the block itself as invalid.
    2380          30 :     pindex->nStatus |= BLOCK_FAILED_VALID;
    2381          30 :     setDirtyBlockIndex.insert(pindex);
    2382          30 :     setBlockIndexCandidates.erase(pindex);
    2383             : 
    2384          60 :     LOCK(mempool.cs); // Lock for as long as disconnectpool is in scope to make sure UpdateMempoolForReorg is called after DisconnectTip without unlocking in between
    2385          60 :     DisconnectedBlockTransactions disconnectpool;
    2386         478 :     while (chainActive.Contains(pindex)) {
    2387         209 :         CBlockIndex* pindexWalk = chainActive.Tip();
    2388         209 :         pindexWalk->nStatus |= BLOCK_FAILED_CHILD;
    2389         209 :         setDirtyBlockIndex.insert(pindexWalk);
    2390         209 :         setBlockIndexCandidates.erase(pindexWalk);
    2391             :         // ActivateBestChain considers blocks already in chainActive
    2392             :         // unconditionally valid already, so force disconnect away from it.
    2393         209 :         if (!DisconnectTip(state, chainparams, &disconnectpool)) {
    2394             :             // It's probably hopeless to try to make the mempool consistent
    2395             :             // here if DisconnectTip failed, but we can try.
    2396           0 :             UpdateMempoolForReorg(disconnectpool, false);
    2397           0 :             return false;
    2398             :         }
    2399             :     }
    2400             : 
    2401             :     // DisconnectTip will add transactions to disconnectpool; try to add these
    2402             :     // back to the mempool.
    2403          30 :     UpdateMempoolForReorg(disconnectpool, true);
    2404             : 
    2405             :     // The resulting new best tip may not be in setBlockIndexCandidates anymore, so
    2406             :     // add it again.
    2407          30 :     BlockMap::iterator it = mapBlockIndex.begin();
    2408       12602 :     while (it != mapBlockIndex.end()) {
    2409       24899 :         if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && !setBlockIndexCandidates.value_comp()(it->second, chainActive.Tip())) {
    2410          38 :             setBlockIndexCandidates.insert(it->second);
    2411             :         }
    2412       12602 :         it++;
    2413             :     }
    2414             : 
    2415          30 :     InvalidChainFound(pindex);
    2416             :     return true;
    2417             : }
    2418             : 
    2419          10 : bool ReconsiderBlock(CValidationState& state, CBlockIndex* pindex)
    2420             : {
    2421          10 :     AssertLockHeld(cs_main);
    2422             : 
    2423          10 :     int nHeight = pindex->nHeight;
    2424             : 
    2425             :     // Remove the invalidity flag from this block and all its descendants.
    2426          10 :     BlockMap::iterator it = mapBlockIndex.begin();
    2427        1744 :     while (it != mapBlockIndex.end()) {
    2428        1734 :         if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) {
    2429         153 :             it->second->nStatus &= ~BLOCK_FAILED_MASK;
    2430         153 :             setDirtyBlockIndex.insert(it->second);
    2431         306 :             if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) {
    2432         152 :                 setBlockIndexCandidates.insert(it->second);
    2433             :             }
    2434         153 :             if (it->second == pindexBestInvalid) {
    2435             :                 // Reset invalid block marker if it was pointing to one of those.
    2436           8 :                 pindexBestInvalid = nullptr;
    2437             :             }
    2438             :         }
    2439        1744 :         it++;
    2440             :     }
    2441             : 
    2442             :     // Remove the invalidity flag from all ancestors too.
    2443        1570 :     while (pindex != nullptr) {
    2444        1560 :         if (pindex->nStatus & BLOCK_FAILED_MASK) {
    2445           1 :             pindex->nStatus &= ~BLOCK_FAILED_MASK;
    2446           1 :             setDirtyBlockIndex.insert(pindex);
    2447             :         }
    2448        1560 :         pindex = pindex->pprev;
    2449             :     }
    2450          10 :     return true;
    2451             : }
    2452             : 
    2453       41174 : static CBlockIndex* AddToBlockIndex(const CBlock& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    2454             : {
    2455       41174 :     AssertLockHeld(cs_main);
    2456             : 
    2457             :     // Check for duplicate
    2458       41174 :     uint256 hash = block.GetHash();
    2459       41174 :     CBlockIndex* pindex = LookupBlockIndex(hash);
    2460       41174 :     if (pindex)
    2461             :         return pindex;
    2462             : 
    2463             :     // Construct new block index object
    2464       41174 :     CBlockIndex* pindexNew = new CBlockIndex(block);
    2465             :     // We assign the sequence id to blocks only when the full data is available,
    2466             :     // to avoid miners withholding blocks but broadcasting headers, to get a
    2467             :     // competitive advantage.
    2468       41174 :     pindexNew->nSequenceId = 0;
    2469       41174 :     BlockMap::iterator mi = mapBlockIndex.emplace(hash, pindexNew).first;
    2470             : 
    2471       41174 :     pindexNew->phashBlock = &((*mi).first);
    2472       41174 :     CBlockIndex* pprev = LookupBlockIndex(block.hashPrevBlock);
    2473       41174 :     if (pprev) {
    2474       40858 :         pindexNew->pprev = pprev;
    2475       40858 :         pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
    2476       40858 :         pindexNew->BuildSkip();
    2477             : 
    2478       40858 :         const Consensus::Params& consensus = Params().GetConsensus();
    2479       40858 :         if (!consensus.NetworkUpgradeActive(pindexNew->nHeight, Consensus::UPGRADE_V3_4)) {
    2480             :             // compute and set new V1 stake modifier (entropy bits)
    2481       34346 :             pindexNew->SetNewStakeModifier();
    2482             : 
    2483             :         } else {
    2484             :             // compute and set new V2 stake modifier (hash of prevout and prevModifier)
    2485        6512 :             pindexNew->SetNewStakeModifier(block.vtx[1]->vin[0].prevout.hash);
    2486             :         }
    2487             :     }
    2488       57944 :     pindexNew->nTimeMax = (pindexNew->pprev ? std::max(pindexNew->pprev->nTimeMax, pindexNew->nTime) : pindexNew->nTime);
    2489      494088 :     pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew);
    2490       41174 :     pindexNew->RaiseValidity(BLOCK_VALID_TREE);
    2491       41174 :     if (pindexBestHeader == nullptr || pindexBestHeader->nChainWork < pindexNew->nChainWork)
    2492       40979 :         pindexBestHeader = pindexNew;
    2493             : 
    2494       41174 :     setDirtyBlockIndex.insert(pindexNew);
    2495             :     // track prevBlockHash -> pindex (multimap)
    2496       41174 :     if (pindexNew->pprev) {
    2497       40858 :         mapPrevBlockIndex.emplace(pindexNew->pprev->GetBlockHash(), pindexNew);
    2498             :     }
    2499             : 
    2500       41174 :     return pindexNew;
    2501             : }
    2502             : 
    2503             : /** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
    2504       41154 : bool ReceivedBlockTransactions(const CBlock& block, CValidationState& state, CBlockIndex* pindexNew, const FlatFilePos& pos)
    2505             : {
    2506       41154 :     if (block.IsProofOfStake())
    2507        6559 :         pindexNew->SetProofOfStake();
    2508       41154 :     pindexNew->nTx = block.vtx.size();
    2509       41154 :     pindexNew->nChainTx = 0;
    2510             : 
    2511             :     // Sapling
    2512       41154 :     CAmount saplingValue = 0;
    2513      283828 :     for (const auto& tx : block.vtx) {
    2514      246833 :         if (tx->IsShieldedTx()) {
    2515             :             // Negative valueBalance "takes" money from the transparent value pool
    2516             :             // and adds it to the Sapling value pool. Positive valueBalance "gives"
    2517             :             // money to the transparent value pool, removing from the Sapling value
    2518             :             // pool. So we invert the sign here.
    2519        1460 :             saplingValue += -tx->sapData->valueBalance;
    2520             :         }
    2521             :     }
    2522       41154 :     pindexNew->nSaplingValue = saplingValue;
    2523       41154 :     pindexNew->nChainSaplingValue = nullopt;
    2524             : 
    2525       41154 :     pindexNew->nFile = pos.nFile;
    2526       41154 :     pindexNew->nDataPos = pos.nPos;
    2527       41154 :     pindexNew->nUndoPos = 0;
    2528       41154 :     pindexNew->nStatus |= BLOCK_HAVE_DATA;
    2529       41154 :     pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
    2530       41154 :     setDirtyBlockIndex.insert(pindexNew);
    2531             : 
    2532       41154 :     if (pindexNew->pprev == nullptr || pindexNew->pprev->nChainTx) {
    2533             :         // If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS.
    2534       41154 :         std::deque<CBlockIndex*> queue;
    2535       41154 :         queue.push_back(pindexNew);
    2536             : 
    2537             :         // Recursively process any descendant blocks that now may be eligible to be connected.
    2538       82308 :         while (!queue.empty()) {
    2539       41154 :             CBlockIndex* pindex = queue.front();
    2540       41154 :             queue.pop_front();
    2541       41154 :             pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx;
    2542             : 
    2543             :             // Sapling, update chain value
    2544       41154 :             pindex->SetChainSaplingValue();
    2545             : 
    2546       41154 :             {
    2547       41154 :                 LOCK(cs_nBlockSequenceId);
    2548       41154 :                 pindex->nSequenceId = nBlockSequenceId++;
    2549             :             }
    2550       41154 :             if (chainActive.Tip() == nullptr || !setBlockIndexCandidates.value_comp()(pindex, chainActive.Tip())) {
    2551       41040 :                 setBlockIndexCandidates.insert(pindex);
    2552             :             }
    2553       41154 :             std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = mapBlocksUnlinked.equal_range(pindex);
    2554       41154 :             while (range.first != range.second) {
    2555           0 :                 std::multimap<CBlockIndex*, CBlockIndex*>::iterator it = range.first;
    2556           0 :                 queue.push_back(it->second);
    2557           0 :                 range.first++;
    2558           0 :                 mapBlocksUnlinked.erase(it);
    2559             :             }
    2560       41154 :         }
    2561             :     } else {
    2562           0 :         if (pindexNew->pprev && pindexNew->pprev->IsValid(BLOCK_VALID_TREE)) {
    2563           0 :             mapBlocksUnlinked.emplace(pindexNew->pprev, pindexNew);
    2564             :         }
    2565             :     }
    2566             : 
    2567       41154 :     return true;
    2568             : }
    2569             : 
    2570       41154 : bool FindBlockPos(CValidationState& state, FlatFilePos& pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false)
    2571             : {
    2572       82308 :     LOCK(cs_LastBlockFile);
    2573             : 
    2574       41154 :     unsigned int nFile = fKnown ? pos.nFile : nLastBlockFile;
    2575       41154 :     if (vinfoBlockFile.size() <= nFile) {
    2576         123 :         vinfoBlockFile.resize(nFile + 1);
    2577             :     }
    2578             : 
    2579       41154 :     if (!fKnown) {
    2580       40811 :         while (vinfoBlockFile[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) {
    2581           1 :             nFile++;
    2582           1 :             if (vinfoBlockFile.size() <= nFile) {
    2583           1 :                 vinfoBlockFile.resize(nFile + 1);
    2584             :             }
    2585             :         }
    2586       40810 :         pos.nFile = nFile;
    2587       40810 :         pos.nPos = vinfoBlockFile[nFile].nSize;
    2588             :     }
    2589             : 
    2590       41154 :     if ((int)nFile != nLastBlockFile) {
    2591           1 :         if (!fKnown) {
    2592           2 :             LogPrintf("Leaving block file %i: %s\n", nFile, vinfoBlockFile[nFile].ToString());
    2593             :         }
    2594           1 :         FlushBlockFile(!fKnown);
    2595           1 :         nLastBlockFile = nFile;
    2596             :     }
    2597             : 
    2598       41154 :     vinfoBlockFile[nFile].AddBlock(nHeight, nTime);
    2599       41154 :     if (fKnown)
    2600         344 :         vinfoBlockFile[nFile].nSize = std::max(pos.nPos + nAddSize, vinfoBlockFile[nFile].nSize);
    2601             :     else
    2602       40810 :         vinfoBlockFile[nFile].nSize += nAddSize;
    2603             : 
    2604       41154 :     if (!fKnown) {
    2605       40810 :         bool out_of_space;
    2606       40810 :         BlockFileSeq().Allocate(pos, nAddSize, out_of_space);
    2607       40810 :         if (out_of_space) {
    2608           0 :             return AbortNode("Disk space is low!", _("Error: Disk space is low!"));
    2609             :         }
    2610             :         // future: add prunning flag check
    2611             :     }
    2612             : 
    2613       41154 :     setDirtyFileInfo.insert(nFile);
    2614       41154 :     return true;
    2615             : }
    2616             : 
    2617       40744 : bool FindUndoPos(CValidationState& state, int nFile, FlatFilePos& pos, unsigned int nAddSize)
    2618             : {
    2619       40744 :     pos.nFile = nFile;
    2620             : 
    2621       81488 :     LOCK(cs_LastBlockFile);
    2622             : 
    2623       40744 :     pos.nPos = vinfoBlockFile[nFile].nUndoSize;
    2624       40744 :     vinfoBlockFile[nFile].nUndoSize += nAddSize;
    2625       40744 :     setDirtyFileInfo.insert(nFile);
    2626             : 
    2627       40744 :     bool out_of_space;
    2628       40744 :     UndoFileSeq().Allocate(pos, nAddSize, out_of_space);
    2629       40744 :     if (out_of_space) {
    2630           0 :         return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!"));
    2631             :     }
    2632             :     // future: add prunning flag check
    2633             : 
    2634             :     return true;
    2635             : }
    2636             : 
    2637       10307 : bool CheckColdStakeFreeOutput(const CTransaction& tx, const int nHeight)
    2638             : {
    2639       10307 :     assert(tx.IsCoinStake());
    2640             :     // This check applies only to coinstakes spending a P2CS_LOF script.
    2641             :     // The script-check ensures that all but the first and the last output
    2642             :     // (if the coinstake has more than 3 outputs) have the same scriptPubKey.
    2643             :     // If the second script is not a P2CS_LOF, then either this is a "regular"
    2644             :     // P2PKH stake, or it fails the script verification.
    2645       10307 :     if (!tx.vout[1].scriptPubKey.IsPayToColdStakingLOF()) {
    2646             :         return true;
    2647             :     }
    2648             :     // If the last output is different, then it can be either a masternode
    2649             :     // or a budget proposal payment
    2650           9 :     const unsigned int outs = tx.vout.size();
    2651           9 :     const CTxOut& lastOut = tx.vout[outs-1];
    2652           9 :     if (outs >=3 && lastOut.scriptPubKey != tx.vout[outs-2].scriptPubKey) {
    2653           1 :         if (Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V6_0)) {
    2654             :             // after v6.0, masternode and budgets are paid in the coinbase. No more free outputs allowed.
    2655             :             return false;
    2656             :         }
    2657           1 :         if (lastOut.nValue == GetMasternodePayment(nHeight))
    2658             :             return true;
    2659             : 
    2660             :         // if mnsync is incomplete, we cannot verify if this is a budget block.
    2661             :         // so we check that the staker is not transferring value to the free output
    2662           1 :         if (!g_tiertwo_sync_state.IsSynced()) {
    2663             :             // First try finding the previous transaction in database
    2664           0 :             CTransactionRef txPrev; uint256 hashBlock;
    2665           0 :             if (!GetTransaction(tx.vin[0].prevout.hash, txPrev, hashBlock, true))
    2666           0 :                 return error("%s : read txPrev failed: %s",  __func__, tx.vin[0].prevout.hash.GetHex());
    2667           0 :             CAmount amtIn = txPrev->vout[tx.vin[0].prevout.n].nValue + GetBlockValue(nHeight);
    2668           0 :             CAmount amtOut = 0;
    2669           0 :             for (unsigned int i = 1; i < outs-1; i++) amtOut += tx.vout[i].nValue;
    2670           0 :             if (amtOut != amtIn)
    2671           0 :                 return error("%s: non-free outputs value %d less than required %d", __func__, amtOut, amtIn);
    2672             :             return true;
    2673             :         }
    2674             : 
    2675             :         // Check that this is indeed a superblock.
    2676           1 :         if (g_budgetman.IsBudgetPaymentBlock(nHeight)) {
    2677             :             // if superblocks are not enabled, reject
    2678           0 :             if (!sporkManager.IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS))
    2679           0 :                 return error("%s: superblocks are not enabled", __func__);
    2680             :             return true;
    2681             :         }
    2682             : 
    2683             :         // wrong free output
    2684           2 :         return error("%s: Wrong cold staking outputs: vout[%d].scriptPubKey (%s) != vout[%d].scriptPubKey (%s) - value: %s",
    2685           5 :                 __func__, outs-1, HexStr(lastOut.scriptPubKey), outs-2, HexStr(tx.vout[outs-2].scriptPubKey), FormatMoney(lastOut.nValue).c_str());
    2686             :     }
    2687             : 
    2688             :     return true;
    2689             : }
    2690             : 
    2691             : // cumulative size of all shielded txes inside a block
    2692         160 : static unsigned int GetTotalShieldedTxSize(const CBlock& block)
    2693             : {
    2694         160 :     unsigned int nSizeShielded = 0;
    2695      468793 :     for (const auto& tx : block.vtx) {
    2696      468633 :         if (tx->IsShieldedTx()) nSizeShielded += tx->GetTotalSize();
    2697             :     }
    2698         160 :     return nSizeShielded;
    2699             : }
    2700             : 
    2701      164847 : bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig)
    2702             : {
    2703      164847 :     AssertLockHeld(cs_main);
    2704             : 
    2705      164847 :     if (block.fChecked)
    2706             :         return true;
    2707             : 
    2708             :     // These are checks that are independent of context.
    2709       82687 :     const bool IsPoS = block.IsProofOfStake();
    2710             : 
    2711             :     // Check that the header is valid (particularly PoW).  This is mostly
    2712             :     // redundant with the call in AcceptBlockHeader.
    2713       82687 :     if (!IsPoS && fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits))
    2714           6 :         return state.DoS(50, false, REJECT_INVALID, "high-hash", false, "proof of work failed");
    2715             : 
    2716             :     // All potential-corruption validation must be done before we do any
    2717             :     // transaction validation, as otherwise we may mark the header as invalid
    2718             :     // because we receive the wrong transactions for it.
    2719             : 
    2720             :     // Check the merkle root.
    2721       82685 :     if (fCheckMerkleRoot) {
    2722       52783 :         bool mutated;
    2723       52783 :         uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated);
    2724       52783 :         if (block.hashMerkleRoot != hashMerkleRoot2)
    2725           3 :             return state.DoS(100, false, REJECT_INVALID, "bad-txnmrklroot", true, "hashMerkleRoot mismatch");
    2726             : 
    2727             :         // Check for merkle tree malleability (CVE-2012-2459): repeating sequences
    2728             :         // of transactions in a block without affecting the merkle root of a block,
    2729             :         // while still invalidating it.
    2730       52782 :         if (mutated)
    2731          20 :             return state.DoS(100, false, REJECT_INVALID, "bad-txns-duplicate", true, "duplicate transaction");
    2732             :     }
    2733             : 
    2734             :     // Size limits
    2735       82679 :     unsigned int nMaxBlockSize = MAX_BLOCK_SIZE_CURRENT;
    2736       82679 :     const unsigned int nBlockSize = ::GetSerializeSize(block, PROTOCOL_VERSION);
    2737       82679 :     if (block.vtx.empty() || block.vtx.size() > nMaxBlockSize || nBlockSize > nMaxBlockSize)
    2738           6 :         return state.DoS(100, false, REJECT_INVALID, "bad-blk-length", false, "size limits failed");
    2739             : 
    2740             :     // Check shielded txes limits (no need to check if the block size is already under 750kB)
    2741       82677 :     if (nBlockSize > MAX_BLOCK_SHIELDED_TXES_SIZE && GetTotalShieldedTxSize(block) > MAX_BLOCK_SHIELDED_TXES_SIZE)
    2742           0 :         return state.DoS(100, false, REJECT_INVALID, "bad-blk-shielded-size", false, "shielded size limits failed");
    2743             : 
    2744             :     // First transaction must be coinbase, the rest must not be
    2745       82677 :     if (block.vtx.empty() || !block.vtx[0]->IsCoinBase())
    2746           3 :         return state.DoS(100, false, REJECT_INVALID, "bad-cb-missing", false, "first tx is not coinbase");
    2747      618835 :     for (unsigned int i = 1; i < block.vtx.size(); i++)
    2748      536161 :         if (block.vtx[i]->IsCoinBase())
    2749           6 :             return state.DoS(100, false, REJECT_INVALID, "bad-cb-multiple", false, "more than one coinbase");
    2750             : 
    2751       82674 :     if (IsPoS) {
    2752             :         // Second transaction must be coinstake, the rest must not be
    2753       10307 :         if (block.vtx.empty() || !block.vtx[1]->IsCoinStake())
    2754           0 :             return state.DoS(100, false, REJECT_INVALID, "bad-cs-missing", false, "second tx is not coinstake");
    2755       14787 :         for (unsigned int i = 2; i < block.vtx.size(); i++)
    2756        4480 :             if (block.vtx[i]->IsCoinStake())
    2757           0 :                 return state.DoS(100, false, REJECT_INVALID, "bad-cs-multiple", false, "more than one coinstake");
    2758             :     }
    2759             : 
    2760             :     // Cold Staking enforcement (true during sync - reject P2CS outputs when false)
    2761       82674 :     bool fColdStakingActive = true;
    2762             : 
    2763             :     // masternode payments / budgets
    2764       82674 :     CBlockIndex* pindexPrev = chainActive.Tip();
    2765      154745 :     int nHeight = 0;
    2766       82356 :     if (pindexPrev != nullptr && block.hashPrevBlock != UINT256_ZERO) {
    2767       82355 :         if (pindexPrev->GetBlockHash() != block.hashPrevBlock) {
    2768             :             //out of order
    2769       11587 :             CBlockIndex* pindexPrev = LookupBlockIndex(block.hashPrevBlock);
    2770       11587 :             if (!pindexPrev) {
    2771       30852 :                 return state.Error("blk-out-of-order");
    2772             :             }
    2773             :         }
    2774       72071 :         nHeight = pindexPrev->nHeight + 1;
    2775             : 
    2776             :         // PIVX
    2777             :         // It is entirely possible that we don't have enough data and this could fail
    2778             :         // (i.e. the block could indeed be valid). Store the block for later consideration
    2779             :         // but issue an initial reject message.
    2780             :         // The case also exists that the sending peer could not have enough data to see
    2781             :         // that this block is invalid, so don't issue an outright ban.
    2782       72071 :         if (nHeight != 0 && !IsInitialBlockDownload()) {
    2783             :             // Last output of Cold-Stake is not abused
    2784       70398 :             if (IsPoS && !CheckColdStakeFreeOutput(*(block.vtx[1]), nHeight)) {
    2785           1 :                 mapRejectedBlocks.emplace(block.GetHash(), GetTime());
    2786           3 :                 return state.DoS(0, false, REJECT_INVALID, "bad-p2cs-outs", false, "invalid cold-stake output");
    2787             :             }
    2788             : 
    2789             :             // set Cold Staking Spork
    2790       70397 :             fColdStakingActive = !sporkManager.IsSporkActive(SPORK_19_COLDSTAKING_MAINTENANCE);
    2791             : 
    2792             :         } else {
    2793        1673 :             LogPrintf("%s: Masternode/Budget payment checks skipped on sync\n", __func__);
    2794             :         }
    2795             :     }
    2796             : 
    2797             :     // Check transactions
    2798      679700 :     for (const auto& txIn : block.vtx) {
    2799      607316 :         const CTransaction& tx = *txIn;
    2800      607316 :         if (!CheckTransaction(tx, state, fColdStakingActive)) {
    2801          10 :             return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(),
    2802          12 :                     strprintf("Transaction check failed (tx hash %s) %s", tx.GetHash().ToString(), state.GetDebugMessage()));
    2803             :         }
    2804             : 
    2805             :         // Non-contextual checks for special txes
    2806      607312 :         if (!CheckSpecialTxNoContext(tx, state)) {
    2807             :             // pass the state returned by the function above
    2808             :             return false;
    2809             :         }
    2810             :     }
    2811             : 
    2812       72384 :     unsigned int nSigOps = 0;
    2813      679691 :     for (const auto& tx : block.vtx) {
    2814      607307 :         nSigOps += GetLegacySigOpCount(*tx);
    2815             :     }
    2816       72384 :     unsigned int nMaxBlockSigOps = block.GetBlockTime() > Params().GetConsensus().ZC_TimeStart ? MAX_BLOCK_SIGOPS_CURRENT : MAX_BLOCK_SIGOPS_LEGACY;
    2817       72384 :     if (nSigOps > nMaxBlockSigOps)
    2818          14 :         return state.DoS(100, error("%s : out-of-bounds SigOpCount", __func__),
    2819             :             REJECT_INVALID, "bad-blk-sigops", true);
    2820             : 
    2821             :     // Check PoS signature.
    2822       72377 :     if (fCheckSig && !CheckBlockSignature(block)) {
    2823           0 :         return state.DoS(100, error("%s : bad proof-of-stake block signature", __func__),
    2824             :                          REJECT_INVALID, "bad-PoS-sig", true);
    2825             :     }
    2826             : 
    2827       72377 :     if (fCheckPOW && fCheckMerkleRoot && fCheckSig)
    2828       42477 :         block.fChecked = true;
    2829             : 
    2830             :     return true;
    2831             : }
    2832             : 
    2833       41106 : bool CheckWork(const CBlock& block, const CBlockIndex* const pindexPrev)
    2834             : {
    2835       41106 :     if (pindexPrev == nullptr)
    2836           0 :         return error("%s : null pindexPrev for block %s", __func__, block.GetHash().GetHex());
    2837             : 
    2838       41106 :     unsigned int nBitsRequired = GetNextWorkRequired(pindexPrev, &block);
    2839             : 
    2840       41106 :     if (!Params().IsRegTestNet() && block.IsProofOfWork() && (pindexPrev->nHeight + 1 <= 68589)) {
    2841           0 :         double n1 = ConvertBitsToDouble(block.nBits);
    2842           0 :         double n2 = ConvertBitsToDouble(nBitsRequired);
    2843             : 
    2844           0 :         if (std::abs(n1 - n2) > n1 * 0.5)
    2845           0 :             return error("%s : incorrect proof of work (DGW pre-fork) - %f %f %f at %d", __func__, std::abs(n1 - n2), n1, n2, pindexPrev->nHeight + 1);
    2846             : 
    2847             :         return true;
    2848             :     }
    2849             : 
    2850       41106 :     if (block.nBits != nBitsRequired) {
    2851             :         // Pivx Specific reference to the block with the wrong threshold was used.
    2852           1 :         const Consensus::Params& consensus = Params().GetConsensus();
    2853           1 :         if ((block.nTime == (uint32_t) consensus.nPivxBadBlockTime) &&
    2854           0 :                 (block.nBits == (uint32_t) consensus.nPivxBadBlockBits)) {
    2855             :             // accept PIVX block minted with incorrect proof of work threshold
    2856             :             return true;
    2857             :         }
    2858             : 
    2859           1 :         return error("%s : incorrect proof of work at %d", __func__, pindexPrev->nHeight + 1);
    2860             :     }
    2861             : 
    2862             :     return true;
    2863             : }
    2864             : 
    2865       55823 : bool CheckBlockTime(const CBlockHeader& block, CValidationState& state, CBlockIndex* const pindexPrev)
    2866             : {
    2867             :     // Not enforced on RegTest
    2868       55823 :     if (Params().IsRegTestNet())
    2869             :         return true;
    2870             : 
    2871           0 :     const int64_t blockTime = block.GetBlockTime();
    2872           0 :     const int blockHeight = pindexPrev->nHeight + 1;
    2873             : 
    2874             :     // Check blocktime against future drift (WANT: blk_time <= Now + MaxDrift)
    2875           0 :     if (blockTime > pindexPrev->MaxFutureBlockTime())
    2876           0 :         return state.Invalid(error("%s : block timestamp too far in the future", __func__), REJECT_INVALID, "time-too-new");
    2877             : 
    2878             :     // Check blocktime against prev (WANT: blk_time > MinPastBlockTime)
    2879           0 :     if (blockTime <= pindexPrev->MinPastBlockTime())
    2880           0 :         return state.DoS(50, error("%s : block timestamp too old", __func__), REJECT_INVALID, "time-too-old");
    2881             : 
    2882             :     // Check blocktime mask
    2883       55823 :     if (!Params().GetConsensus().IsValidBlockTimeStamp(blockTime, blockHeight))
    2884           0 :         return state.DoS(100, error("%s : block timestamp mask not valid", __func__), REJECT_INVALID, "invalid-time-mask");
    2885             : 
    2886             :     // All good
    2887             :     return true;
    2888             : }
    2889             : 
    2890             : //! Returns last CBlockIndex* that is a checkpoint
    2891       55823 : static const CBlockIndex* GetLastCheckpoint() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    2892             : {
    2893       55823 :     AssertLockHeld(cs_main);
    2894             : 
    2895       55823 :     if (!Checkpoints::fEnabled)
    2896             :         return nullptr;
    2897             : 
    2898       55696 :     const MapCheckpoints& checkpoints = *Params().Checkpoints().mapCheckpoints;
    2899             : 
    2900      111392 :     for (const auto& i : reverse_iterate(checkpoints)) {
    2901       55696 :         const uint256& hash = i.second;
    2902       55696 :         CBlockIndex* pindex = LookupBlockIndex(hash);
    2903       55696 :         if (pindex)
    2904           0 :             return pindex;
    2905             :     }
    2906       55696 :     return nullptr;
    2907             : }
    2908             : 
    2909       55828 : bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex* const pindexPrev)
    2910             : {
    2911       55828 :     AssertLockHeld(cs_main);
    2912             : 
    2913       55828 :     const Consensus::Params& consensus = Params().GetConsensus();
    2914       55828 :     uint256 hash = block.GetHash();
    2915             : 
    2916       55828 :     if (hash == consensus.hashGenesisBlock)
    2917             :         return true;
    2918             : 
    2919       55823 :     assert(pindexPrev);
    2920             : 
    2921       55823 :     const int nHeight = pindexPrev->nHeight + 1;
    2922       55823 :     const int chainHeight = chainActive.Height();
    2923             : 
    2924             :     //If this is a reorg, check that it is not too deep
    2925       55823 :     int nMaxReorgDepth = gArgs.GetArg("-maxreorg", DEFAULT_MAX_REORG_DEPTH);
    2926       55823 :     if (chainHeight - nHeight >= nMaxReorgDepth)
    2927           0 :         return state.DoS(1, error("%s: forked chain older than max reorganization depth (height %d)", __func__, chainHeight - nHeight));
    2928             : 
    2929             :     // Check blocktime (past limit, future limit and mask)
    2930       55823 :     if (!CheckBlockTime(block, state, pindexPrev))
    2931             :         return false;
    2932             : 
    2933             :     // Check that the block chain matches the known block chain up to a checkpoint
    2934       55823 :     if (!Checkpoints::CheckBlock(nHeight, hash))
    2935           0 :         return state.DoS(100, error("%s : rejected by checkpoint lock-in at %d", __func__, nHeight),
    2936             :             REJECT_CHECKPOINT, "checkpoint mismatch");
    2937             : 
    2938             :     // Don't accept any forks from the main chain prior to last checkpoint
    2939       55823 :     const CBlockIndex* pcheckpoint = GetLastCheckpoint();
    2940       55823 :     if (pcheckpoint && nHeight < pcheckpoint->nHeight)
    2941           0 :         return state.DoS(0, error("%s : forked chain older than last checkpoint (height %d)", __func__, nHeight));
    2942             : 
    2943             :     // Reject outdated version blocks
    2944       55823 :     if ((block.nVersion < 3 && nHeight >= 1) ||
    2945           0 :         (block.nVersion < 4 && consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_ZC)) ||
    2946       55823 :         (block.nVersion < 5 && consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BIP65)) ||
    2947       55823 :         (block.nVersion < 6 && consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V3_4)) ||
    2948      111646 :         (block.nVersion < 7 && consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V4_0)) ||
    2949       55823 :         (block.nVersion < 8 && consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V5_0)))
    2950             :     {
    2951           0 :         std::string stringErr = strprintf("rejected block version %d at height %d", block.nVersion, nHeight);
    2952           0 :         return state.Invalid(false, REJECT_OBSOLETE, "bad-version", stringErr);
    2953             :     }
    2954             : 
    2955             :     return true;
    2956             : }
    2957             : 
    2958       55813 : bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex* const pindexPrev)
    2959             : {
    2960       55813 :     const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
    2961       55813 :     const CChainParams& chainparams = Params();
    2962             : 
    2963             :     // Check that all transactions are finalized
    2964      452547 :     for (const auto& tx : block.vtx) {
    2965             : 
    2966             :         // Check transaction contextually against consensus rules at block height
    2967      396739 :         if (!ContextualCheckTransaction(tx, state, chainparams, nHeight, true /* isMined */, IsInitialBlockDownload())) {
    2968           5 :             return false;
    2969             :         }
    2970             : 
    2971      396736 :         if (!IsFinalTx(tx, nHeight, block.GetBlockTime())) {
    2972           8 :             return state.DoS(10, false, REJECT_INVALID, "bad-txns-nonfinal", false, "non-final transaction");
    2973             :         }
    2974             :     }
    2975             : 
    2976             :     // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
    2977       55808 :     if (pindexPrev) { // pindexPrev is only null on the first block which is a version 1 block.
    2978      111604 :         CScript expect = CScript() << nHeight;
    2979      111606 :         if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() ||
    2980      167409 :             !std::equal(expect.begin(), expect.end(), block.vtx[0]->vin[0].scriptSig.begin())) {
    2981           6 :             return state.DoS(100, false, REJECT_INVALID, "bad-cb-height", false, "block height mismatch in coinbase");
    2982             :         }
    2983             :     }
    2984             : 
    2985       55806 :     if (block.IsProofOfStake()) {
    2986       16840 :         CTransactionRef csTx = block.vtx[1];
    2987        8421 :         if (csTx->vin.size() > 1) {
    2988           4 :             return state.DoS(100, false, REJECT_INVALID, "bad-cs-multi-inputs", false,
    2989             :                              "invalid multi-inputs coinstake");
    2990             :         }
    2991             : 
    2992             :         // Prevent multi-empty-outputs
    2993       17280 :         for (size_t i=1; i<csTx->vout.size(); i++ ) {
    2994        8861 :             if (csTx->vout[i].IsEmpty()) {
    2995           3 :                 return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-empty");
    2996             :             }
    2997             :         }
    2998             :     }
    2999             : 
    3000             :     return true;
    3001             : }
    3002             : 
    3003             : // Get the index of previous block of given CBlock
    3004       41351 : static bool GetPrevIndex(const CBlock& block, CBlockIndex** pindexPrevRet, CValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    3005             : {
    3006       41351 :     AssertLockHeld(cs_main);
    3007             : 
    3008       41351 :     CBlockIndex*& pindexPrev = *pindexPrevRet;
    3009       41351 :     pindexPrev = nullptr;
    3010       41351 :     if (block.GetHash() != Params().GetConsensus().hashGenesisBlock) {
    3011       41340 :         pindexPrev = LookupBlockIndex(block.hashPrevBlock);
    3012       41340 :         if (!pindexPrev) {
    3013           0 :             return state.DoS(0, error("%s : prev block %s not found", __func__, block.hashPrevBlock.GetHex()), 0,
    3014             :                              "prevblk-not-found");
    3015             :         }
    3016       41340 :         if (pindexPrev->nStatus & BLOCK_FAILED_MASK) {
    3017             :             //If this "invalid" block is an exact match from the checkpoints, then reconsider it
    3018         234 :             if (Checkpoints::CheckBlock(pindexPrev->nHeight, block.hashPrevBlock, true)) {
    3019           0 :                 LogPrintf("%s : Reconsidering block %s height %d\n", __func__, block.hashPrevBlock.ToString(), pindexPrev->nHeight);
    3020           0 :                 CValidationState statePrev;
    3021           0 :                 ReconsiderBlock(statePrev, pindexPrev);
    3022           0 :                 if (statePrev.IsValid()) {
    3023           0 :                     ActivateBestChain(statePrev);
    3024           0 :                     return true;
    3025             :                 }
    3026             :             }
    3027         936 :             return state.DoS(100, error("%s : prev block %s is invalid, unable to add block %s", __func__, block.hashPrevBlock.GetHex(), block.GetHash().GetHex()),
    3028             :                              REJECT_INVALID, "bad-prevblk");
    3029             :         }
    3030             :     }
    3031             :     return true;
    3032             : }
    3033             : 
    3034       41110 : bool AcceptBlockHeader(const CBlock& block, CValidationState& state, CBlockIndex** ppindex, CBlockIndex* pindexPrev)
    3035             : {
    3036       41110 :     AssertLockHeld(cs_main);
    3037             :     // Check for duplicate
    3038       41110 :     const uint256& hash = block.GetHash();
    3039       41110 :     CBlockIndex* pindex = LookupBlockIndex(hash);
    3040             : 
    3041             :     // TODO : ENABLE BLOCK CACHE IN SPECIFIC CASES
    3042       41110 :     if (pindex) {
    3043             :         // Block header is already known.
    3044         234 :         if (ppindex)
    3045         234 :             *ppindex = pindex;
    3046         234 :         if (pindex->nStatus & BLOCK_FAILED_MASK)
    3047         114 :             return state.Invalid(error("%s : block is marked invalid", __func__), 0, "duplicate");
    3048             :         return true;
    3049             :     }
    3050             : 
    3051             :     // Get prev block index
    3052       40876 :     if (pindexPrev == nullptr && !GetPrevIndex(block, &pindexPrev, state)) {
    3053             :         return false;
    3054             :     }
    3055             : 
    3056       40876 :     if (!ContextualCheckBlockHeader(block, state, pindexPrev))
    3057           0 :         return error("%s: ContextualCheckBlockHeader failed for block %s: %s", __func__, hash.ToString(), FormatStateMessage(state));
    3058             : 
    3059             :     // Check for conflicting chainlocks UNLESS that's the genesis block
    3060       40876 :     if (block.GetHash() != Params().GetConsensus().hashGenesisBlock) {
    3061       40871 :         if (llmq::chainLocksHandler->HasConflictingChainLock(pindexPrev->nHeight + 1, hash)) {
    3062          26 :             return state.DoS(10, error("%s: conflicting with chainlock", __func__), REJECT_INVALID, "bad-chainlock");
    3063             :         }
    3064             :     }
    3065       40863 :     if (pindex == nullptr)
    3066       40863 :         pindex = AddToBlockIndex(block);
    3067             : 
    3068       40863 :     if (ppindex)
    3069       40863 :         *ppindex = pindex;
    3070             : 
    3071       40863 :     CheckBlockIndex();
    3072             : 
    3073             :     // Notify external listeners about accepted block header
    3074       40863 :     GetMainSignals().AcceptedBlockHeader(pindex);
    3075             :     return true;
    3076             : }
    3077             : 
    3078             : /*
    3079             :  * Collect the sets of the inputs (either regular utxos or zerocoin serials) spent
    3080             :  * by in-block txes.
    3081             :  * Also, check that there are no in-block double spends.
    3082             :  */
    3083        6570 : static bool CheckInBlockDoubleSpends(const CBlock& block, int nHeight, CValidationState& state,
    3084             :                                      std::unordered_set<COutPoint, SaltedOutpointHasher>& spent_outpoints,
    3085             :                                      std::set<CBigNum>& spent_serials)
    3086             : {
    3087        6570 :     const Consensus::Params& consensus = Params().GetConsensus();
    3088        6570 :     libzerocoin::ZerocoinParams* params = consensus.Zerocoin_Params(false);
    3089        6570 :     const bool zpivActive = consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_ZC);
    3090        6570 :     const bool publicZpivActive = consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_ZC_PUBLIC);
    3091        6570 :     const bool v5Active = consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V5_0);
    3092             : 
    3093             :     // First collect the tx inputs, and check double spends
    3094       15785 :     for (size_t i = 1; i < block.vtx.size(); i++) {
    3095             :         // skip coinbase
    3096       18433 :         CTransactionRef tx = block.vtx[i];
    3097       17736 :         for (const CTxIn& in: tx->vin) {
    3098        8521 :             bool isPublicSpend = in.IsZerocoinPublicSpend();
    3099        8521 :             if (isPublicSpend && (!publicZpivActive || v5Active)) {
    3100           0 :                 return state.DoS(100, error("%s: public zerocoin spend at height %d", __func__, nHeight));
    3101             :             }
    3102        8521 :             bool isPrivZerocoinSpend = !isPublicSpend && in.IsZerocoinSpend();
    3103           0 :             if (isPrivZerocoinSpend && (!zpivActive || publicZpivActive)) {
    3104           0 :                 return state.DoS(100, error("%s: private zerocoin spend at height %d", __func__, nHeight));
    3105             :             }
    3106        8521 :             if (isPrivZerocoinSpend || isPublicSpend) {
    3107           0 :                 libzerocoin::CoinSpend spend;
    3108           0 :                 if (isPublicSpend) {
    3109           0 :                     PublicCoinSpend publicSpend(params);
    3110           0 :                     if (!ZPIVModule::ParseZerocoinPublicSpend(in, *tx, state, publicSpend)){
    3111           0 :                         return false;
    3112             :                     }
    3113           0 :                     spend = publicSpend;
    3114             :                 } else {
    3115           0 :                     spend = ZPIVModule::TxInToZerocoinSpend(in);
    3116             :                 }
    3117             :                 // Check for serials double spending in the same block
    3118           0 :                 const CBigNum& s = spend.getCoinSerialNumber();
    3119           0 :                 if (spent_serials.find(s) != spent_serials.end()) {
    3120           0 :                     return state.DoS(100, error("%s: serials double spent in the same block", __func__));
    3121             :                 }
    3122           0 :                 spent_serials.insert(s);
    3123             :             } else {
    3124             :                 // regular utxo
    3125        8521 :                 if (spent_outpoints.find(in.prevout) != spent_outpoints.end()) {
    3126           6 :                     return state.DoS(100, error("%s: inputs double spent in the same block", __func__));
    3127             :                 }
    3128       17036 :                 spent_outpoints.insert(in.prevout);
    3129             :             }
    3130             :         }
    3131             :     }
    3132             : 
    3133             :     // Then remove from the coins_spent set, any coin that was created inside this block.
    3134             :     // In fact, if a transaction inside this block spends an output generated by another in-block tx,
    3135             :     // such output doesn't exist on chain yet, so we must not access the coins cache, or "walk the fork",
    3136             :     // to ensure that it was unspent before this block.
    3137             :     // The coinstake requires special treatment: its input cannot be the output of another in-block
    3138             :     // transaction (due to nStakeMinDepth), and no in-block tx can spend its outputs (due to nCoinbaseMaturity).
    3139       13137 :     std::unordered_set<uint256> inblock_txes;
    3140        9198 :     for (size_t i = 2; i < block.vtx.size(); i++) {
    3141             :         // coinbase/coinstake outputs cannot be spent inside the same block
    3142        2631 :         inblock_txes.insert(block.vtx[i]->GetHash());
    3143             :     }
    3144        6567 :     for (auto it = spent_outpoints.begin(); it != spent_outpoints.end(); /* no increment */) {
    3145        8501 :         if (inblock_txes.find(it->hash) != inblock_txes.end()) {
    3146             :             // the input spent was created as output of another in-block tx
    3147             :             // this is not allowed for the coinstake input
    3148           1 :             if (*it == block.vtx[1]->vin[0].prevout) {
    3149           0 :                 return state.DoS(100, error("%s: coinstake input created in the same block", __func__));
    3150             :             }
    3151           1 :             it = spent_outpoints.erase(it);
    3152             :         } else {
    3153       23568 :             it++;
    3154             :         }
    3155             :     }
    3156             : 
    3157        6567 :     return true;
    3158             : }
    3159             : 
    3160             : /*
    3161             :  * Check whether ALL the provided inputs (outpoints and zerocoin serials) are UNSPENT on
    3162             :  * a forked (non currently active) chain.
    3163             :  * Start from startIndex and go backwards on the forked chain, down to the split block.
    3164             :  * Return false if any block contains a tx spending an input included in the provided sets
    3165             :  * 'outpoints' and/or 'serials'.
    3166             :  * Return false also when the fork is longer than -maxreorg.
    3167             :  * Return true otherwise.
    3168             :  * Save in pindexFork the index of the pre-split block (last common block with the active chain).
    3169             :  * Remove from the outpoints set, any coin that was created in the fork (we don't
    3170             :  * need to check that it was unspent on the active chain before the split).
    3171             :  */
    3172          58 : static bool IsUnspentOnFork(std::unordered_set<COutPoint, SaltedOutpointHasher>& outpoints,
    3173             :                             const std::set<CBigNum>& serials,
    3174             :                             const CBlockIndex* startIndex, CValidationState& state, const CBlockIndex*& pindexFork)
    3175             : {
    3176             :     // Go backwards on the forked chain up to the split
    3177          58 :     int readBlock = 0;
    3178          58 :     pindexFork = startIndex;
    3179         540 :     for ( ; !chainActive.Contains(pindexFork); pindexFork = pindexFork->pprev) {
    3180             :         // Check if the forked chain is longer than the max reorg limit
    3181         214 :         if (++readBlock == gArgs.GetArg("-maxreorg", DEFAULT_MAX_REORG_DEPTH)) {
    3182             :             // TODO: Remove this chain from disk.
    3183           2 :             return error("%s: forked chain longer than maximum reorg limit", __func__);
    3184             :         }
    3185         214 :         if (pindexFork->pprev == nullptr) {
    3186           0 :             return error("%s: null pprev for block %s", __func__, pindexFork->GetBlockHash().GetHex());
    3187             :         }
    3188             : 
    3189             :         // if there are no coins left, don't read the block
    3190         214 :         if (outpoints.empty() && serials.empty()) continue;
    3191             : 
    3192             :         // read block
    3193         426 :         CBlock bl;
    3194         214 :         if (!ReadBlockFromDisk(bl, pindexFork)) {
    3195           0 :             return error("%s: block %s not on disk", __func__, pindexFork->GetBlockHash().GetHex());
    3196             :         }
    3197             :         // Loop through every tx of this block
    3198             :         // (reversed because we first check spent outpoints, and then remove created ones)
    3199         643 :         for (auto it = bl.vtx.rbegin(); it != bl.vtx.rend(); ++it) {
    3200         860 :             CTransactionRef tx = *it;
    3201             :             // Loop through every input of this tx
    3202         860 :             for (const CTxIn& in: tx->vin) {
    3203             :                 // check if any of the provided outpoints/serials is being spent
    3204         431 :                 if (!in.IsZerocoinSpend()) {
    3205             :                     // regular utxo
    3206         431 :                     if (outpoints.find(in.prevout) != outpoints.end()) {
    3207           6 :                         return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-spent-fork-post-split");
    3208             :                     }
    3209             :                 } else {
    3210             :                     // zerocoin serial
    3211           0 :                     const CBigNum& s = ZPIVModule::TxInToZerocoinSpend(in).getCoinSerialNumber();
    3212           0 :                     if (serials.find(s) != serials.end()) {
    3213           0 :                         return state.DoS(100, false, REJECT_INVALID, "bad-txns-serials-spent-fork-post-split");
    3214             :                     }
    3215             :                 }
    3216             :             }
    3217             :             // Then remove from the outpoints set, any coin created by this tx
    3218         429 :             const uint256& txid = tx->GetHash();
    3219        1079 :             for (size_t i = 0; i < tx->vout.size(); i++) {
    3220             :                 // erase if present (no-op if not)
    3221         650 :                 outpoints.erase(COutPoint(txid, i));
    3222             :             }
    3223             :         }
    3224             :     }
    3225             : 
    3226             :     // All the provided outpoints/serials are not spent on the fork,
    3227             :     // and this fork is below the max reorg depth
    3228             :     return true;
    3229             : }
    3230             : 
    3231             : /*
    3232             :  * Check whether ALL the provided inputs (regular utxos) are SPENT on the currently active chain.
    3233             :  * Start from the block on top of pindexFork, and go upwards on the active chain, up to the tip.
    3234             :  * Remove from the 'outpoints' set, all the inputs spent by transactions included in the scanned
    3235             :  * blocks. At the end, return true if the set is empty (all outpoints are spent), and false
    3236             :  * otherwise (some outpoint is unspent).
    3237             :  */
    3238           6 : static bool IsSpentOnActiveChain(std::unordered_set<COutPoint, SaltedOutpointHasher>& outpoints, const CBlockIndex* pindexFork)
    3239             : {
    3240          12 :     assert(chainActive.Contains(pindexFork));
    3241           6 :     const int height_start = pindexFork->nHeight + 1;
    3242           6 :     const int height_end = chainActive.Height();
    3243             : 
    3244             :     // Go upwards on the active chain till the tip
    3245          29 :     for (int height = height_start; height <= height_end && !outpoints.empty(); height++) {
    3246             :         // read block
    3247          46 :         const CBlockIndex* pindex = mapBlockIndex.at(chainActive[height]->GetBlockHash());
    3248          46 :         CBlock bl;
    3249          23 :         if (!ReadBlockFromDisk(bl, pindex)) {
    3250           0 :             return error("%s: block %s not on disk", __func__, pindex->GetBlockHash().GetHex());
    3251             :         }
    3252             :         // Loop through every tx of this block
    3253          78 :         for (const auto& tx : bl.vtx) {
    3254             :             // Loop through every input of this tx
    3255         208 :             for (const CTxIn& in: tx->vin) {
    3256             :                 // erase if present (no-op if not)
    3257         153 :                 outpoints.erase(in.prevout);
    3258             :             }
    3259             :         }
    3260             :     }
    3261             : 
    3262           6 :     return outpoints.empty();
    3263             : }
    3264             : 
    3265       41346 : static bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex** ppindex, const FlatFilePos* dbp) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    3266             : {
    3267       41346 :     AssertLockHeld(cs_main);
    3268             : 
    3269       41346 :     CBlockIndex* pindexDummy = nullptr;
    3270       41346 :     CBlockIndex*& pindex = ppindex ? *ppindex : pindexDummy;
    3271             : 
    3272       41346 :     const Consensus::Params& consensus = Params().GetConsensus();
    3273             : 
    3274             :     // Get prev block index
    3275       41346 :     CBlockIndex* pindexPrev = nullptr;
    3276       41346 :     if (!GetPrevIndex(block, &pindexPrev, state))
    3277             :         return false;
    3278             : 
    3279       41112 :     if (block.GetHash() != consensus.hashGenesisBlock && !CheckWork(block, pindexPrev))
    3280           2 :         return state.DoS(100, false, REJECT_INVALID);
    3281             : 
    3282       41111 :     bool isPoS = block.IsProofOfStake();
    3283       41111 :     if (isPoS) {
    3284       13145 :         std::string strError;
    3285        6573 :         if (!CheckProofOfStake(block, strError, pindexPrev))
    3286           2 :             return state.DoS(100, error("%s: proof of stake check failed (%s)", __func__, strError));
    3287             :     }
    3288             : 
    3289       41110 :     if (!AcceptBlockHeader(block, state, &pindex, pindexPrev))
    3290             :         return false;
    3291             : 
    3292       40983 :     if (pindex->nStatus & BLOCK_HAVE_DATA) {
    3293             :         // TODO: deal better with duplicate blocks.
    3294             :         // return state.DoS(20, error("AcceptBlock() : already have block %d %s", pindex->nHeight, pindex->GetBlockHash().ToString()), REJECT_DUPLICATE, "duplicate");
    3295         120 :         LogPrintf("%s : already have block %d %s\n", __func__, pindex->nHeight, pindex->GetBlockHash().ToString());
    3296         120 :         return true;
    3297             :     }
    3298             : 
    3299       40863 :     if (!CheckBlock(block, state) || !ContextualCheckBlock(block, state, pindex->pprev)) {
    3300           9 :         if (state.IsInvalid() && !state.CorruptionPossible()) {
    3301           9 :             pindex->nStatus |= BLOCK_FAILED_VALID;
    3302           9 :             setDirtyBlockIndex.insert(pindex);
    3303             :         }
    3304          18 :         return error("%s: %s", __func__, FormatStateMessage(state));
    3305             :     }
    3306             : 
    3307       40854 :     int nHeight = pindex->nHeight;
    3308             : 
    3309       40854 :     if (isPoS) {
    3310             :         // Blocks arrives in order, so if prev block is not the tip then we are on a fork.
    3311             :         // Extra info: duplicated blocks are skipping this checks, so we don't have to worry about those here.
    3312       13140 :         bool isBlockFromFork = pindexPrev != nullptr && chainActive.Tip() != pindexPrev;
    3313             : 
    3314             :         // Collect spent_outpoints and check for in-block double spends
    3315       13129 :         std::unordered_set<COutPoint, SaltedOutpointHasher> spent_outpoints;
    3316       13129 :         std::set<CBigNum> spent_serials;
    3317        6570 :         if (!CheckInBlockDoubleSpends(block, nHeight, state, spent_outpoints, spent_serials)) {
    3318          11 :             return false;
    3319             :         }
    3320             : 
    3321             :         // If this is a fork, check if all the tx inputs were spent in the fork
    3322             :         // Start at the block we're adding on to.
    3323             :         // Also remove from spent_outpoints any coin that was created in the fork
    3324        6567 :         const CBlockIndex* pindexFork{nullptr}; // index of the split block (last common block between fork and active chain)
    3325        6567 :         if (isBlockFromFork && !IsUnspentOnFork(spent_outpoints, spent_serials, pindexPrev, state, pindexFork)) {
    3326             :             return false;
    3327             :         }
    3328        6565 :         assert(!isBlockFromFork || pindexFork != nullptr);
    3329             : 
    3330             :         // Reject forks below maxdepth
    3331        6677 :         if (isBlockFromFork && chainActive.Height() - pindexFork->nHeight > gArgs.GetArg("-maxreorg", DEFAULT_MAX_REORG_DEPTH)) {
    3332             :             // TODO: Remove this chain from disk.
    3333           0 :             return error("%s: forked chain longer than maximum reorg limit", __func__);
    3334             :         }
    3335             : 
    3336             :         // Check that the serials were unspent on the active chain before the fork
    3337        6565 :         for (const CBigNum& s : spent_serials) {
    3338           0 :             int nHeightTx = 0;
    3339           0 :             if (IsSerialInBlockchain(s, nHeightTx)) {
    3340             :                 // if the height is nHeightTx > chainSplit means that the spent occurred after the chain split
    3341           0 :                 if (nHeightTx <= pindexFork->nHeight)
    3342           0 :                     return state.DoS(100, error("%s: serials double spent on main chain", __func__));
    3343             :             }
    3344             :         }
    3345             : 
    3346             :         // Check that all tx inputs were unspent on the active chain before the fork
    3347        6565 :         for (auto it = spent_outpoints.begin(); it != spent_outpoints.end(); /* no increment */) {
    3348        8493 :             const Coin& coin = pcoinsTip->AccessCoin(*it);
    3349        8493 :             if (!coin.IsSpent()) {
    3350             :                 // if this is on a fork, then the coin must be created before the split
    3351        8484 :                 if (isBlockFromFork && (int) coin.nHeight > pindexFork->nHeight) {
    3352           6 :                     return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-created-post-split");
    3353             :                 }
    3354             :                 // unspent on active chain
    3355        8482 :                 it = spent_outpoints.erase(it);
    3356             :             } else {
    3357             :                 // spent on active chain
    3358           9 :                 if (!isBlockFromFork)
    3359           6 :                     return error("%s: tx inputs spent/not-available on main chain (%s)", __func__, it->ToString());
    3360       15059 :                 it++;
    3361             :             }
    3362             :         }
    3363        6560 :         if (isBlockFromFork && !spent_outpoints.empty()) {
    3364             :             // Some coins are not spent on the fork post-split, but cannot be found in the coins cache.
    3365             :             // So they were either created on the fork, or spent on the active chain.
    3366             :             // Since coins created in the fork are removed by IsUnspentOnFork(), if there are some coins left,
    3367             :             // they were spent on the active chain.
    3368             :             // If some of them was not spent after the split, then the block is invalid.
    3369             :             // Walk the active chain, starting from pindexFork, going upwards till the chain tip, and check if
    3370             :             // all of these coins were spent by transactions included in the scanned blocks.
    3371             :             // If ALL of them are spent, then accept the block.
    3372             :             // Otherwise reject it, as it means that this blocks includes a transaction with an input that is
    3373             :             // either already spent before the chain split, or non-existent.
    3374           6 :             if (!IsSpentOnActiveChain(spent_outpoints, pindexFork)) {
    3375           3 :                 return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-spent-fork-pre-split");
    3376             :             }
    3377             :         }
    3378             : 
    3379             :         // ZPOS contextual checks
    3380        6559 :         const CTransaction& coinstake = *block.vtx[1];
    3381        6559 :         const CTxIn& coinstake_in = coinstake.vin[0];
    3382        6559 :         if (coinstake_in.IsZerocoinSpend()) {
    3383           0 :             libzerocoin::CoinSpend spend = ZPIVModule::TxInToZerocoinSpend(coinstake_in);
    3384           0 :             if (!ContextualCheckZerocoinSpend(coinstake, &spend, pindex->nHeight)) {
    3385           0 :                 return state.DoS(100,error("%s: main chain ContextualCheckZerocoinSpend failed for tx %s", __func__,
    3386           0 :                         coinstake.GetHash().GetHex()), REJECT_INVALID, "bad-txns-invalid-zpiv");
    3387             :             }
    3388             :         }
    3389             : 
    3390             :     }
    3391             : 
    3392             :     // Write block to history file
    3393       40843 :     try {
    3394       40843 :         unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION);
    3395       40843 :         FlatFilePos blockPos;
    3396       40843 :         if (dbp != nullptr)
    3397         344 :             blockPos = *dbp;
    3398       40843 :         if (!FindBlockPos(state, blockPos, nBlockSize + 8, nHeight, block.GetBlockTime(), dbp != nullptr))
    3399           0 :             return error("%s : FindBlockPos failed", __func__);
    3400       40843 :         if (dbp == nullptr)
    3401       40499 :             if (!WriteBlockToDisk(block, blockPos))
    3402           0 :                 return AbortNode(state, "Failed to write block");
    3403       40843 :         if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
    3404           0 :             return error("%s : ReceivedBlockTransactions failed", __func__);
    3405           0 :     } catch (const std::runtime_error& e) {
    3406           0 :         return AbortNode(state, std::string("System error: ") + e.what());
    3407             :     }
    3408             : 
    3409       40843 :     return true;
    3410             : }
    3411             : 
    3412       51654 : bool ProcessNewBlock(const std::shared_ptr<const CBlock>& pblock, const FlatFilePos* dbp)
    3413             : {
    3414       51654 :     AssertLockNotHeld(cs_main);
    3415             : 
    3416             :     // Preliminary checks
    3417       51654 :     int64_t nStartTime = GetTimeMillis();
    3418       51654 :     int newHeight = 0;
    3419             : 
    3420       51654 :     {
    3421             :         // CheckBlock requires cs_main lock
    3422       51654 :         LOCK(cs_main);
    3423       92617 :         CValidationState state;
    3424       51654 :         if (!CheckBlock(*pblock, state)) {
    3425       10308 :             GetMainSignals().BlockChecked(*pblock, state);
    3426       30918 :             return error ("%s : CheckBlock FAILED for block %s, %s", __func__, pblock->GetHash().GetHex(), FormatStateMessage(state));
    3427             :         }
    3428             : 
    3429             :         // Store to disk
    3430       41346 :         CBlockIndex* pindex = nullptr;
    3431       41346 :         bool ret = AcceptBlock(*pblock, state, &pindex, dbp);
    3432       41346 :         CheckBlockIndex();
    3433       41346 :         if (!ret) {
    3434         383 :             GetMainSignals().BlockChecked(*pblock, state);
    3435         383 :             return error("%s : AcceptBlock FAILED", __func__);
    3436             :         }
    3437       40963 :         newHeight = pindex->nHeight;
    3438             :     }
    3439             : 
    3440       81926 :     CValidationState state; // Only used to report errors, not invalidity - ignore it
    3441       81926 :     if (!ActivateBestChain(state, pblock))
    3442           1 :         return error("%s : ActivateBestChain failed", __func__);
    3443             : 
    3444       81924 :     LogPrintf("%s : ACCEPTED Block %ld in %ld milliseconds with size=%d\n", __func__, newHeight, GetTimeMillis() - nStartTime,
    3445       40962 :               GetSerializeSize(*pblock, CLIENT_VERSION));
    3446             : 
    3447       40962 :     return true;
    3448             : }
    3449             : 
    3450       14952 : bool TestBlockValidity(CValidationState& state, const CBlock& block, CBlockIndex* const pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckBlockSig)
    3451             : {
    3452       14952 :     AssertLockHeld(cs_main);
    3453       14952 :     assert(pindexPrev);
    3454       29904 :     if (pindexPrev != chainActive.Tip()) {
    3455           0 :         LogPrintf("%s : No longer working on chain tip\n", __func__);
    3456           0 :         return false;
    3457             :     }
    3458       14952 :     if (llmq::chainLocksHandler->HasConflictingChainLock(pindexPrev->nHeight + 1, block.GetHash())) {
    3459           0 :         return state.DoS(10, error("%s: conflicting with chainlock", __func__), REJECT_INVALID, "bad-chainlock");
    3460             :     }
    3461             : 
    3462       14952 :     CCoinsViewCache viewNew(pcoinsTip.get());
    3463       29904 :     CBlockIndex indexDummy(block);
    3464       14952 :     indexDummy.pprev = pindexPrev;
    3465       14952 :     indexDummy.nHeight = pindexPrev->nHeight + 1;
    3466             : 
    3467             :     // begin tx and let it rollback
    3468       29904 :     auto dbTx = evoDb->BeginTransaction();
    3469             : 
    3470             :     // NOTE: CheckBlockHeader is called by CheckBlock
    3471       14952 :     if (!ContextualCheckBlockHeader(block, state, pindexPrev))
    3472           0 :         return error("%s: ContextualCheckBlockHeader failed: %s", __func__, FormatStateMessage(state));
    3473       14952 :     if (!CheckBlock(block, state, fCheckPOW, fCheckMerkleRoot, fCheckBlockSig))
    3474           3 :         return error("%s: CheckBlock failed: %s", __func__, FormatStateMessage(state));
    3475       14950 :     if (!ContextualCheckBlock(block, state, pindexPrev))
    3476           0 :         return error("%s: ContextualCheckBlock failed: %s", __func__, FormatStateMessage(state));
    3477       14950 :     if (!ConnectBlock(block, state, &indexDummy, viewNew, true))
    3478             :         return false;
    3479       14947 :     assert(state.IsValid());
    3480             : 
    3481             :     return true;
    3482             : }
    3483             : 
    3484      368921 : static FlatFileSeq BlockFileSeq()
    3485             : {
    3486      737842 :     return FlatFileSeq(GetBlocksDir(), "blk", BLOCKFILE_CHUNK_SIZE);
    3487             : }
    3488             : 
    3489       84832 : static FlatFileSeq UndoFileSeq()
    3490             : {
    3491      169664 :     return FlatFileSeq(GetBlocksDir(), "rev", UNDOFILE_CHUNK_SIZE);
    3492             : }
    3493             : 
    3494      327298 : FILE* OpenBlockFile(const FlatFilePos& pos, bool fReadOnly)
    3495             : {
    3496      654596 :     return BlockFileSeq().Open(pos, fReadOnly);
    3497             : }
    3498             : 
    3499       43285 : FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly)
    3500             : {
    3501       86570 :     return UndoFileSeq().Open(pos, fReadOnly);
    3502             : }
    3503             : 
    3504          10 : fs::path GetBlockPosFilename(const FlatFilePos &pos)
    3505             : {
    3506          20 :     return BlockFileSeq().FileName(pos);
    3507             : }
    3508             : 
    3509       65764 : CBlockIndex* InsertBlockIndex(const uint256& hash)
    3510             : {
    3511       65764 :     AssertLockHeld(cs_main);
    3512             : 
    3513      131528 :     if (hash.IsNull())
    3514             :         return nullptr;
    3515             : 
    3516             :     // Return existing
    3517       65605 :     BlockMap::iterator mi = mapBlockIndex.find(hash);
    3518       65605 :     if (mi != mapBlockIndex.end())
    3519       32723 :         return (*mi).second;
    3520             : 
    3521             :     // Create new
    3522       32882 :     CBlockIndex* pindexNew = new CBlockIndex();
    3523       32882 :     mi = mapBlockIndex.emplace(hash, pindexNew).first;
    3524             : 
    3525       32882 :     pindexNew->phashBlock = &((*mi).first);
    3526             : 
    3527       32882 :     return pindexNew;
    3528             : }
    3529             : 
    3530         352 : bool static LoadBlockIndexDB(std::string& strError) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    3531             : {
    3532         352 :     AssertLockHeld(cs_main);
    3533             : 
    3534         704 :     if (!pblocktree->LoadBlockIndexGuts(InsertBlockIndex))
    3535             :         return false;
    3536             : 
    3537         352 :     boost::this_thread::interruption_point();
    3538             : 
    3539             :     // Calculate nChainWork
    3540         704 :     std::vector<std::pair<int, CBlockIndex*> > vSortedByHeight;
    3541         352 :     vSortedByHeight.reserve(mapBlockIndex.size());
    3542       33234 :     for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex) {
    3543       32882 :         CBlockIndex* pindex = item.second;
    3544       32882 :         vSortedByHeight.emplace_back(pindex->nHeight, pindex);
    3545             :         // build mapPrevBlockIndex
    3546       32882 :         if (pindex->pprev) {
    3547       32723 :             mapPrevBlockIndex.emplace(pindex->pprev->GetBlockHash(), pindex);
    3548             :         }
    3549             :     }
    3550         352 :     std::sort(vSortedByHeight.begin(), vSortedByHeight.end());
    3551       33234 :     for (const std::pair<int, CBlockIndex*>& item : vSortedByHeight) {
    3552             :         // Stop if shutdown was requested
    3553       32882 :         if (ShutdownRequested()) return false;
    3554             : 
    3555       32882 :         CBlockIndex* pindex = item.second;
    3556      394584 :         pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex);
    3557       55027 :         pindex->nTimeMax = (pindex->pprev ? std::max(pindex->pprev->nTimeMax, pindex->nTime) : pindex->nTime);
    3558       32882 :         if (pindex->nStatus & BLOCK_HAVE_DATA) {
    3559       32882 :             if (pindex->pprev) {
    3560       32723 :                 if (pindex->pprev->nChainTx) {
    3561       32723 :                     pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx;
    3562             :                     // Sapling, calculate chain index value
    3563       32723 :                     if (pindex->pprev->nChainSaplingValue) {
    3564       32723 :                         pindex->nChainSaplingValue = *pindex->pprev->nChainSaplingValue + pindex->nSaplingValue;
    3565             :                     } else {
    3566           0 :                         pindex->nChainSaplingValue = nullopt;
    3567             :                     }
    3568             : 
    3569             :                 } else {
    3570           0 :                     pindex->nChainTx = 0;
    3571           0 :                     pindex->nChainSaplingValue = nullopt;
    3572           0 :                     mapBlocksUnlinked.emplace(pindex->pprev, pindex);
    3573             :                 }
    3574             :             } else {
    3575         159 :                 pindex->nChainTx = pindex->nTx;
    3576         159 :                 pindex->nChainSaplingValue = pindex->nSaplingValue;
    3577             :             }
    3578             :         }
    3579       32882 :         if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->nChainTx || pindex->pprev == nullptr))
    3580       32877 :             setBlockIndexCandidates.insert(pindex);
    3581       32882 :         if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork))
    3582           5 :             pindexBestInvalid = pindex;
    3583       32882 :         if (pindex->pprev)
    3584       32723 :             pindex->BuildSkip();
    3585       32882 :         if (pindex->IsValid(BLOCK_VALID_TREE) && (pindexBestHeader == nullptr || CBlockIndexWorkComparator()(pindexBestHeader, pindex)))
    3586       32821 :             pindexBestHeader = pindex;
    3587             :     }
    3588             : 
    3589             :     // Load block file info
    3590         352 :     pblocktree->ReadLastBlockFile(nLastBlockFile);
    3591         352 :     vinfoBlockFile.resize(nLastBlockFile + 1);
    3592         352 :     LogPrintf("%s: last block file = %i\n", __func__, nLastBlockFile);
    3593         704 :     for (int nFile = 0; nFile <= nLastBlockFile; nFile++) {
    3594         352 :         pblocktree->ReadBlockFileInfo(nFile, vinfoBlockFile[nFile]);
    3595             :     }
    3596         352 :     LogPrintf("%s: last block file info: %s\n", __func__, vinfoBlockFile[nLastBlockFile].ToString());
    3597         352 :     for (int nFile = nLastBlockFile + 1; true; nFile++) {
    3598         352 :         CBlockFileInfo info;
    3599         352 :         if (pblocktree->ReadBlockFileInfo(nFile, info)) {
    3600           0 :             vinfoBlockFile.push_back(info);
    3601             :         } else {
    3602             :             break;
    3603             :         }
    3604           0 :     }
    3605             : 
    3606             :     // Check presence of blk files
    3607         352 :     LogPrintf("Checking all blk files are present...\n");
    3608         704 :     std::set<int> setBlkDataFiles;
    3609       33234 :     for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex) {
    3610       32882 :         CBlockIndex* pindex = item.second;
    3611       32882 :         if (pindex->nStatus & BLOCK_HAVE_DATA) {
    3612       65764 :             setBlkDataFiles.insert(pindex->nFile);
    3613             :         }
    3614             :     }
    3615         511 :     for (std::set<int>::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++) {
    3616         159 :         FlatFilePos pos(*it, 0);
    3617         318 :         if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION).IsNull()) {
    3618           0 :             return false;
    3619             :         }
    3620             :     }
    3621             : 
    3622             :     //Check if the shutdown procedure was followed on last client exit
    3623         352 :     bool fLastShutdownWasPrepared = true;
    3624         352 :     pblocktree->ReadFlag("shutdown", fLastShutdownWasPrepared);
    3625         352 :     LogPrintf("%s: Last shutdown was prepared: %s\n", __func__, fLastShutdownWasPrepared);
    3626             : 
    3627             :     // Check whether we need to continue reindexing
    3628         352 :     bool fReindexing = false;
    3629         352 :     pblocktree->ReadReindexing(fReindexing);
    3630         352 :     if (fReindexing) fReindex = true;
    3631             : 
    3632             :     // Check whether we have a transaction index
    3633         352 :     pblocktree->ReadFlag("txindex", fTxIndex);
    3634         352 :     LogPrintf("LoadBlockIndexDB(): transaction index %s\n", fTxIndex ? "enabled" : "disabled");
    3635             : 
    3636             :     // If this is written true before the next client init, then we know the shutdown process failed
    3637         352 :     pblocktree->WriteFlag("shutdown", false);
    3638             : 
    3639         352 :     return true;
    3640             : }
    3641             : 
    3642         157 : bool LoadChainTip(const CChainParams& chainparams)
    3643             : {
    3644         157 :     AssertLockHeld(cs_main);
    3645             : 
    3646         157 :     if (chainActive.Tip() && chainActive.Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) return true;
    3647             : 
    3648         314 :     if (pcoinsTip->GetBestBlock().IsNull() && mapBlockIndex.size() == 1) {
    3649             :         // In case we just added the genesis block, connect it now, so
    3650             :         // that we always have a chainActive.Tip() when we return.
    3651           0 :         LogPrintf("%s: Connecting genesis block...\n", __func__);
    3652           0 :         CValidationState state;
    3653           0 :         if (!ActivateBestChain(state)) {
    3654           0 :             return false;
    3655             :         }
    3656             :     }
    3657             : 
    3658             :     // Load pointer to end of best chain
    3659         157 :     CBlockIndex* pindex = LookupBlockIndex(pcoinsTip->GetBestBlock());
    3660         157 :     if (!pindex) {
    3661             :         return false;
    3662             :     }
    3663         157 :     chainActive.SetTip(pindex);
    3664             : 
    3665         157 :     PruneBlockIndexCandidates();
    3666             : 
    3667         157 :     const CBlockIndex* pChainTip = chainActive.Tip();
    3668             : 
    3669         157 :     LogPrintf("Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n",
    3670         314 :             pChainTip->GetBlockHash().GetHex(), pChainTip->nHeight,
    3671         157 :             FormatISO8601DateTime(pChainTip->GetBlockTime()),
    3672         157 :             Checkpoints::GuessVerificationProgress(pChainTip));
    3673         157 :     return true;
    3674             : }
    3675             : 
    3676         158 : CVerifyDB::CVerifyDB()
    3677             : {
    3678         158 :     uiInterface.ShowProgress(_("Verifying blocks..."), 0);
    3679         158 : }
    3680             : 
    3681         158 : CVerifyDB::~CVerifyDB()
    3682             : {
    3683         158 :     uiInterface.ShowProgress("", 100);
    3684         158 : }
    3685             : 
    3686         158 : bool CVerifyDB::VerifyDB(CCoinsView* coinsview, int nCheckLevel, int nCheckDepth)
    3687             : {
    3688         316 :     LOCK(cs_main);
    3689         297 :     if (chainActive.Tip() == nullptr || chainActive.Tip()->pprev == nullptr)
    3690             :         return true;
    3691             : 
    3692         139 :     const int chainHeight = chainActive.Height();
    3693             : 
    3694             :     // begin tx and let it rollback
    3695         278 :     auto dbTx = evoDb->BeginTransaction();
    3696             : 
    3697             :     // Verify blocks in the best chain
    3698         139 :     if (nCheckDepth <= 0)
    3699           1 :         nCheckDepth = 1000000000; // suffices until the year 19000
    3700         139 :     if (nCheckDepth > chainHeight)
    3701           6 :         nCheckDepth = chainHeight;
    3702         278 :     nCheckLevel = std::max(0, std::min(4, nCheckLevel));
    3703         139 :     LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
    3704         278 :     CCoinsViewCache coins(coinsview);
    3705         139 :     CBlockIndex* pindexState = chainActive.Tip();
    3706         139 :     CBlockIndex* pindexFailure = nullptr;
    3707         139 :     int nGoodTransactions = 0;
    3708         139 :     int reportDone = 0;
    3709         139 :     LogPrintf("[0%%]...");
    3710         278 :     CValidationState state;
    3711        1413 :     for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) {
    3712        1269 :         boost::this_thread::interruption_point();
    3713        3539 :         int percentageDone = std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
    3714        1269 :         if (reportDone < percentageDone/10) {
    3715             :             // report every 10% step
    3716         807 :             LogPrintf("[%d%%]...", percentageDone);
    3717         807 :             reportDone = percentageDone/10;
    3718             :         }
    3719        1269 :         uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone);
    3720        1269 :         if (pindex->nHeight < chainHeight - nCheckDepth)
    3721             :             break;
    3722        2271 :         CBlock block;
    3723             :         // check level 0: read from disk
    3724        1136 :         if (!ReadBlockFromDisk(block, pindex))
    3725           0 :             return error("%s: *** ReadBlockFromDisk failed at %d, hash=%s", __func__, pindex->nHeight, pindex->GetBlockHash().ToString());
    3726             :         // check level 1: verify block validity
    3727        1136 :         if (nCheckLevel >= 1 && !CheckBlock(block, state))
    3728           0 :             return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__, pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state));
    3729             :         // check level 2: verify undo validity
    3730        1136 :         if (nCheckLevel >= 2 && pindex) {
    3731        2271 :             CBlockUndo undo;
    3732        1136 :             FlatFilePos pos = pindex->GetUndoPos();
    3733        1136 :             if (!pos.IsNull()) {
    3734        1136 :                 if (!UndoReadFromDisk(undo, pos, pindex->pprev->GetBlockHash()))
    3735           2 :                     return error("%s: *** found bad undo data at %d, hash=%s\n", __func__, pindex->nHeight, pindex->GetBlockHash().ToString());
    3736             :             }
    3737             :         }
    3738             :         // check level 3: check for inconsistencies during memory-only disconnect of tip blocks
    3739        1135 :         if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) {
    3740        1122 :             assert(coins.GetBestBlock() == pindex->GetBlockHash());
    3741        1122 :             DisconnectResult res = DisconnectBlock(block, pindex, coins);
    3742        1122 :             if (res == DISCONNECT_FAILED) {
    3743           0 :                 return error("%s: *** irrecoverable inconsistency in block data at %d, hash=%s", __func__,
    3744           0 :                              pindex->nHeight, pindex->GetBlockHash().ToString());
    3745             :             }
    3746        1122 :             pindexState = pindex->pprev;
    3747        1122 :             if (res == DISCONNECT_UNCLEAN) {
    3748           0 :                 nGoodTransactions = 0;
    3749           0 :                 pindexFailure = pindex;
    3750             :             } else {
    3751        1122 :                 nGoodTransactions += block.vtx.size();
    3752             :             }
    3753             :         }
    3754        1135 :         if (ShutdownRequested())
    3755             :             return true;
    3756             :     }
    3757         138 :     if (pindexFailure)
    3758           0 :         return error("%s: *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", __func__, chainHeight - pindexFailure->nHeight + 1, nGoodTransactions);
    3759             : 
    3760             :     // check level 4: try reconnecting blocks
    3761         138 :     if (nCheckLevel >= 4) {
    3762             :         CBlockIndex* pindex = pindexState;
    3763           0 :         while (pindex != chainActive.Tip()) {
    3764           0 :             boost::this_thread::interruption_point();
    3765           0 :             uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainHeight - pindex->nHeight)) / (double)nCheckDepth * 50))));
    3766           0 :             pindex = chainActive.Next(pindex);
    3767           0 :             CBlock block;
    3768           0 :             if (!ReadBlockFromDisk(block, pindex))
    3769           0 :                 return error("%s: *** ReadBlockFromDisk failed at %d, hash=%s", __func__, pindex->nHeight, pindex->GetBlockHash().ToString());
    3770           0 :             if (!ConnectBlock(block, state, pindex, coins, false))
    3771           0 :                 return error("%s: *** found unconnectable block at %d, hash=%s", __func__, pindex->nHeight, pindex->GetBlockHash().ToString());
    3772             :         }
    3773             :     }
    3774         138 :     LogPrintf("[DONE].\n");
    3775         138 :     LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", chainHeight - pindexState->nHeight, nGoodTransactions);
    3776             : 
    3777         138 :     return true;
    3778             : }
    3779             : 
    3780             : /** Apply the effects of a block on the utxo cache, ignoring that it may already have been applied. */
    3781           7 : static bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    3782             : {
    3783           7 :     AssertLockHeld(cs_main);
    3784             : 
    3785             :     // TODO: merge with ConnectBlock
    3786          14 :     CBlock block;
    3787           7 :     if (!ReadBlockFromDisk(block, pindex)) {
    3788           0 :         return error("ReplayBlock(): ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
    3789             :     }
    3790             : 
    3791           7 :     const bool fSkipInvalid = SkipInvalidUTXOS(pindex->nHeight);
    3792             : 
    3793       17514 :     for (const CTransactionRef& tx : block.vtx) {
    3794       17507 :         if (!tx->IsCoinBase()) {
    3795       52500 :             for (const CTxIn &txin : tx->vin) {
    3796       35000 :                 inputs.SpendCoin(txin.prevout);
    3797             :             }
    3798             :         }
    3799             : 
    3800             :         // Pass check = true as every addition may be an overwrite.
    3801       17507 :         AddCoins(inputs, *tx, pindex->nHeight, true, fSkipInvalid);
    3802             :     }
    3803             : 
    3804          14 :     CValidationState state;
    3805           7 :     if (!ProcessSpecialTxsInBlock(block, pindex, &inputs, state, false /*fJustCheck*/)) {
    3806           0 :         return error("%s: Special tx processing failed for block %s with %s",
    3807           0 :                      __func__, pindex->GetBlockHash().ToString(), FormatStateMessage(state));
    3808             :     }
    3809             : 
    3810             :     return true;
    3811             : }
    3812             : 
    3813         357 : bool ReplayBlocks(const CChainParams& params, CCoinsView* view)
    3814             : {
    3815         714 :     LOCK(cs_main);
    3816             : 
    3817         714 :     CCoinsViewCache cache(view);
    3818             : 
    3819         714 :     std::vector<uint256> hashHeads = view->GetHeadBlocks();
    3820         357 :     if (hashHeads.empty()) return true; // We're already in a consistent state.
    3821           3 :     if (hashHeads.size() != 2) return error("%s: unknown inconsistent state", __func__);
    3822             : 
    3823           3 :     uiInterface.ShowProgress(_("Replaying blocks..."), 0);
    3824           3 :     LogPrintf("Replaying blocks\n");
    3825             : 
    3826           3 :     const CBlockIndex* pindexOld = nullptr;  // Old tip during the interrupted flush.
    3827           3 :     const CBlockIndex* pindexNew;            // New tip during the interrupted flush.
    3828           3 :     const CBlockIndex* pindexFork = nullptr; // Latest block common to both the old and the new tip.
    3829             : 
    3830           3 :     pindexNew = LookupBlockIndex(hashHeads[0]);
    3831           3 :     if (!pindexNew) {
    3832           0 :         return error("%s: reorganization to unknown block requested", __func__);
    3833             :     }
    3834             : 
    3835           6 :     if (!hashHeads[1].IsNull()) { // The old tip is allowed to be 0, indicating it's the first flush.
    3836           3 :         pindexOld = LookupBlockIndex(hashHeads[1]);
    3837           3 :         if (!pindexOld) {
    3838           0 :             return error("%s: reorganization from unknown block requested", __func__);
    3839             :         }
    3840           3 :         pindexFork = LastCommonAncestor(pindexOld, pindexNew);
    3841           3 :         assert(pindexFork != nullptr);
    3842             :     }
    3843             : 
    3844             :     // Rollback along the old branch.
    3845           3 :     while (pindexOld != pindexFork) {
    3846           0 :         if (pindexOld->nHeight > 0) { // Never disconnect the genesis block.
    3847           0 :             CBlock block;
    3848           0 :             if (!ReadBlockFromDisk(block, pindexOld)) {
    3849           0 :                 return error("RollbackBlock(): ReadBlockFromDisk() failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString());
    3850             :             }
    3851           0 :             LogPrintf("Rolling back %s (%i)\n", pindexOld->GetBlockHash().ToString(), pindexOld->nHeight);
    3852           0 :             DisconnectResult res = DisconnectBlock(block, pindexOld, cache);
    3853           0 :             if (res == DISCONNECT_FAILED) {
    3854           0 :                 return error("RollbackBlock(): DisconnectBlock failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString());
    3855             :             }
    3856             :             // If DISCONNECT_UNCLEAN is returned, it means a non-existing UTXO was deleted, or an existing UTXO was
    3857             :             // overwritten. It corresponds to cases where the block-to-be-disconnect never had all its operations
    3858             :             // applied to the UTXO set. However, as both writing a UTXO and deleting a UTXO are idempotent operations,
    3859             :             // the result is still a version of the UTXO set with the effects of that block undone.
    3860             :         }
    3861           0 :         pindexOld = pindexOld->pprev;
    3862             :     }
    3863             : 
    3864             :     // Roll forward from the forking point to the new tip.
    3865           3 :     int nForkHeight = pindexFork ? pindexFork->nHeight : 0;
    3866          10 :     for (int nHeight = nForkHeight + 1; nHeight <= pindexNew->nHeight; ++nHeight) {
    3867           7 :         const CBlockIndex* pindex = pindexNew->GetAncestor(nHeight);
    3868           7 :         LogPrintf("Rolling forward %s (%i)\n", pindex->GetBlockHash().ToString(), nHeight);
    3869           7 :         if (!RollforwardBlock(pindex, cache, params)) return false;
    3870             :     }
    3871             : 
    3872           3 :     cache.SetBestBlock(pindexNew->GetBlockHash());
    3873           3 :     evoDb->WriteBestBlock(pindexNew->GetBlockHash());
    3874           3 :     cache.Flush();
    3875           3 :     uiInterface.ShowProgress("", 100);
    3876           3 :     return true;
    3877             : }
    3878             : 
    3879             : // May NOT be used after any connections are up as much
    3880             : // of the peer-processing logic assumes a consistent
    3881             : // block index state
    3882         475 : void UnloadBlockIndex()
    3883             : {
    3884         475 :     LOCK(cs_main);
    3885         475 :     setBlockIndexCandidates.clear();
    3886         475 :     chainActive.SetTip(nullptr);
    3887         475 :     pindexBestInvalid = nullptr;
    3888         475 :     pindexBestHeader = nullptr;
    3889         475 :     mempool.clear();
    3890         475 :     mapBlocksUnlinked.clear();
    3891         475 :     vinfoBlockFile.clear();
    3892         475 :     nLastBlockFile = 0;
    3893         475 :     nBlockSequenceId = 1;
    3894         475 :     setDirtyBlockIndex.clear();
    3895         475 :     setDirtyFileInfo.clear();
    3896             : 
    3897        3199 :     for (BlockMap::value_type& entry : mapBlockIndex) {
    3898        5448 :         delete entry.second;
    3899             :     }
    3900         475 :     mapBlockIndex.clear();
    3901         475 : }
    3902             : 
    3903         357 : bool LoadBlockIndex(std::string& strError)
    3904             : {
    3905         357 :     AssertLockHeld(cs_main);
    3906             : 
    3907         357 :     bool needs_init = fReindex;
    3908         357 :     if (!fReindex) {
    3909         352 :         if (!LoadBlockIndexDB(strError))
    3910             :             return false;
    3911         352 :         needs_init = mapBlockIndex.empty();
    3912             :     }
    3913             : 
    3914         357 :     if (needs_init) {
    3915             :         // Everything here is for *new* reindex/DBs. Thus, though
    3916             :         // LoadBlockIndexDB may have set fReindex if we shut down
    3917             :         // mid-reindex previously, we don't check fReindex and
    3918             :         // instead only check it prior to LoadBlockIndexDB to set
    3919             :         // needs_init.
    3920             : 
    3921         198 :         LogPrintf("Initializing databases...\n");
    3922             :         // Use the provided setting for -txindex in the new database
    3923         198 :         fTxIndex = gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX);
    3924         396 :         pblocktree->WriteFlag("txindex", fTxIndex);
    3925             :     }
    3926             :     return true;
    3927             : }
    3928             : 
    3929             : 
    3930         475 : bool LoadGenesisBlock()
    3931             : {
    3932         950 :     LOCK(cs_main);
    3933             : 
    3934             :     // Check whether we're already initialized by checking for genesis in
    3935             :     // mapBlockIndex. Note that we can't use chainActive here, since it is
    3936             :     // set based on the coins db, not the block index db, which is the only
    3937             :     // thing loaded at this point.
    3938         950 :     if (mapBlockIndex.count(Params().GenesisBlock().GetHash()))
    3939             :         return true;
    3940             : 
    3941         311 :     try {
    3942         311 :         CBlock& block = const_cast<CBlock&>(Params().GenesisBlock());
    3943             :         // Start new block file
    3944         311 :         unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION);
    3945         311 :         FlatFilePos blockPos;
    3946         622 :         CValidationState state;
    3947         311 :         if (!FindBlockPos(state, blockPos, nBlockSize + 8, 0, block.GetBlockTime()))
    3948           0 :             return error("%s: FindBlockPos failed", __func__);
    3949         311 :         if (!WriteBlockToDisk(block, blockPos))
    3950           0 :             return error("%s: writing genesis block to disk failed", __func__);
    3951         311 :         CBlockIndex *pindex = AddToBlockIndex(block);
    3952         311 :         if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
    3953           0 :             return error("%s: genesis block not accepted", __func__);
    3954           0 :     } catch (const std::runtime_error& e) {
    3955           0 :          return error("%s: failed to write genesis block: %s", __func__, e.what());
    3956             :      }
    3957             : 
    3958         311 :     return true;
    3959             : }
    3960             : 
    3961             : 
    3962           5 : bool LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
    3963             : {
    3964             :     // Map of disk positions for blocks with unknown parent (only used for reindex)
    3965           5 :     static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
    3966           5 :     int64_t nStart = GetTimeMillis();
    3967             : 
    3968             :     // Block checked event listener
    3969           5 :     BlockStateCatcherWrapper stateCatcher(UINT256_ZERO);
    3970           5 :     stateCatcher.registerEvent();
    3971             : 
    3972           5 :     int nLoaded = 0;
    3973           5 :     try {
    3974             :         // This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
    3975           5 :         CBufferedFile blkdat(fileIn, 2 * MAX_BLOCK_SIZE_CURRENT, MAX_BLOCK_SIZE_CURRENT + 8, SER_DISK, CLIENT_VERSION);
    3976           5 :         uint64_t nRewind = blkdat.GetPos();
    3977         354 :         while (!blkdat.eof()) {
    3978         349 :             boost::this_thread::interruption_point();
    3979             : 
    3980         349 :             blkdat.SetPos(nRewind);
    3981         349 :             nRewind++;         // start one byte further next time, in case of failure
    3982         349 :             blkdat.SetLimit(); // remove former limit
    3983         349 :             unsigned int nSize = 0;
    3984         349 :             try {
    3985             :                 // locate a header
    3986         349 :                 unsigned char buf[CMessageHeader::MESSAGE_START_SIZE];
    3987         349 :                 blkdat.FindByte(Params().MessageStart()[0]);
    3988         344 :                 nRewind = blkdat.GetPos()+1;
    3989         344 :                 blkdat >> buf;
    3990         344 :                 if (memcmp(buf, Params().MessageStart(), CMessageHeader::MESSAGE_START_SIZE))
    3991           0 :                     continue;
    3992             :                 // read size
    3993         344 :                 blkdat >> nSize;
    3994         344 :                 if (nSize < 80 || nSize > MAX_BLOCK_SIZE_CURRENT)
    3995           0 :                     continue;
    3996           5 :             } catch (const std::exception&) {
    3997             :                 // no valid block header found; don't complain
    3998           5 :                 break;
    3999             :             }
    4000         344 :             try {
    4001             :                 // read block
    4002         344 :                 uint64_t nBlockPos = blkdat.GetPos();
    4003         344 :                 if (dbp)
    4004         344 :                     dbp->nPos = nBlockPos;
    4005         344 :                 blkdat.SetLimit(nBlockPos + nSize);
    4006         344 :                 blkdat.SetPos(nBlockPos);
    4007         344 :                 CBlock block;
    4008         344 :                 blkdat >> block;
    4009         344 :                 nRewind = blkdat.GetPos();
    4010             : 
    4011         344 :                 uint256 hash = block.GetHash();
    4012         344 :                 CBlockIndex* pindex{nullptr};
    4013         344 :                 {
    4014         344 :                     LOCK(cs_main);
    4015             :                     // detect out of order blocks, and store them for later
    4016         344 :                     if (hash != Params().GetConsensus().hashGenesisBlock && !LookupBlockIndex(block.hashPrevBlock)) {
    4017           0 :                         LogPrint(BCLog::REINDEX, "%s: Out of order block %s, parent %s not known\n", __func__,
    4018             :                                 hash.ToString(), block.hashPrevBlock.ToString());
    4019           0 :                         if (dbp)
    4020           0 :                             mapBlocksUnknownParent.emplace(block.hashPrevBlock, *dbp);
    4021           0 :                         continue;
    4022             :                     }
    4023             : 
    4024         344 :                     pindex = LookupBlockIndex(hash);
    4025             :                 }
    4026             : 
    4027             :                 // process in case the block isn't known yet
    4028         344 :                 if (!pindex || (pindex->nStatus & BLOCK_HAVE_DATA) == 0) {
    4029         688 :                     std::shared_ptr<const CBlock> block_ptr = std::make_shared<const CBlock>(block);
    4030         344 :                     stateCatcher.get().setBlockHash(block_ptr->GetHash());
    4031         344 :                     if (ProcessNewBlock(block_ptr, dbp)) {
    4032         344 :                         nLoaded++;
    4033             :                     }
    4034         688 :                     if (stateCatcher.get().stateErrorFound()) {
    4035             :                         break;
    4036             :                     }
    4037           0 :                 } else if (hash != Params().GetConsensus().hashGenesisBlock && pindex->nHeight % 1000 == 0) {
    4038           0 :                     LogPrint(BCLog::REINDEX, "Block Import: already had block %s at height %d\n", hash.ToString(), pindex->nHeight);
    4039             :                 }
    4040             : 
    4041             :                 // Recursively process earlier encountered successors of this block
    4042         688 :                 std::deque<uint256> queue;
    4043         344 :                 queue.push_back(hash);
    4044         688 :                 while (!queue.empty()) {
    4045         344 :                     uint256 head = queue.front();
    4046         344 :                     queue.pop_front();
    4047         344 :                     std::pair<std::multimap<uint256, FlatFilePos>::iterator, std::multimap<uint256, FlatFilePos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
    4048         344 :                     while (range.first != range.second) {
    4049           0 :                         std::multimap<uint256, FlatFilePos>::iterator it = range.first;
    4050           0 :                         if (ReadBlockFromDisk(block, it->second)) {
    4051           0 :                             LogPrint(BCLog::REINDEX, "%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(),
    4052             :                                 head.ToString());
    4053           0 :                             std::shared_ptr<const CBlock> block_ptr = std::make_shared<const CBlock>(block);
    4054           0 :                             if (ProcessNewBlock(block_ptr, &it->second)) {
    4055           0 :                                 nLoaded++;
    4056           0 :                                 queue.emplace_back(block.GetHash());
    4057             :                             }
    4058             :                         }
    4059           0 :                         range.first++;
    4060           0 :                         mapBlocksUnknownParent.erase(it);
    4061             :                     }
    4062             :                 }
    4063           0 :             } catch (const std::exception& e) {
    4064           0 :                 LogPrintf("%s : Deserialize or I/O error - %s\n", __func__, e.what());
    4065             :             }
    4066             :         }
    4067           0 :     } catch (const std::runtime_error& e) {
    4068           0 :         AbortNode(std::string("System error: ") + e.what());
    4069             :     }
    4070           5 :     if (nLoaded > 0)
    4071           5 :         LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, GetTimeMillis() - nStart);
    4072           5 :     return nLoaded > 0;
    4073             : }
    4074             : 
    4075      123223 : void static CheckBlockIndex()
    4076             : {
    4077      123223 :     if (!fCheckBlockIndex) {
    4078          10 :         return;
    4079             :     }
    4080             : 
    4081      246436 :     LOCK(cs_main);
    4082             : 
    4083             :     // During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain,
    4084             :     // so we have the genesis block in mapBlockIndex but no active chain.  (A few of the tests when
    4085             :     // iterating the block tree require that chainActive has been initialized.)
    4086      123223 :     if (chainActive.Height() < 0) {
    4087          10 :         assert(mapBlockIndex.size() <= 1);
    4088          20 :         return;
    4089             :     }
    4090             : 
    4091             :     // Build forward-pointing map of the entire block tree.
    4092      246426 :     std::multimap<CBlockIndex*, CBlockIndex*> forward;
    4093    31123250 :     for (auto& entry : mapBlockIndex) {
    4094    31000100 :         forward.emplace(entry.second->pprev, entry.second);
    4095             :     }
    4096             : 
    4097      123213 :     assert(forward.size() == mapBlockIndex.size());
    4098             : 
    4099      123213 :     std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> rangeGenesis = forward.equal_range(nullptr);
    4100      123213 :     CBlockIndex* pindex = rangeGenesis.first->second;
    4101      123213 :     rangeGenesis.first++;
    4102      123213 :     assert(rangeGenesis.first == rangeGenesis.second); // There is only one index entry with parent nullptr.
    4103             : 
    4104             :     // Iterate over the entire block tree, using depth-first search.
    4105             :     // Along the way, remember whether there are blocks on the path from genesis
    4106             :     // block being explored which are the first to have certain properties.
    4107             :     size_t nNodes = 0;
    4108             :     int nHeight = 0;
    4109             :     CBlockIndex* pindexFirstInvalid = nullptr;         // Oldest ancestor of pindex which is invalid.
    4110             :     CBlockIndex* pindexFirstMissing = nullptr;         // Oldest ancestor of pindex which does not have BLOCK_HAVE_DATA.
    4111             :     CBlockIndex* pindexFirstNotTreeValid = nullptr;    // Oldest ancestor of pindex which does not have BLOCK_VALID_TREE (regardless of being valid or not).
    4112             :     CBlockIndex* pindexFirstNotChainValid = nullptr;   // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not).
    4113             :     CBlockIndex* pindexFirstNotScriptsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not).
    4114    31123250 :     while (pindex != nullptr) {
    4115    31000100 :         nNodes++;
    4116    31000100 :         if (pindexFirstInvalid == nullptr && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex;
    4117    31000100 :         if (pindexFirstMissing == nullptr && !(pindex->nStatus & BLOCK_HAVE_DATA)) pindexFirstMissing = pindex;
    4118    31000100 :         if (pindex->pprev != nullptr && pindexFirstNotTreeValid == nullptr && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TREE) pindexFirstNotTreeValid = pindex;
    4119    31000100 :         if (pindex->pprev != nullptr && pindexFirstNotChainValid == nullptr && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_CHAIN) pindexFirstNotChainValid = pindex;
    4120    31000100 :         if (pindex->pprev != nullptr && pindexFirstNotScriptsValid == nullptr && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_SCRIPTS) pindexFirstNotScriptsValid = pindex;
    4121             : 
    4122             :         // Begin: actual consistency checks.
    4123    31000100 :         if (pindex->pprev == nullptr) {
    4124             :             // Genesis block checks.
    4125      123213 :             assert(pindex->GetBlockHash() == Params().GetConsensus().hashGenesisBlock); // Genesis block's hash must match.
    4126      246426 :             assert(pindex == chainActive.Genesis());                       // The current active chain's genesis block must be this block.
    4127             :         }
    4128             :         // HAVE_DATA is equivalent to VALID_TRANSACTIONS and equivalent to nTx > 0 (we stored the number of transactions in the block)
    4129    31000100 :         assert(!(pindex->nStatus & BLOCK_HAVE_DATA) == (pindex->nTx == 0));
    4130    31000100 :         assert(((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS) == (pindex->nTx > 0));
    4131    31000100 :         if (pindex->nChainTx == 0) assert(pindex->nSequenceId == 0); // nSequenceId can't be set for blocks that aren't linked
    4132             :         // All parents having data is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to nChainTx being set.
    4133    31000100 :         assert((pindexFirstMissing != nullptr) == (pindex->nChainTx == 0));                                             // nChainTx == 0 is used to signal that all parent block's transaction data is available.
    4134    31000100 :         assert(pindex->nHeight == nHeight);                                                                          // nHeight must be consistent.
    4135    31000100 :         assert(pindex->pprev == nullptr || pindex->nChainWork >= pindex->pprev->nChainWork);                            // For every block except the genesis block, the chainwork must be larger than the parent's.
    4136    31000100 :         assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight)));                                // The pskip pointer must point back for all but the first 2 blocks.
    4137    31000100 :         assert(pindexFirstNotTreeValid == nullptr);                                                                     // All mapBlockIndex entries must at least be TREE valid
    4138    31000100 :         if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TREE) assert(pindexFirstNotTreeValid == nullptr);       // TREE valid implies all parents are TREE valid
    4139    31000100 :         if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_CHAIN) assert(pindexFirstNotChainValid == nullptr);     // CHAIN valid implies all parents are CHAIN valid
    4140    31000100 :         if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_SCRIPTS) assert(pindexFirstNotScriptsValid == nullptr); // SCRIPTS valid implies all parents are SCRIPTS valid
    4141    31000100 :         if (pindexFirstInvalid == nullptr) {
    4142             :             // Checks for not-invalid blocks.
    4143    30991360 :             assert((pindex->nStatus & BLOCK_FAILED_MASK) == 0); // The failed mask cannot be set for blocks without invalid parents.
    4144             :         }
    4145    62000110 :         if (!CBlockIndexWorkComparator()(pindex, chainActive.Tip()) && pindexFirstMissing == nullptr) {
    4146      164680 :             if (pindexFirstInvalid == nullptr) { // If this block sorts at least as good as the current tip and is valid, it must be in setBlockIndexCandidates.
    4147      327906 :                 assert(setBlockIndexCandidates.count(pindex));
    4148             :             }
    4149             :         } else { // If this block sorts worse than the current tip, it cannot be in setBlockIndexCandidates.
    4150    61670800 :             assert(setBlockIndexCandidates.count(pindex) == 0);
    4151             :         }
    4152             :         // Check whether this block is in mapBlocksUnlinked.
    4153    31000100 :         std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> rangeUnlinked = mapBlocksUnlinked.equal_range(pindex->pprev);
    4154    31000100 :         bool foundInUnlinked = false;
    4155    31000100 :         while (rangeUnlinked.first != rangeUnlinked.second) {
    4156           0 :             assert(rangeUnlinked.first->first == pindex->pprev);
    4157           0 :             if (rangeUnlinked.first->second == pindex) {
    4158             :                 foundInUnlinked = true;
    4159             :                 break;
    4160             :             }
    4161    31000100 :             rangeUnlinked.first++;
    4162             :         }
    4163    31000100 :         if (pindex->pprev && pindex->nStatus & BLOCK_HAVE_DATA && pindexFirstMissing != nullptr) {
    4164           0 :             if (pindexFirstInvalid == nullptr) { // If this block has block data available, some parent doesn't, and has no invalid parents, it must be in mapBlocksUnlinked.
    4165           0 :                 assert(foundInUnlinked);
    4166             :             }
    4167             :         } else { // If this block does not have block data available, or all parents do, it cannot be in mapBlocksUnlinked.
    4168    31000100 :             assert(!foundInUnlinked);
    4169             :         }
    4170             :         // assert(pindex->GetBlockHash() == pindex->GetBlockHeader().GetHash()); // Perhaps too slow
    4171             :         // End: actual consistency checks.
    4172             : 
    4173             :         // Try descending into the first subnode.
    4174    31000100 :         std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = forward.equal_range(pindex);
    4175    31000100 :         if (range.first != range.second) {
    4176             :             // A subnode was found.
    4177    30868780 :             pindex = range.first->second;
    4178    30868780 :             nHeight++;
    4179    30868780 :             continue;
    4180             :         }
    4181             :         // This is a leaf node.
    4182             :         // Move upwards until we reach a node of which we have not yet visited the last child.
    4183    31123250 :         while (pindex) {
    4184             :             // We are going to either move to a parent or a sibling of pindex.
    4185             :             // If pindex was the first with a certain property, unset the corresponding variable.
    4186    31000100 :             if (pindex == pindexFirstInvalid) pindexFirstInvalid = nullptr;
    4187    31000100 :             if (pindex == pindexFirstMissing) pindexFirstMissing = nullptr;
    4188    31000100 :             if (pindex == pindexFirstNotTreeValid) pindexFirstNotTreeValid = nullptr;
    4189    31000100 :             if (pindex == pindexFirstNotChainValid) pindexFirstNotChainValid = nullptr;
    4190    31000100 :             if (pindex == pindexFirstNotScriptsValid) pindexFirstNotScriptsValid = nullptr;
    4191             :             // Find our parent.
    4192    31000100 :             CBlockIndex* pindexPar = pindex->pprev;
    4193             :             // Find which child we just visited.
    4194    31000100 :             std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> rangePar = forward.equal_range(pindexPar);
    4195    31011560 :             while (rangePar.first->second != pindex) {
    4196       11495 :                 assert(rangePar.first != rangePar.second); // Our parent must have at least the node we're coming from as child.
    4197    31011560 :                 rangePar.first++;
    4198             :             }
    4199             :             // Proceed to the next one.
    4200    31000100 :             rangePar.first++;
    4201    31000100 :             if (rangePar.first != rangePar.second) {
    4202             :                 // Move to the sibling.
    4203        8072 :                 pindex = rangePar.first->second;
    4204        8072 :                 break;
    4205             :             } else {
    4206             :                 // Move up further.
    4207    30992030 :                 pindex = pindexPar;
    4208    30992030 :                 nHeight--;
    4209    30992030 :                 continue;
    4210             :             }
    4211             :         }
    4212             :     }
    4213             : 
    4214             :     // Check that we actually traversed the entire map.
    4215      123213 :     assert(nNodes == forward.size());
    4216             : }
    4217             : 
    4218             : // Note: whenever a protocol update is needed toggle between both implementations (comment out the formerly active one)
    4219             : //       so we can leave the existing clients untouched (old SPORK will stay on so they don't see even older clients).
    4220             : //       Those old clients won't react to the changes of the other (new) SPORK because at the time of their implementation
    4221             : //       it was the one which was commented out
    4222       85256 : int ActiveProtocol()
    4223             : {
    4224             :     // SPORK_14 is used for 70926 (v5.5.0), commented out now.
    4225             :     //if (sporkManager.IsSporkActive(SPORK_14_NEW_PROTOCOL_ENFORCEMENT))
    4226             :     //        return MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT;
    4227             : 
    4228             :     // SPORK_15 is used for 70927 (v5.6.0), commented out now.
    4229       85256 :     if (sporkManager.IsSporkActive(SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2))
    4230           0 :             return MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT;
    4231             : 
    4232             :     return MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT;
    4233             : }
    4234             : 
    4235         353 : std::string CBlockFileInfo::ToString() const
    4236             : {
    4237         706 :     return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, FormatISO8601Date(nTimeFirst), FormatISO8601Date(nTimeLast));
    4238             : }
    4239             : 
    4240           1 : CBlockFileInfo* GetBlockFileInfo(size_t n)
    4241             : {
    4242           1 :     return &vinfoBlockFile.at(n);
    4243             : }
    4244             : 
    4245             : static const uint64_t MEMPOOL_DUMP_VERSION = 1;
    4246             : 
    4247         347 : bool LoadMempool(CTxMemPool& pool)
    4248             : {
    4249         347 :     int64_t nExpiryTimeout = gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60;
    4250         694 :     FILE* filestr = fopen((GetDataDir() / "mempool.dat").string().c_str(), "r");
    4251         694 :     CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
    4252         347 :     if (file.IsNull()) {
    4253         271 :         LogPrintf("Failed to open mempool file from disk. Continuing anyway.\n");
    4254             :         return false;
    4255             :     }
    4256             : 
    4257          76 :     int64_t count = 0;
    4258          76 :     int64_t skipped = 0;
    4259          76 :     int64_t failed = 0;
    4260          76 :     int64_t nNow = GetTime();
    4261             : 
    4262          76 :     try {
    4263          76 :         uint64_t version;
    4264          76 :         file >> version;
    4265          76 :         if (version != MEMPOOL_DUMP_VERSION) {
    4266           0 :             return false;
    4267             :         }
    4268          76 :         uint64_t num;
    4269          76 :         file >> num;
    4270          99 :         while (num--) {
    4271          23 :             CTransactionRef tx;
    4272          23 :             int64_t nTime;
    4273          23 :             int64_t nFeeDelta;
    4274          23 :             file >> tx;
    4275          23 :             file >> nTime;
    4276          23 :             file >> nFeeDelta;
    4277             : 
    4278          23 :             CAmount amountdelta = nFeeDelta;
    4279          23 :             if (amountdelta) {
    4280           0 :                 pool.PrioritiseTransaction(tx->GetHash(), amountdelta);
    4281             :             }
    4282          46 :             CValidationState state;
    4283          23 :             if (nTime + nExpiryTimeout > nNow) {
    4284          46 :                 LOCK(cs_main);
    4285          23 :                 AcceptToMemoryPoolWithTime(pool, state, tx, true, nullptr, nTime);
    4286          23 :                 if (state.IsValid()) {
    4287          21 :                     ++count;
    4288             :                 } else {
    4289           2 :                     ++failed;
    4290             :                 }
    4291             :             } else {
    4292           0 :                 ++skipped;
    4293             :             }
    4294          23 :             if (ShutdownRequested())
    4295           0 :                 return false;
    4296             :         }
    4297          76 :         std::map<uint256, CAmount> mapDeltas;
    4298          76 :         file >> mapDeltas;
    4299             : 
    4300          76 :         for (const auto& i : mapDeltas) {
    4301           0 :             pool.PrioritiseTransaction(i.first, i.second);
    4302             :         }
    4303           0 :     } catch (const std::exception& e) {
    4304           0 :         LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
    4305           0 :         return false;
    4306             :     }
    4307             : 
    4308          76 :     LogPrintf("Imported mempool transactions from disk: %i successes, %i failed, %i expired\n", count, failed, skipped);
    4309             :     return true;
    4310             : }
    4311             : 
    4312         347 : bool DumpMempool(const CTxMemPool& pool)
    4313             : {
    4314         347 :     int64_t start = GetTimeMicros();
    4315             : 
    4316         694 :     std::map<uint256, CAmount> mapDeltas;
    4317         694 :     std::vector<TxMempoolInfo> vinfo;
    4318             : 
    4319         347 :     static Mutex dump_mutex;
    4320         694 :     LOCK(dump_mutex);
    4321             : 
    4322         347 :     {
    4323         347 :         LOCK(pool.cs);
    4324         347 :         for (const auto &i : pool.mapDeltas) {
    4325           0 :             mapDeltas[i.first] = i.second;
    4326             :         }
    4327         694 :         vinfo = pool.infoAll();
    4328             :     }
    4329             : 
    4330         347 :     int64_t mid = GetTimeMicros();
    4331             : 
    4332         347 :     try {
    4333         694 :         FILE* filestr = fopen((GetDataDir() / "mempool.dat.new").string().c_str(), "w");
    4334         347 :         if (!filestr) {
    4335           0 :             return false;
    4336             :         }
    4337             : 
    4338         347 :         CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
    4339             : 
    4340         347 :         uint64_t version = MEMPOOL_DUMP_VERSION;
    4341         347 :         file << version;
    4342             : 
    4343         347 :         file << (uint64_t)vinfo.size();
    4344        1194 :         for (const auto& i : vinfo) {
    4345         847 :             file << i.tx;
    4346         847 :             file << (int64_t)i.nTime;
    4347         847 :             file << (int64_t)i.nFeeDelta;
    4348         847 :             mapDeltas.erase(i.tx->GetHash());
    4349             :         }
    4350             : 
    4351         347 :         file << mapDeltas;
    4352         347 :         if (!FileCommit(file.Get()))
    4353           0 :             throw std::runtime_error("FileCommit failed");
    4354         347 :         file.fclose();
    4355        1388 :         if (!RenameOver(GetDataDir() / "mempool.dat.new", GetDataDir() / "mempool.dat")) {
    4356           0 :             throw std::runtime_error("Rename failed");
    4357             :         }
    4358         347 :         int64_t last = GetTimeMicros();
    4359         347 :         LogPrintf("Dumped mempool: %gs to copy, %gs to dump\n", (mid-start)*0.000001, (last-mid)*0.000001);
    4360           0 :     } catch (const std::exception& e) {
    4361           0 :         LogPrintf("Failed to dump mempool: %s. Continuing anyway.\n", e.what());
    4362           0 :         return false;
    4363             :     }
    4364         347 :     return true;
    4365             : }
    4366             : 
    4367             : class CMainCleanup
    4368             : {
    4369             : public:
    4370             :     CMainCleanup() {}
    4371         479 :     ~CMainCleanup()
    4372             :     {
    4373             :         // block headers
    4374         479 :         BlockMap::iterator it1 = mapBlockIndex.begin();
    4375       71813 :         for (; it1 != mapBlockIndex.end(); it1++)
    4376      142668 :             delete (*it1).second;
    4377         479 :         mapBlockIndex.clear();
    4378         479 :     }
    4379             : } instance_of_cmaincleanup;
    4380             : 

Generated by: LCOV version 1.14