]> Git Repo - VerusCoin.git/blob - src/chain.h
Merge branch 'dev' of github.com:miketout/VerusCoin into dev
[VerusCoin.git] / src / chain.h
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 https://www.opensource.org/licenses/mit-license.php .
5
6 #ifndef BITCOIN_CHAIN_H
7 #define BITCOIN_CHAIN_H
8
9 class CChainPower;
10
11 #include "arith_uint256.h"
12 #include "primitives/block.h"
13 #include "pow.h"
14 #include "tinyformat.h"
15 #include "uint256.h"
16 #include "mmr.h"
17
18 #include <vector>
19
20 static const int SPROUT_VALUE_VERSION = 1001400;
21 static const int SAPLING_VALUE_VERSION = 1010100;
22
23 class CBlockFileInfo
24 {
25 public:
26     unsigned int nBlocks;      //!< number of blocks stored in file
27     unsigned int nSize;        //!< number of used bytes of block file
28     unsigned int nUndoSize;    //!< number of used bytes in the undo file
29     unsigned int nHeightFirst; //!< lowest height of block in file
30     unsigned int nHeightLast;  //!< highest height of block in file
31     uint64_t nTimeFirst;       //!< earliest time of block in file
32     uint64_t nTimeLast;        //!< latest time of block in file
33
34     ADD_SERIALIZE_METHODS;
35
36     template <typename Stream, typename Operation>
37     inline void SerializationOp(Stream& s, Operation ser_action) {
38         READWRITE(VARINT(nBlocks));
39         READWRITE(VARINT(nSize));
40         READWRITE(VARINT(nUndoSize));
41         READWRITE(VARINT(nHeightFirst));
42         READWRITE(VARINT(nHeightLast));
43         READWRITE(VARINT(nTimeFirst));
44         READWRITE(VARINT(nTimeLast));
45     }
46
47      void SetNull() {
48          nBlocks = 0;
49          nSize = 0;
50          nUndoSize = 0;
51          nHeightFirst = 0;
52          nHeightLast = 0;
53          nTimeFirst = 0;
54          nTimeLast = 0;
55      }
56
57      CBlockFileInfo() {
58          SetNull();
59      }
60
61      std::string ToString() const;
62
63      /** update statistics (does not update nSize) */
64      void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) {
65          if (nBlocks==0 || nHeightFirst > nHeightIn)
66              nHeightFirst = nHeightIn;
67          if (nBlocks==0 || nTimeFirst > nTimeIn)
68              nTimeFirst = nTimeIn;
69          nBlocks++;
70          if (nHeightIn > nHeightLast)
71              nHeightLast = nHeightIn;
72          if (nTimeIn > nTimeLast)
73              nTimeLast = nTimeIn;
74      }
75 };
76
77 struct CDiskBlockPos
78 {
79     int nFile;
80     unsigned int nPos;
81
82     ADD_SERIALIZE_METHODS;
83
84     template <typename Stream, typename Operation>
85     inline void SerializationOp(Stream& s, Operation ser_action) {
86         READWRITE(VARINT(nFile));
87         READWRITE(VARINT(nPos));
88     }
89
90     CDiskBlockPos() {
91         SetNull();
92     }
93
94     CDiskBlockPos(int nFileIn, unsigned int nPosIn) {
95         nFile = nFileIn;
96         nPos = nPosIn;
97     }
98
99     friend bool operator==(const CDiskBlockPos &a, const CDiskBlockPos &b) {
100         return (a.nFile == b.nFile && a.nPos == b.nPos);
101     }
102
103     friend bool operator!=(const CDiskBlockPos &a, const CDiskBlockPos &b) {
104         return !(a == b);
105     }
106
107     void SetNull() { nFile = -1; nPos = 0; }
108     bool IsNull() const { return (nFile == -1); }
109
110     std::string ToString() const
111     {
112         return strprintf("CBlockDiskPos(nFile=%i, nPos=%i)", nFile, nPos);
113     }
114
115 };
116
117 enum BlockStatus: uint32_t {
118     //! Unused.
119     BLOCK_VALID_UNKNOWN      =    0,
120
121     //! Parsed, version ok, hash satisfies claimed PoW, 1 <= vtx count <= max, timestamp not in future
122     BLOCK_VALID_HEADER       =    1,
123
124     //! All parent headers found, difficulty matches, timestamp >= median previous, checkpoint. Implies all parents
125     //! are also at least TREE.
126     BLOCK_VALID_TREE         =    2,
127
128     /**
129      * Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids,
130      * sigops, size, merkle root. Implies all parents are at least TREE but not necessarily TRANSACTIONS. When all
131      * parent blocks also have TRANSACTIONS, CBlockIndex::nChainTx will be set.
132      */
133     BLOCK_VALID_TRANSACTIONS =    3,
134
135     //! Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends, BIP30.
136     //! Implies all parents are also at least CHAIN.
137     BLOCK_VALID_CHAIN        =    4,
138
139     //! Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
140     BLOCK_VALID_SCRIPTS      =    5,
141
142     //! All validity bits.
143     BLOCK_VALID_MASK         =   BLOCK_VALID_HEADER | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS |
144                                  BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS,
145
146     BLOCK_HAVE_DATA          =    8, //! full block available in blk*.dat
147     BLOCK_HAVE_UNDO          =   16, //! undo data available in rev*.dat
148     BLOCK_HAVE_MASK          =   BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO,
149
150     BLOCK_FAILED_VALID       =   32, //! stage after last reached validness failed
151     BLOCK_FAILED_CHILD       =   64, //! descends from failed block
152     BLOCK_FAILED_MASK        =   BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
153
154     BLOCK_ACTIVATES_UPGRADE  =   128, //! block activates a network upgrade
155 };
156
157 //! Short-hand for the highest consensus validity we implement.
158 //! Blocks with this validity are assumed to satisfy all consensus rules.
159 static const BlockStatus BLOCK_VALID_CONSENSUS = BLOCK_VALID_SCRIPTS;
160
161 class CBlockIndex;
162
163 // This class provides an accumulator for both the chainwork and the chainPOS value
164 // CChainPower's can be compared, and the comparison ensures that work and proof of stake power
165 // are both used equally to determine which chain has the most work. This makes an attack
166 // that involves mining in secret completely ineffective, even before dPOW, unless a large part 
167 // of the staking supply is also controlled. It also enables a faster deterministic convergence, 
168 // aided by both POS and POW.
169 class CChainPower
170 {
171     public:
172         arith_uint256 chainWork;
173         arith_uint256 chainStake;
174         int32_t nHeight;
175
176         CChainPower() : nHeight(0), chainStake(0), chainWork(0) {}
177         CChainPower(CBlockIndex *pblockIndex);
178         CChainPower(CBlockIndex *pblockIndex, const arith_uint256 &stake, const arith_uint256 &work);
179         CChainPower(int32_t height) : nHeight(height), chainStake(0), chainWork(0) {}
180         CChainPower(int32_t height, const arith_uint256 &stake, const arith_uint256 &work) : 
181                     nHeight(height), chainStake(stake), chainWork(work) {}
182
183         CChainPower &operator=(const CChainPower &chainPower)
184         {
185             chainWork = chainPower.chainWork;
186             chainStake = chainPower.chainStake;
187             nHeight = chainPower.nHeight;
188             return *this;
189         }
190
191         CChainPower &operator+=(const CChainPower &chainPower)
192         {
193             this->chainWork += chainPower.chainWork;
194             this->chainStake += chainPower.chainStake;
195             return *this;
196         }
197
198         friend CChainPower operator+(const CChainPower &chainPowerA, const CChainPower &chainPowerB)
199         {
200             CChainPower result = CChainPower(chainPowerA);
201             result.chainWork += chainPowerB.chainWork;
202             result.chainStake += chainPowerB.chainStake;
203             return result;
204         }
205
206         friend CChainPower operator-(const CChainPower &chainPowerA, const CChainPower &chainPowerB)
207         {
208             CChainPower result = CChainPower(chainPowerA);
209             result.chainWork -= chainPowerB.chainWork;
210             result.chainStake -= chainPowerB.chainStake;
211             return result;
212         }
213
214         friend CChainPower operator*(const CChainPower &chainPower, int32_t x)
215         {
216             CChainPower result = CChainPower(chainPower);
217             result.chainWork *= x;
218             result.chainStake *= x;
219             return result;
220         }
221
222         CChainPower &addStake(const arith_uint256 &nChainStake)
223         {
224             chainStake += nChainStake;
225             return *this;
226         }
227
228         CChainPower &addWork(const arith_uint256 &nChainWork)
229         {
230             chainWork += nChainWork;
231             return *this;
232         }
233
234         friend bool operator==(const CChainPower &p1, const CChainPower &p2);
235
236         friend bool operator!=(const CChainPower &p1, const CChainPower &p2)
237         {
238             return !(p1 == p2);
239         }
240
241         friend bool operator<(const CChainPower &p1, const CChainPower &p2);
242
243         friend bool operator<=(const CChainPower &p1, const CChainPower &p2);
244
245         friend bool operator>(const CChainPower &p1, const CChainPower &p2)
246         {
247             return !(p1 <= p2);
248         }
249
250         friend bool operator>=(const CChainPower &p1, const CChainPower &p2)
251         {
252             return !(p1 < p2);
253         }
254 };
255
256 /** The block chain is a tree shaped structure starting with the
257  * genesis block at the root, with each block potentially having multiple
258  * candidates to be the next block. A blockindex may have multiple pprev pointing
259  * to it, but at most one of them can be part of the currently active branch.
260  */
261 class CBlockIndex
262 {
263 public:
264     //! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
265     const uint256* phashBlock;
266
267     //! pointer to the index of the predecessor of this block
268     CBlockIndex* pprev;
269
270     //! pointer to the index of some further predecessor of this block
271     CBlockIndex* pskip;
272
273     int64_t newcoins;
274     int64_t zfunds;
275     int64_t immature;       // how much in this block is immature
276     uint32_t maturity;      // when do the immature funds in this block mature?
277
278     int8_t segid; // jl777 fields
279
280     //! Which # file this block is stored in (blk?????.dat)
281     int nFile;
282
283     //! Byte offset within blk?????.dat where this block's data is stored
284     unsigned int nDataPos;
285
286     //! Byte offset within rev?????.dat where this block's undo data is stored
287     unsigned int nUndoPos;
288
289     //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
290     CChainPower chainPower;
291
292     //! Number of transactions in this block.
293     //! Note: in a potential headers-first mode, this number cannot be relied upon
294     unsigned int nTx;
295
296     //! (memory only) Number of transactions in the chain up to and including this block.
297     //! This value will be non-zero only if and only if transactions for this block and all its parents are available.
298     //! Change to 64-bit type when necessary; won't happen before 2030
299     unsigned int nChainTx;
300
301     //! Verification status of this block. See enum BlockStatus
302     unsigned int nStatus;
303
304     //! Branch ID corresponding to the consensus rules used to validate this block.
305     //! Only cached if block validity is BLOCK_VALID_CONSENSUS.
306     //! Persisted at each activation height, memory-only for intervening blocks.
307     boost::optional<uint32_t> nCachedBranchId;
308
309     //! The anchor for the tree state up to the start of this block
310     uint256 hashSproutAnchor;
311
312     //! (memory only) The anchor for the tree state up to the end of this block
313     uint256 hashFinalSproutRoot;
314
315     //! Change in value held by the Sprout circuit over this block.
316     //! Will be boost::none for older blocks on old nodes until a reindex has taken place.
317     boost::optional<CAmount> nSproutValue;
318
319     //! (memory only) Total value held by the Sprout circuit up to and including this block.
320     //! Will be boost::none for on old nodes until a reindex has taken place.
321     //! Will be boost::none if nChainTx is zero.
322     boost::optional<CAmount> nChainSproutValue;
323
324     //! Change in value held by the Sapling circuit over this block.
325     //! Not a boost::optional because this was added before Sapling activated, so we can
326     //! rely on the invariant that every block before this was added had nSaplingValue = 0.
327     CAmount nSaplingValue;
328
329     //! (memory only) Total value held by the Sapling circuit up to and including this block.
330     //! Will be boost::none if nChainTx is zero.
331     boost::optional<CAmount> nChainSaplingValue;
332
333     //! block header
334     int nVersion;
335     uint256 hashMerkleRoot;
336     uint256 hashFinalSaplingRoot;
337     unsigned int nTime;
338     unsigned int nBits;
339     uint256 nNonce;
340     std::vector<unsigned char> nSolution;
341
342     //! (memory only) Sequential id assigned to distinguish order in which blocks are received.
343     uint32_t nSequenceId;
344     
345     void SetNull()
346     {
347         phashBlock = NULL;
348         newcoins = zfunds = 0;
349         maturity = 0;
350         immature = 0;
351         segid = -2;
352         pprev = NULL;
353         pskip = NULL;
354         nFile = 0;
355         nDataPos = 0;
356         nUndoPos = 0;
357         chainPower = CChainPower();
358         nTx = 0;
359         nChainTx = 0;
360         nStatus = 0;
361         nCachedBranchId = boost::none;
362         hashSproutAnchor = uint256();
363         hashFinalSproutRoot = uint256();
364         nSequenceId = 0;
365         nSproutValue = boost::none;
366         nChainSproutValue = boost::none;
367         nSaplingValue = 0;
368         nChainSaplingValue = boost::none;
369
370         nVersion       = 0;
371         hashMerkleRoot = uint256();
372         hashFinalSaplingRoot   = uint256();
373         nTime          = 0;
374         nBits          = 0;
375         nNonce         = uint256();
376         nSolution.clear();
377     }
378
379     CBlockIndex()
380     {
381         SetNull();
382     }
383
384     CBlockIndex(const CBlockHeader& block)
385     {
386         SetNull();
387
388         nVersion       = block.nVersion;
389         hashMerkleRoot = block.hashMerkleRoot;
390         hashFinalSaplingRoot   = block.hashFinalSaplingRoot;
391         nTime          = block.nTime;
392         nBits          = block.nBits;
393         nNonce         = block.nNonce;
394         nSolution      = block.nSolution;
395     }
396
397     void SetHeight(int32_t height)
398     {
399         this->chainPower.nHeight = height;
400     }
401
402     inline int32_t GetHeight() const
403     {
404         return this->chainPower.nHeight;
405     }
406
407     CDiskBlockPos GetBlockPos() const {
408         CDiskBlockPos ret;
409         if (nStatus & BLOCK_HAVE_DATA) {
410             ret.nFile = nFile;
411             ret.nPos  = nDataPos;
412         }
413         return ret;
414     }
415
416     CDiskBlockPos GetUndoPos() const {
417         CDiskBlockPos ret;
418         if (nStatus & BLOCK_HAVE_UNDO) {
419             ret.nFile = nFile;
420             ret.nPos  = nUndoPos;
421         }
422         return ret;
423     }
424
425     CBlockHeader GetBlockHeader() const
426     {
427         CBlockHeader block;
428         block.nVersion       = nVersion;
429         if (pprev)
430             block.hashPrevBlock = pprev->GetBlockHash();
431         block.hashMerkleRoot = hashMerkleRoot;
432         block.hashFinalSaplingRoot   = hashFinalSaplingRoot;
433         block.nTime          = nTime;
434         block.nBits          = nBits;
435         block.nNonce         = nNonce;
436         block.nSolution      = nSolution;
437         return block;
438     }
439
440     uint256 GetBlockHash() const
441     {
442         return *phashBlock;
443     }
444
445     int64_t GetBlockTime() const
446     {
447         return (int64_t)nTime;
448     }
449
450     enum { nMedianTimeSpan=11 };
451
452     int64_t GetMedianTimePast() const
453     {
454         int64_t pmedian[nMedianTimeSpan];
455         int64_t* pbegin = &pmedian[nMedianTimeSpan];
456         int64_t* pend = &pmedian[nMedianTimeSpan];
457
458         const CBlockIndex* pindex = this;
459         for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
460             *(--pbegin) = pindex->GetBlockTime();
461
462         std::sort(pbegin, pend);
463         return pbegin[(pend - pbegin)/2];
464     }
465
466     std::string ToString() const
467     {
468         return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
469             pprev, this->chainPower.nHeight,
470             hashMerkleRoot.ToString(),
471             GetBlockHash().ToString());
472     }
473
474     //! Check whether this block index entry is valid up to the passed validity level.
475     bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const
476     {
477         assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
478         if (nStatus & BLOCK_FAILED_MASK)
479             return false;
480         return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
481     }
482
483     //! Raise the validity level of this block index entry.
484     //! Returns true if the validity was changed.
485     bool RaiseValidity(enum BlockStatus nUpTo)
486     {
487         assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
488         if (nStatus & BLOCK_FAILED_MASK)
489             return false;
490         if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {
491             nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
492             return true;
493         }
494         return false;
495     }
496
497     //! Build the skiplist pointer for this entry.
498     void BuildSkip();
499
500     //! Efficiently find an ancestor of this block.
501     CBlockIndex* GetAncestor(int height);
502     const CBlockIndex* GetAncestor(int height) const;
503
504     int32_t GetVerusPOSTarget() const
505     {
506         return GetBlockHeader().GetVerusPOSTarget();
507     }
508
509     bool IsVerusPOSBlock() const
510     {
511         return GetBlockHeader().IsVerusPOSBlock();
512     }
513
514     bool GetRawVerusPOSHash(uint256 &ret) const;
515     uint256 GetVerusEntropyHashComponent() const;
516
517     uint256 BlockMMRRoot() const
518     {
519         if (nVersion == CBlockHeader::VERUS_V2)
520         {
521             CPBaaSSolutionDescriptor descr = CConstVerusSolutionVector::GetDescriptor((nSolution));
522             if (descr.version >= CActivationHeight::ACTIVATE_PBAAS)
523             {
524                 return descr.hashBlockMMRRoot;
525             }
526         }
527         return hashMerkleRoot;
528     }
529
530     uint256 PrevMMRRoot()
531     {
532         if (nVersion == CBlockHeader::VERUS_V2)
533         {
534             CPBaaSSolutionDescriptor descr = CConstVerusSolutionVector::GetDescriptor(nSolution);
535             if (descr.version >= CActivationHeight::ACTIVATE_PBAAS)
536             {
537                 return descr.hashPrevMMRRoot;
538             }
539         }
540         return uint256();
541     }
542
543     // return a node from this block index as is, including hash of merkle root and block hash as well as compact chain power, to put into an MMR
544     ChainMMRNode GetBlockMMRNode() const
545     {
546         uint256 blockHash = GetBlockHash();
547
548         uint256 preHash = ChainMMRNode::HashObj(BlockMMRRoot(), blockHash);
549         uint256 power = ArithToUint256(GetCompactPower(nNonce, nBits, nVersion));
550
551         return ChainMMRNode(ChainMMRNode::HashObj(preHash, power), power);
552     }
553
554     CMMRNodeBranch MMRProofBridge()
555     {
556         // we need to add the block hash on the right, no change to index, as bit is zero
557         return CMMRNodeBranch(CMMRNodeBranch::BRANCH_MMRBLAKE_NODE, 2, 0, std::vector<uint256>({GetBlockHash()}));
558     }
559
560     CMMRNodeBranch BlockProofBridge()
561     {
562         // we need to add the merkle root on the left
563         return CMMRNodeBranch(CMMRNodeBranch::BRANCH_MMRBLAKE_NODE, 2, 1, std::vector<uint256>({BlockMMRRoot()}));
564     }
565 };
566
567 /** Used to marshal pointers into hashes for db storage. */
568 class CDiskBlockIndex : public CBlockIndex
569 {
570 public:
571     uint256 hashPrev;
572
573     CDiskBlockIndex() : CBlockIndex() {
574         hashPrev = uint256();
575     }
576
577     explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex) {
578         hashPrev = (pprev ? pprev->GetBlockHash() : uint256());
579     }
580
581     ADD_SERIALIZE_METHODS;
582
583     template <typename Stream, typename Operation>
584     inline void SerializationOp(Stream& s, Operation ser_action) {
585         int nVersion = s.GetVersion();
586 #ifdef VERUSHASHDEBUG
587         if (!ser_action.ForRead()) printf("Serializing block index %s, stream version: %x\n", ToString().c_str(), nVersion);
588 #endif
589         if (!(s.GetType() & SER_GETHASH))
590             READWRITE(VARINT(nVersion));
591
592         if (ser_action.ForRead()) {
593             chainPower = CChainPower();
594         }
595         READWRITE(VARINT(chainPower.nHeight));
596         READWRITE(VARINT(nStatus));
597         READWRITE(VARINT(nTx));
598         if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO))
599             READWRITE(VARINT(nFile));
600         if (nStatus & BLOCK_HAVE_DATA)
601             READWRITE(VARINT(nDataPos));
602         if (nStatus & BLOCK_HAVE_UNDO)
603             READWRITE(VARINT(nUndoPos));
604         if (nStatus & BLOCK_ACTIVATES_UPGRADE) {
605             if (ser_action.ForRead()) {
606                 uint32_t branchId;
607                 READWRITE(branchId);
608                 nCachedBranchId = branchId;
609             } else {
610                 // nCachedBranchId must always be set if BLOCK_ACTIVATES_UPGRADE is set.
611                 assert(nCachedBranchId);
612                 uint32_t branchId = *nCachedBranchId;
613                 READWRITE(branchId);
614             }
615         }
616         READWRITE(hashSproutAnchor);
617
618         // block header
619         READWRITE(this->nVersion);
620         READWRITE(hashPrev);
621         READWRITE(hashMerkleRoot);
622         READWRITE(hashFinalSaplingRoot);
623         READWRITE(nTime);
624         READWRITE(nBits);
625         READWRITE(nNonce);
626         READWRITE(nSolution);
627
628         // Only read/write nSproutValue if the client version used to create
629         // this index was storing them.
630         if ((s.GetType() & SER_DISK) && (nVersion >= SPROUT_VALUE_VERSION)) {
631             READWRITE(nSproutValue);
632         }
633
634         // Only read/write nSaplingValue if the client version used to create
635         // this index was storing them.
636         if ((s.GetType() & SER_DISK) && (nVersion >= SAPLING_VALUE_VERSION)) {
637             READWRITE(nSaplingValue);
638         }
639
640         // If you have just added new serialized fields above, remember to add
641         // them to CBlockTreeDB::LoadBlockIndexGuts() in txdb.cpp :)
642     }
643
644     uint256 GetBlockHash() const
645     {
646         CBlockHeader block;
647         block.nVersion        = nVersion;
648         block.hashPrevBlock   = hashPrev;
649         block.hashMerkleRoot  = hashMerkleRoot;
650         block.hashFinalSaplingRoot    = hashFinalSaplingRoot;
651         block.nTime           = nTime;
652         block.nBits           = nBits;
653         block.nNonce          = nNonce;
654         block.nSolution       = nSolution;
655         return block.GetHash();
656     }
657
658
659     std::string ToString() const
660     {
661         std::string str = "CDiskBlockIndex(";
662         str += strprintf("nVersion=%x, pprev=%p, nHeight=%d, merkle=%s\nhashBlock=%s, hashPrev=%s)\n",
663             this->nVersion, pprev, this->chainPower.nHeight, hashMerkleRoot.ToString(), GetBlockHash().ToString(), hashPrev.ToString());
664         return str;
665     }
666 };
667
668 class CChain;
669 typedef CMerkleMountainRange<ChainMMRNode, CChunkedLayer<ChainMMRNode, 9>, COverlayNodeLayer<ChainMMRNode, CChain>> ChainMerkleMountainRange;
670 typedef CMerkleMountainView<ChainMMRNode, CChunkedLayer<ChainMMRNode, 9>, COverlayNodeLayer<ChainMMRNode, CChain>> ChainMerkleMountainView;
671
672 /** An in-memory indexed chain of blocks. 
673  * With Verus and PBaaS chains, this also provides a complete Merkle Mountain Range (MMR) for the chain at all times,
674  * enabling proof of any transaction that can be exported and trusted on any chain that has a trusted oracle or other lite proof of this chain.
675 */
676 class CChain {
677 private:
678     std::vector<CBlockIndex*> vChain;
679     ChainMerkleMountainRange mmr;
680     CBlockIndex *lastTip;
681
682 public:
683     CChain() : vChain(), mmr(COverlayNodeLayer<ChainMMRNode, CChain>(*this)) {}
684
685     /** Returns the index entry for the genesis block of this chain, or NULL if none. */
686     CBlockIndex *Genesis() const {
687         return vChain.size() > 0 ? vChain[0] : NULL;
688     }
689
690     /** Returns the index entry for the tip of this chain, or NULL if none. */
691     CBlockIndex *Tip() const {
692         return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL;
693     }
694     
695     /** Returns the last tip of the chain, or NULL if none. */
696     CBlockIndex *LastTip() const {
697         return vChain.size() > 0 ? lastTip : NULL;
698     }
699
700     /** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */
701     CBlockIndex *operator[](int nHeight) const {
702         if (nHeight < 0 || nHeight >= (int)vChain.size())
703             return NULL;
704         return vChain[nHeight];
705     }
706
707     uint256 GetVerusEntropyHash(int forHeight, int *pPOSheight=nullptr, int *pPOWheight=nullptr, int *pALTheight=nullptr) const;
708
709     /** Get the Merkle Mountain Range for this chain. */
710     const ChainMerkleMountainRange &GetMMR()
711     {
712         return mmr;
713     }
714
715     /** Get a Merkle Mountain Range view for this chain. */
716     ChainMerkleMountainView GetMMV()
717     {
718         return ChainMerkleMountainView(mmr, mmr.size());
719     }    
720
721     ChainMMRNode GetMMRNode(int index) const
722     {
723         return vChain[index]->GetBlockMMRNode();
724     }
725
726     bool GetBlockProof(ChainMerkleMountainView &view, CMMRProof &retProof, int index) const;
727     bool GetMerkleProof(ChainMerkleMountainView &view, CMMRProof &retProof, int index) const;
728
729     /** Compare two chains efficiently. */
730     friend bool operator==(const CChain &a, const CChain &b) {
731         return a.vChain.size() == b.vChain.size() &&
732                a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1];
733     }
734
735     /** Efficiently check whether a block is present in this chain. */
736     bool Contains(const CBlockIndex *pindex) const {
737         return !pindex ? false : (*this)[pindex->GetHeight()] == pindex;
738     }
739
740     /** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */
741     CBlockIndex *Next(const CBlockIndex *pindex) const {
742         if (Contains(pindex))
743             return (*this)[pindex->GetHeight() + 1];
744         else
745             return NULL;
746     }
747
748     /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->GetHeight() : -1. */
749     int Height() const {
750         return vChain.size() - 1;
751     }
752
753     uint64_t size()
754     {
755         return vChain.size();
756     }
757
758     /** Set/initialize a chain with a given tip. */
759     void SetTip(CBlockIndex *pindex);
760
761     /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
762     CBlockLocator GetLocator(const CBlockIndex *pindex = NULL) const;
763
764     /** Find the last common block between this chain and a block index entry. */
765     const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
766 };
767
768 CChainPower ExpandCompactPower(uint256 compactPower, uint32_t height = 0);
769
770 #endif // BITCOIN_CHAIN_H
This page took 0.065149 seconds and 4 git commands to generate.