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