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

Generated by: LCOV version 1.14