LCOV - code coverage report
Current view: top level - src - chain.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 100 146 68.5 %
Date: 2025-02-23 09:33:43 Functions: 9 9 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin developers
       3             : // Copyright (c) 2011-2013 The PPCoin developers
       4             : // Copyright (c) 2013-2014 The NovaCoin Developers
       5             : // Copyright (c) 2014-2018 The BlackCoin Developers
       6             : // Copyright (c) 2015-2021 The PIVX Core developers
       7             : // Distributed under the MIT software license, see the accompanying
       8             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       9             : 
      10             : #ifndef PIVX_CHAIN_H
      11             : #define PIVX_CHAIN_H
      12             : 
      13             : #include "chainparams.h"
      14             : #include "flatfile.h"
      15             : #include "optional.h"
      16             : #include "primitives/block.h"
      17             : #include "timedata.h"
      18             : #include "tinyformat.h"
      19             : #include "uint256.h"
      20             : #include "util/system.h"
      21             : #include "libzerocoin/Denominations.h"
      22             : 
      23             : #include <vector>
      24             : 
      25             : /**
      26             :  * Timestamp window used as a grace period by code that compares external
      27             :  * timestamps (such as timestamps passed to RPCs, or wallet key creation times)
      28             :  * to block timestamps.
      29             :  */
      30             : static constexpr int64_t TIMESTAMP_WINDOW = 2 * 60 * 60;
      31             : 
      32             : class CBlockFileInfo
      33             : {
      34             : public:
      35             :     unsigned int nBlocks;      //!< number of blocks stored in file
      36             :     unsigned int nSize;        //!< number of used bytes of block file
      37             :     unsigned int nUndoSize;    //!< number of used bytes in the undo file
      38             :     unsigned int nHeightFirst; //!< lowest height of block in file
      39             :     unsigned int nHeightLast;  //!< highest height of block in file
      40             :     uint64_t nTimeFirst;       //!< earliest time of block in file
      41             :     uint64_t nTimeLast;        //!< latest time of block in file
      42             : 
      43        1521 :     SERIALIZE_METHODS(CBlockFileInfo, obj)
      44             :     {
      45         488 :         READWRITE(VARINT(obj.nBlocks));
      46         488 :         READWRITE(VARINT(obj.nSize));
      47         488 :         READWRITE(VARINT(obj.nUndoSize));
      48         488 :         READWRITE(VARINT(obj.nHeightFirst));
      49         488 :         READWRITE(VARINT(obj.nHeightLast));
      50         488 :         READWRITE(VARINT(obj.nTimeFirst));
      51         488 :         READWRITE(VARINT(obj.nTimeLast));
      52         488 :     }
      53             : 
      54         828 :     void SetNull()
      55             :     {
      56         828 :         nBlocks = 0;
      57         828 :         nSize = 0;
      58         828 :         nUndoSize = 0;
      59         828 :         nHeightFirst = 0;
      60         828 :         nHeightLast = 0;
      61         828 :         nTimeFirst = 0;
      62         828 :         nTimeLast = 0;
      63             :     }
      64             : 
      65         828 :     CBlockFileInfo()
      66         828 :     {
      67         828 :         SetNull();
      68             :     }
      69             : 
      70             :     std::string ToString() const;
      71             : 
      72             :     /** update statistics (does not update nSize) */
      73       41476 :     void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn)
      74             :     {
      75       41476 :         if (nBlocks == 0 || nHeightFirst > nHeightIn)
      76         317 :             nHeightFirst = nHeightIn;
      77       41476 :         if (nBlocks == 0 || nTimeFirst > nTimeIn)
      78         317 :             nTimeFirst = nTimeIn;
      79       41476 :         nBlocks++;
      80       41476 :         if (nHeightIn > nHeightLast)
      81       40931 :             nHeightLast = nHeightIn;
      82       41476 :         if (nTimeIn > nTimeLast)
      83       17145 :             nTimeLast = nTimeIn;
      84             :     }
      85             : };
      86             : 
      87             : enum BlockStatus {
      88             :     //! Unused.
      89             :     BLOCK_VALID_UNKNOWN = 0,
      90             : 
      91             :     //! Parsed, version ok, hash satisfies claimed PoW, 1 <= vtx count <= max, timestamp not in future
      92             :     BLOCK_VALID_HEADER = 1,
      93             : 
      94             :     //! All parent headers found, difficulty matches, timestamp >= median previous, checkpoint. Implies all parents
      95             :     //! are also at least TREE.
      96             :     BLOCK_VALID_TREE = 2,
      97             : 
      98             :     /**
      99             :      * Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids,
     100             :      * sigops, size, merkle root. Implies all parents are at least TREE but not necessarily TRANSACTIONS. When all
     101             :      * parent blocks also have TRANSACTIONS, CBlockIndex::nChainTx will be set.
     102             :      */
     103             :     BLOCK_VALID_TRANSACTIONS = 3,
     104             : 
     105             :     //! Outputs do not overspend inputs, no double spends, coinbase output ok, immature coinbase spends.
     106             :     //! Implies all parents are also at least CHAIN.
     107             :     BLOCK_VALID_CHAIN = 4,
     108             : 
     109             :     //! Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
     110             :     BLOCK_VALID_SCRIPTS = 5,
     111             : 
     112             :     //! All validity bits.
     113             :     BLOCK_VALID_MASK = BLOCK_VALID_HEADER | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS |
     114             :                        BLOCK_VALID_CHAIN |
     115             :                        BLOCK_VALID_SCRIPTS,
     116             : 
     117             :     BLOCK_HAVE_DATA = 8,  //! full block available in blk*.dat
     118             :     BLOCK_HAVE_UNDO = 16, //! undo data available in rev*.dat
     119             :     BLOCK_HAVE_MASK = BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO,
     120             : 
     121             :     BLOCK_FAILED_VALID = 32, //! stage after last reached validness failed
     122             :     BLOCK_FAILED_CHILD = 64, //! descends from failed block
     123             :     BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
     124             : };
     125             : 
     126             : // BlockIndex flags
     127             : enum {
     128             :     BLOCK_PROOF_OF_STAKE = (1 << 0), // is proof-of-stake block
     129             :     BLOCK_STAKE_ENTROPY = (1 << 1),  // entropy bit for stake modifier
     130             :     BLOCK_STAKE_MODIFIER = (1 << 2), // regenerated stake modifier
     131             : };
     132             : 
     133             : /** The block chain is a tree shaped structure starting with the
     134             :  * genesis block at the root, with each block potentially having multiple
     135             :  * candidates to be the next block. A blockindex may have multiple pprev pointing
     136             :  * to it, but at most one of them can be part of the currently active branch.
     137             :  */
     138      857497 : class CBlockIndex
     139             : {
     140             : public:
     141             :     //! pointer to the hash of the block, if any. memory is owned by this CBlockIndex
     142             :     const uint256* phashBlock{nullptr};
     143             : 
     144             :     //! pointer to the index of the predecessor of this block
     145             :     CBlockIndex* pprev{nullptr};
     146             : 
     147             :     //! pointer to the index of some further predecessor of this block
     148             :     CBlockIndex* pskip{nullptr};
     149             : 
     150             :     //! height of the entry in the chain. The genesis block has height 0
     151             :     int nHeight{0};
     152             : 
     153             :     //! Which # file this block is stored in (blk?????.dat)
     154             :     int nFile{0};
     155             : 
     156             :     //! Byte offset within blk?????.dat where this block's data is stored
     157             :     unsigned int nDataPos{0};
     158             : 
     159             :     //! Byte offset within rev?????.dat where this block's undo data is stored
     160             :     unsigned int nUndoPos{0};
     161             : 
     162             :     //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
     163             :     arith_uint256 nChainWork{};
     164             : 
     165             :     //! Number of transactions in this block.
     166             :     //! Note: in a potential headers-first mode, this number cannot be relied upon
     167             :     unsigned int nTx{0};
     168             : 
     169             :     //! (memory only) Number of transactions in the chain up to and including this block.
     170             :     //! This value will be non-zero only if and only if transactions for this block and all its parents are available.
     171             :     //! Change to 64-bit type when necessary; won't happen before 2030
     172             :     unsigned int nChainTx{0};
     173             : 
     174             :     //! Verification status of this block. See enum BlockStatus
     175             :     uint32_t nStatus{0};
     176             : 
     177             :     // proof-of-stake specific fields
     178             :     // char vector holding the stake modifier bytes. It is empty for PoW blocks.
     179             :     // Modifier V1 is 64 bit while modifier V2 is 256 bit.
     180             :     std::vector<unsigned char> vStakeModifier{};
     181             :     unsigned int nFlags{0};
     182             : 
     183             :     //! Change in value held by the Sapling circuit over this block.
     184             :     //! Not a Optional because this was added before Sapling activated, so we can
     185             :     //! rely on the invariant that every block before this was added had nSaplingValue = 0.
     186             :     CAmount nSaplingValue{0};
     187             : 
     188             :     //! (memory only) Total value held by the Sapling circuit up to and including this block.
     189             :     //! Will be nullopt if nChainTx is zero.
     190             :    Optional<CAmount> nChainSaplingValue{nullopt};
     191             : 
     192             :     //! block header
     193             :     int32_t nVersion{0};
     194             :     uint256 hashMerkleRoot{};
     195             :     uint256 hashFinalSaplingRoot{};
     196             :     uint32_t nTime{0};
     197             :     uint32_t nBits{0};
     198             :     uint32_t nNonce{0};
     199             :     uint256 nAccumulatorCheckpoint{};
     200             : 
     201             :     //! (memory only) Sequential id assigned to distinguish order in which blocks are received.
     202             :     uint32_t nSequenceId{0};
     203             : 
     204             :     //! (memory only) Maximum nTime in the chain upto and including this block.
     205             :     unsigned int nTimeMax{0};
     206             : 
     207     2462892 :     CBlockIndex() {}
     208             :     explicit CBlockIndex(const CBlock& block);
     209             : 
     210             :     std::string ToString() const;
     211             : 
     212             :     FlatFilePos GetBlockPos() const;
     213             :     FlatFilePos GetUndoPos() const;
     214             :     CBlockHeader GetBlockHeader() const;
     215     5829242 :     uint256 GetBlockHash() const { return *phashBlock; }
     216     5735697 :     int64_t GetBlockTime() const { return (int64_t)nTime; }
     217      168682 :     int64_t GetBlockTimeMax() const { return (int64_t)nTimeMax; }
     218             : 
     219             :     int64_t GetMedianTimePast() const;
     220             : 
     221             :     int64_t MaxFutureBlockTime() const;
     222             :     int64_t MinPastBlockTime() const;
     223             : 
     224     1388534 :     bool IsProofOfStake() const { return (nFlags & BLOCK_PROOF_OF_STAKE); }
     225             :     bool IsProofOfWork() const { return !IsProofOfStake(); }
     226       15295 :     void SetProofOfStake() { nFlags |= BLOCK_PROOF_OF_STAKE; }
     227             : 
     228             :     // Stake Modifier
     229             :     unsigned int GetStakeEntropyBit() const;
     230             :     bool SetStakeEntropyBit(unsigned int nEntropyBit);
     231     2005606 :     bool GeneratedStakeModifier() const { return (nFlags & BLOCK_STAKE_MODIFIER); }
     232             :     void SetStakeModifier(const uint64_t nStakeModifier, bool fGeneratedStakeModifier);
     233             :     void SetNewStakeModifier();                             // generates and sets new v1 modifier
     234             :     void SetStakeModifier(const uint256& nStakeModifier);
     235             :     void SetNewStakeModifier(const uint256& prevoutId);     // generates and sets new v2 modifier
     236             :     uint64_t GetStakeModifierV1() const;
     237             :     uint256 GetStakeModifierV2() const;
     238             : 
     239             :     // Update Sapling chain value
     240             :     void SetChainSaplingValue();
     241             : 
     242             :     //! Check whether this block index entry is valid up to the passed validity level.
     243             :     bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const;
     244             :     //! Raise the validity level of this block index entry.
     245             :     //! Returns true if the validity was changed.
     246             :     bool RaiseValidity(enum BlockStatus nUpTo);
     247             :     //! Build the skiplist pointer for this entry.
     248             :     void BuildSkip();
     249             :     //! Efficiently find an ancestor of this block.
     250             :     CBlockIndex* GetAncestor(int height);
     251             :     const CBlockIndex* GetAncestor(int height) const;
     252             : };
     253             : 
     254             : /** Find the forking point between two chain tips. */
     255             : const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb);
     256             : 
     257             : /** Used to marshal pointers into hashes for db storage. */
     258             : 
     259             : // New serialization introduced with 4.0.99
     260             : static const int DBI_OLD_SER_VERSION = 4009900;
     261             : static const int DBI_SER_VERSION_NO_ZC = 4009902;   // removes mapZerocoinSupply, nMoneySupply
     262             : 
     263      143725 : class CDiskBlockIndex : public CBlockIndex
     264             : {
     265             : public:
     266             :     uint256 hashPrev;
     267             : 
     268       32806 :     CDiskBlockIndex()
     269       32806 :     {
     270       32806 :         hashPrev = UINT256_ZERO;
     271       32806 :     }
     272             : 
     273       39236 :     explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex)
     274             :     {
     275       39236 :         hashPrev = (pprev ? pprev->GetBlockHash() : UINT256_ZERO);
     276       39236 :     }
     277             : 
     278      144084 :     SERIALIZE_METHODS(CDiskBlockIndex, obj)
     279             :     {
     280       72042 :         int nSerVersion = s.GetVersion();
     281       72042 :         if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT_MODE(nSerVersion, VarIntMode::NONNEGATIVE_SIGNED));
     282             : 
     283       72042 :         READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));
     284       72042 :         READWRITE(VARINT(obj.nStatus));
     285       72042 :         READWRITE(VARINT(obj.nTx));
     286       72042 :         if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));
     287       72042 :         if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos));
     288       72042 :         if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos));
     289             : 
     290       72042 :         if (nSerVersion >= DBI_SER_VERSION_NO_ZC) {
     291             :             // Serialization with CLIENT_VERSION = 4009902+
     292       72042 :             READWRITE(obj.nFlags);
     293       72042 :             READWRITE(obj.nVersion);
     294       72042 :             READWRITE(obj.vStakeModifier);
     295       72042 :             READWRITE(obj.hashPrev);
     296       72042 :             READWRITE(obj.hashMerkleRoot);
     297       72042 :             READWRITE(obj.nTime);
     298       72042 :             READWRITE(obj.nBits);
     299       72042 :             READWRITE(obj.nNonce);
     300       72042 :             if(obj.nVersion > 3 && obj.nVersion < 7)
     301       10786 :                 READWRITE(obj.nAccumulatorCheckpoint);
     302             : 
     303             :             // Sapling blocks
     304       72042 :             if (obj.nVersion >= 8) {
     305       21365 :                 READWRITE(obj.hashFinalSaplingRoot);
     306       21365 :                 READWRITE(obj.nSaplingValue);
     307             :             }
     308           0 :         } else if (nSerVersion > DBI_OLD_SER_VERSION && ser_action.ForRead()) {
     309             :             // Serialization with CLIENT_VERSION = 4009901
     310           0 :             std::map<libzerocoin::CoinDenomination, int64_t> mapZerocoinSupply;
     311           0 :             int64_t nMoneySupply = 0;
     312           0 :             READWRITE(nMoneySupply);
     313           0 :             READWRITE(obj.nFlags);
     314           0 :             READWRITE(obj.nVersion);
     315           0 :             READWRITE(obj.vStakeModifier);
     316           0 :             READWRITE(obj.hashPrev);
     317           0 :             READWRITE(obj.hashMerkleRoot);
     318           0 :             READWRITE(obj.nTime);
     319           0 :             READWRITE(obj.nBits);
     320           0 :             READWRITE(obj.nNonce);
     321           0 :             if (obj.nVersion > 3) {
     322           0 :                 READWRITE(mapZerocoinSupply);
     323           0 :                 if (obj.nVersion < 7) READWRITE(obj.nAccumulatorCheckpoint);
     324             :             }
     325             :         } else if (ser_action.ForRead()) {
     326             :             // Serialization with CLIENT_VERSION = 4009900-
     327           0 :             int64_t nMint = 0;
     328           0 :             uint256 hashNext{};
     329           0 :             int64_t nMoneySupply = 0;
     330           0 :             READWRITE(nMint);
     331           0 :             READWRITE(nMoneySupply);
     332           0 :             READWRITE(obj.nFlags);
     333           0 :             if (!Params().GetConsensus().NetworkUpgradeActive(obj.nHeight, Consensus::UPGRADE_V3_4)) {
     334           0 :                 uint64_t nStakeModifier = 0;
     335           0 :                 READWRITE(nStakeModifier);
     336           0 :                 SER_READ(obj, obj.SetStakeModifier(nStakeModifier, obj.GeneratedStakeModifier()));
     337             :             } else {
     338           0 :                 uint256 nStakeModifierV2;
     339           0 :                 READWRITE(nStakeModifierV2);
     340           0 :                 SER_READ(obj, obj.SetStakeModifier(nStakeModifierV2));
     341             :             }
     342           0 :             if (obj.IsProofOfStake()) {
     343           0 :                 COutPoint prevoutStake;
     344           0 :                 unsigned int nStakeTime = 0;
     345           0 :                 READWRITE(prevoutStake);
     346           0 :                 READWRITE(nStakeTime);
     347             :             }
     348           0 :             READWRITE(obj.nVersion);
     349           0 :             READWRITE(obj.hashPrev);
     350           0 :             READWRITE(hashNext);
     351           0 :             READWRITE(obj.hashMerkleRoot);
     352           0 :             READWRITE(obj.nTime);
     353           0 :             READWRITE(obj.nBits);
     354           0 :             READWRITE(obj.nNonce);
     355           0 :             if (obj.nVersion > 3) {
     356           0 :                 std::map<libzerocoin::CoinDenomination, int64_t> mapZerocoinSupply;
     357           0 :                 std::vector<libzerocoin::CoinDenomination> vMintDenominationsInBlock;
     358           0 :                 READWRITE(obj.nAccumulatorCheckpoint);
     359           0 :                 READWRITE(mapZerocoinSupply);
     360           0 :                 READWRITE(vMintDenominationsInBlock);
     361             :             }
     362             :         }
     363       72042 :     }
     364             : 
     365       32806 :     uint256 GetBlockHash() const
     366             :     {
     367       32806 :         CBlockHeader block;
     368       32806 :         block.nVersion = nVersion;
     369       32806 :         block.hashPrevBlock = hashPrev;
     370       32806 :         block.hashMerkleRoot = hashMerkleRoot;
     371       32806 :         block.nTime = nTime;
     372       32806 :         block.nBits = nBits;
     373       32806 :         block.nNonce = nNonce;
     374       32806 :         if (nVersion > 3 && nVersion < 7)
     375        8008 :             block.nAccumulatorCheckpoint = nAccumulatorCheckpoint;
     376       32806 :         if (nVersion >= 8)
     377        1699 :             block.hashFinalSaplingRoot = hashFinalSaplingRoot;
     378       32806 :         return block.GetHash();
     379             :     }
     380             : 
     381             : 
     382             :     std::string ToString() const
     383             :     {
     384             :         return strprintf("CDiskBlockIndex(%s\n                hashBlock=%s, hashPrev=%s)",
     385             :                 CBlockIndex::ToString(),
     386             :                 GetBlockHash().ToString(),
     387             :                 hashPrev.ToString());
     388             :     }
     389             : };
     390             : 
     391             : /** An in-memory indexed chain of blocks. */
     392           6 : class CChain
     393             : {
     394             : private:
     395             :     std::vector<CBlockIndex*> vChain;
     396             : 
     397             : public:
     398             :     /** Returns the index entry for the genesis block of this chain, or nullptr if none. */
     399      124786 :     CBlockIndex* Genesis() const
     400             :     {
     401      124786 :         return vChain.size() > 0 ? vChain[0] : nullptr;
     402             :     }
     403             : 
     404             :     /** Returns the index entry for the tip of this chain, or nullptr if none. */
     405    34160650 :     CBlockIndex* Tip(bool fProofOfStake = false) const
     406             :     {
     407    34160650 :         if (vChain.size() < 1)
     408             :             return nullptr;
     409             : 
     410    34074270 :         CBlockIndex* pindex = vChain[vChain.size() - 1];
     411             : 
     412    34074270 :         if (fProofOfStake) {
     413             :             while (pindex && pindex->pprev && !pindex->IsProofOfStake())
     414             :                 pindex = pindex->pprev;
     415             :         }
     416             :         return pindex;
     417             :     }
     418             : 
     419             :     /** Returns the index entry at a particular height in this chain, or nullptr if no such height exists. */
     420      400475 :     CBlockIndex* operator[](int nHeight) const
     421             :     {
     422      400475 :         if (nHeight < 0 || nHeight >= (int)vChain.size())
     423             :             return nullptr;
     424      356557 :         return vChain[nHeight];
     425             :     }
     426             : 
     427             :     /** Compare two chains efficiently. */
     428             :     friend bool operator==(const CChain& a, const CChain& b)
     429             :     {
     430             :         return a.vChain.size() == b.vChain.size() &&
     431             :                a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1];
     432             :     }
     433             : 
     434             :     /** Efficiently check whether a block is present in this chain. */
     435      303470 :     bool Contains(const CBlockIndex* pindex) const
     436             :     {
     437      542148 :         return (*this)[pindex->nHeight] == pindex;
     438             :     }
     439             : 
     440             :     /** Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip. */
     441       32396 :     CBlockIndex* Next(const CBlockIndex* pindex) const
     442             :     {
     443       64792 :         if (Contains(pindex))
     444       32396 :             return (*this)[pindex->nHeight + 1];
     445             :         else
     446             :             return nullptr;
     447             :     }
     448             : 
     449             :     /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
     450     2201705 :     int Height() const
     451             :     {
     452     2156916 :         return vChain.size() - 1;
     453             :     }
     454             : 
     455             :     /** Set/initialize a chain with a given tip. */
     456             :     void SetTip(CBlockIndex* pindex);
     457             : 
     458             :     /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
     459             :     CBlockLocator GetLocator(const CBlockIndex* pindex = nullptr) const;
     460             : 
     461             :     /** Find the last common block between this chain and a block index entry. */
     462             :     const CBlockIndex* FindFork(const CBlockIndex* pindex) const;
     463             : 
     464             :     /** Find the earliest block with timestamp equal or greater than the given. */
     465             :     CBlockIndex* FindEarliestAtLeast(int64_t nTime) const;
     466             : };
     467             : 
     468             : #endif // PIVX_CHAIN_H

Generated by: LCOV version 1.14