LCOV - code coverage report
Current view: top level - src - chain.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 120 135 88.9 %
Date: 2015-10-12 22:39:14 Functions: 20 37 54.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #ifndef BITCOIN_CHAIN_H
       7             : #define BITCOIN_CHAIN_H
       8             : 
       9             : #include "arith_uint256.h"
      10             : #include "primitives/block.h"
      11             : #include "pow.h"
      12             : #include "tinyformat.h"
      13             : #include "uint256.h"
      14             : 
      15             : #include <vector>
      16             : 
      17             : #include <boost/foreach.hpp>
      18             : 
      19             : struct CDiskBlockPos
      20             : {
      21             :     int nFile;
      22             :     unsigned int nPos;
      23             : 
      24         221 :     ADD_SERIALIZE_METHODS;
      25             : 
      26             :     template <typename Stream, typename Operation>
      27         221 :     inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
      28         221 :         READWRITE(VARINT(nFile));
      29         221 :         READWRITE(VARINT(nPos));
      30         221 :     }
      31             : 
      32           0 :     CDiskBlockPos() {
      33             :         SetNull();
      34           0 :     }
      35             : 
      36           0 :     CDiskBlockPos(int nFileIn, unsigned int nPosIn) {
      37        7023 :         nFile = nFileIn;
      38        7023 :         nPos = nPosIn;
      39           0 :     }
      40             : 
      41             :     friend bool operator==(const CDiskBlockPos &a, const CDiskBlockPos &b) {
      42             :         return (a.nFile == b.nFile && a.nPos == b.nPos);
      43             :     }
      44             : 
      45             :     friend bool operator!=(const CDiskBlockPos &a, const CDiskBlockPos &b) {
      46             :         return !(a == b);
      47             :     }
      48             : 
      49       75225 :     void SetNull() { nFile = -1; nPos = 0; }
      50           0 :     bool IsNull() const { return (nFile == -1); }
      51             : 
      52             :     std::string ToString() const
      53             :     {
      54           0 :         return strprintf("CBlockDiskPos(nFile=%i, nPos=%i)", nFile, nPos);
      55             :     }
      56             : 
      57             : };
      58             : 
      59             : enum BlockStatus {
      60             :     //! Unused.
      61             :     BLOCK_VALID_UNKNOWN      =    0,
      62             : 
      63             :     //! Parsed, version ok, hash satisfies claimed PoW, 1 <= vtx count <= max, timestamp not in future
      64             :     BLOCK_VALID_HEADER       =    1,
      65             : 
      66             :     //! All parent headers found, difficulty matches, timestamp >= median previous, checkpoint. Implies all parents
      67             :     //! are also at least TREE.
      68             :     BLOCK_VALID_TREE         =    2,
      69             : 
      70             :     /**
      71             :      * Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids,
      72             :      * sigops, size, merkle root. Implies all parents are at least TREE but not necessarily TRANSACTIONS. When all
      73             :      * parent blocks also have TRANSACTIONS, CBlockIndex::nChainTx will be set.
      74             :      */
      75             :     BLOCK_VALID_TRANSACTIONS =    3,
      76             : 
      77             :     //! Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends, BIP30.
      78             :     //! Implies all parents are also at least CHAIN.
      79             :     BLOCK_VALID_CHAIN        =    4,
      80             : 
      81             :     //! Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
      82             :     BLOCK_VALID_SCRIPTS      =    5,
      83             : 
      84             :     //! All validity bits.
      85             :     BLOCK_VALID_MASK         =   BLOCK_VALID_HEADER | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS |
      86             :                                  BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS,
      87             : 
      88             :     BLOCK_HAVE_DATA          =    8, //! full block available in blk*.dat
      89             :     BLOCK_HAVE_UNDO          =   16, //! undo data available in rev*.dat
      90             :     BLOCK_HAVE_MASK          =   BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO,
      91             : 
      92             :     BLOCK_FAILED_VALID       =   32, //! stage after last reached validness failed
      93             :     BLOCK_FAILED_CHILD       =   64, //! descends from failed block
      94             :     BLOCK_FAILED_MASK        =   BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
      95             : };
      96             : 
      97             : /** The block chain is a tree shaped structure starting with the
      98             :  * genesis block at the root, with each block potentially having multiple
      99             :  * candidates to be the next block. A blockindex may have multiple pprev pointing
     100             :  * to it, but at most one of them can be part of the currently active branch.
     101             :  */
     102      930646 : class CBlockIndex
     103             : {
     104             : public:
     105             :     //! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
     106             :     const uint256* phashBlock;
     107             : 
     108             :     //! pointer to the index of the predecessor of this block
     109             :     CBlockIndex* pprev;
     110             : 
     111             :     //! pointer to the index of some further predecessor of this block
     112             :     CBlockIndex* pskip;
     113             : 
     114             :     //! height of the entry in the chain. The genesis block has height 0
     115             :     int nHeight;
     116             : 
     117             :     //! Which # file this block is stored in (blk?????.dat)
     118             :     int nFile;
     119             : 
     120             :     //! Byte offset within blk?????.dat where this block's data is stored
     121             :     unsigned int nDataPos;
     122             : 
     123             :     //! Byte offset within rev?????.dat where this block's undo data is stored
     124             :     unsigned int nUndoPos;
     125             : 
     126             :     //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
     127             :     arith_uint256 nChainWork;
     128             : 
     129             :     //! Number of transactions in this block.
     130             :     //! Note: in a potential headers-first mode, this number cannot be relied upon
     131             :     unsigned int nTx;
     132             : 
     133             :     //! (memory only) Number of transactions in the chain up to and including this block.
     134             :     //! This value will be non-zero only if and only if transactions for this block and all its parents are available.
     135             :     //! Change to 64-bit type when necessary; won't happen before 2030
     136             :     unsigned int nChainTx;
     137             : 
     138             :     //! Verification status of this block. See enum BlockStatus
     139             :     unsigned int nStatus;
     140             : 
     141             :     //! block header
     142             :     int nVersion;
     143             :     uint256 hashMerkleRoot;
     144             :     unsigned int nTime;
     145             :     unsigned int nBits;
     146             :     unsigned int nNonce;
     147             : 
     148             :     //! (memory only) Sequential id assigned to distinguish order in which blocks are received.
     149             :     uint32_t nSequenceId;
     150             : 
     151       29275 :     void SetNull()
     152             :     {
     153       29275 :         phashBlock = NULL;
     154       29275 :         pprev = NULL;
     155       29275 :         pskip = NULL;
     156       29275 :         nHeight = 0;
     157       29275 :         nFile = 0;
     158       29275 :         nDataPos = 0;
     159       29275 :         nUndoPos = 0;
     160       29275 :         nChainWork = arith_uint256();
     161       29275 :         nTx = 0;
     162       29275 :         nChainTx = 0;
     163       29275 :         nStatus = 0;
     164       29275 :         nSequenceId = 0;
     165             : 
     166       29275 :         nVersion       = 0;
     167       29275 :         hashMerkleRoot = uint256();
     168       29275 :         nTime          = 0;
     169       29275 :         nBits          = 0;
     170       29275 :         nNonce         = 0;
     171       29275 :     }
     172             : 
     173       22386 :     CBlockIndex()
     174       44772 :     {
     175       22386 :         SetNull();
     176       22386 :     }
     177             : 
     178        6889 :     CBlockIndex(const CBlockHeader& block)
     179       13778 :     {
     180        6889 :         SetNull();
     181             : 
     182        6889 :         nVersion       = block.nVersion;
     183        6889 :         hashMerkleRoot = block.hashMerkleRoot;
     184        6889 :         nTime          = block.nTime;
     185        6889 :         nBits          = block.nBits;
     186        6889 :         nNonce         = block.nNonce;
     187        6889 :     }
     188             : 
     189           0 :     CDiskBlockPos GetBlockPos() const {
     190             :         CDiskBlockPos ret;
     191       31186 :         if (nStatus & BLOCK_HAVE_DATA) {
     192       29833 :             ret.nFile = nFile;
     193       29833 :             ret.nPos  = nDataPos;
     194             :         }
     195           0 :         return ret;
     196             :     }
     197             : 
     198           0 :     CDiskBlockPos GetUndoPos() const {
     199             :         CDiskBlockPos ret;
     200       33088 :         if (nStatus & BLOCK_HAVE_UNDO) {
     201       22224 :             ret.nFile = nFile;
     202       22224 :             ret.nPos  = nUndoPos;
     203             :         }
     204           0 :         return ret;
     205             :     }
     206             : 
     207      188107 :     CBlockHeader GetBlockHeader() const
     208             :     {
     209      188107 :         CBlockHeader block;
     210      188107 :         block.nVersion       = nVersion;
     211      188107 :         if (pprev)
     212      376214 :             block.hashPrevBlock = pprev->GetBlockHash();
     213      188107 :         block.hashMerkleRoot = hashMerkleRoot;
     214      188107 :         block.nTime          = nTime;
     215      188107 :         block.nBits          = nBits;
     216      188107 :         block.nNonce         = nNonce;
     217      188107 :         return block;
     218             :     }
     219             : 
     220           0 :     uint256 GetBlockHash() const
     221             :     {
     222     1017133 :         return *phashBlock;
     223             :     }
     224             : 
     225           0 :     int64_t GetBlockTime() const
     226             :     {
     227      135336 :         return (int64_t)nTime;
     228             :     }
     229             : 
     230             :     enum { nMedianTimeSpan=11 };
     231             : 
     232        8293 :     int64_t GetMedianTimePast() const
     233             :     {
     234             :         int64_t pmedian[nMedianTimeSpan];
     235        8293 :         int64_t* pbegin = &pmedian[nMedianTimeSpan];
     236        8293 :         int64_t* pend = &pmedian[nMedianTimeSpan];
     237             : 
     238        8293 :         const CBlockIndex* pindex = this;
     239       96418 :         for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
     240      176250 :             *(--pbegin) = pindex->GetBlockTime();
     241             : 
     242             :         std::sort(pbegin, pend);
     243        8293 :         return pbegin[(pend - pbegin)/2];
     244             :     }
     245             : 
     246           0 :     std::string ToString() const
     247             :     {
     248             :         return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
     249             :             pprev, nHeight,
     250             :             hashMerkleRoot.ToString(),
     251           0 :             GetBlockHash().ToString());
     252             :     }
     253             : 
     254             :     //! Check whether this block index entry is valid up to the passed validity level.
     255      165815 :     bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const
     256             :     {
     257      165815 :         assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
     258      165815 :         if (nStatus & BLOCK_FAILED_MASK)
     259             :             return false;
     260      165706 :         return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
     261             :     }
     262             : 
     263             :     //! Raise the validity level of this block index entry.
     264             :     //! Returns true if the validity was changed.
     265       16486 :     bool RaiseValidity(enum BlockStatus nUpTo)
     266             :     {
     267       16486 :         assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
     268       16486 :         if (nStatus & BLOCK_FAILED_MASK)
     269             :             return false;
     270       16486 :         if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {
     271       16486 :             nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
     272           0 :             return true;
     273             :         }
     274             :         return false;
     275             :     }
     276             : 
     277             :     //! Build the skiplist pointer for this entry.
     278             :     void BuildSkip();
     279             : 
     280             :     //! Efficiently find an ancestor of this block.
     281             :     CBlockIndex* GetAncestor(int height);
     282             :     const CBlockIndex* GetAncestor(int height) const;
     283             : };
     284             : 
     285             : /** Used to marshal pointers into hashes for db storage. */
     286             : class CDiskBlockIndex : public CBlockIndex
     287             : {
     288             : public:
     289             :     uint256 hashPrev;
     290             : 
     291       11139 :     CDiskBlockIndex() {
     292       11139 :         hashPrev = uint256();
     293       11139 :     }
     294             : 
     295        5323 :     explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex) {
     296       10646 :         hashPrev = (pprev ? pprev->GetBlockHash() : uint256());
     297        5323 :     }
     298             : 
     299       21785 :     ADD_SERIALIZE_METHODS;
     300             : 
     301             :     template <typename Stream, typename Operation>
     302       21785 :     inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
     303       21785 :         if (!(nType & SER_GETHASH))
     304       21785 :             READWRITE(VARINT(nVersion));
     305             : 
     306       21785 :         READWRITE(VARINT(nHeight));
     307       21785 :         READWRITE(VARINT(nStatus));
     308       21785 :         READWRITE(VARINT(nTx));
     309       21785 :         if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO))
     310       21749 :             READWRITE(VARINT(nFile));
     311       21785 :         if (nStatus & BLOCK_HAVE_DATA)
     312       21749 :             READWRITE(VARINT(nDataPos));
     313       21785 :         if (nStatus & BLOCK_HAVE_UNDO)
     314       21524 :             READWRITE(VARINT(nUndoPos));
     315             : 
     316             :         // block header
     317       21785 :         READWRITE(this->nVersion);
     318       21785 :         READWRITE(hashPrev);
     319       21785 :         READWRITE(hashMerkleRoot);
     320       21785 :         READWRITE(nTime);
     321       21785 :         READWRITE(nBits);
     322       21785 :         READWRITE(nNonce);
     323       21785 :     }
     324             : 
     325       11139 :     uint256 GetBlockHash() const
     326             :     {
     327       11139 :         CBlockHeader block;
     328       11139 :         block.nVersion        = nVersion;
     329       11139 :         block.hashPrevBlock   = hashPrev;
     330       11139 :         block.hashMerkleRoot  = hashMerkleRoot;
     331       11139 :         block.nTime           = nTime;
     332       11139 :         block.nBits           = nBits;
     333       11139 :         block.nNonce          = nNonce;
     334       11139 :         return block.GetHash();
     335             :     }
     336             : 
     337             : 
     338             :     std::string ToString() const
     339             :     {
     340             :         std::string str = "CDiskBlockIndex(";
     341             :         str += CBlockIndex::ToString();
     342             :         str += strprintf("\n                hashBlock=%s, hashPrev=%s)",
     343             :             GetBlockHash().ToString(),
     344             :             hashPrev.ToString());
     345             :         return str;
     346             :     }
     347             : };
     348             : 
     349             : /** An in-memory indexed chain of blocks. */
     350         291 : class CChain {
     351             : private:
     352             :     std::vector<CBlockIndex*> vChain;
     353             : 
     354             : public:
     355             :     /** Returns the index entry for the genesis block of this chain, or NULL if none. */
     356             :     CBlockIndex *Genesis() const {
     357       29408 :         return vChain.size() > 0 ? vChain[0] : NULL;
     358             :     }
     359             : 
     360             :     /** Returns the index entry for the tip of this chain, or NULL if none. */
     361             :     CBlockIndex *Tip() const {
     362     7048940 :         return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL;
     363             :     }
     364             : 
     365             :     /** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */
     366             :     CBlockIndex *operator[](int nHeight) const {
     367     1370708 :         if (nHeight < 0 || nHeight >= (int)vChain.size())
     368             :             return NULL;
     369     1154338 :         return vChain[nHeight];
     370             :     }
     371             : 
     372             :     /** Compare two chains efficiently. */
     373             :     friend bool operator==(const CChain &a, const CChain &b) {
     374             :         return a.vChain.size() == b.vChain.size() &&
     375             :                a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1];
     376             :     }
     377             : 
     378             :     /** Efficiently check whether a block is present in this chain. */
     379             :     bool Contains(const CBlockIndex *pindex) const {
     380      452762 :         return (*this)[pindex->nHeight] == pindex;
     381             :     }
     382             : 
     383             :     /** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */
     384      197435 :     CBlockIndex *Next(const CBlockIndex *pindex) const {
     385      197435 :         if (Contains(pindex))
     386      394870 :             return (*this)[pindex->nHeight + 1];
     387             :         else
     388             :             return NULL;
     389             :     }
     390             : 
     391             :     /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
     392             :     int Height() const {
     393      788702 :         return vChain.size() - 1;
     394             :     }
     395             : 
     396             :     /** Set/initialize a chain with a given tip. */
     397             :     void SetTip(CBlockIndex *pindex);
     398             : 
     399             :     /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
     400             :     CBlockLocator GetLocator(const CBlockIndex *pindex = NULL) const;
     401             : 
     402             :     /** Find the last common block between this chain and a block index entry. */
     403             :     const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
     404             : };
     405             : 
     406             : #endif // BITCOIN_CHAIN_H

Generated by: LCOV version 1.11