]> Git Repo - VerusCoin.git/blame - src/chain.h
Move CBlockIndex, CChain and related code out of main
[VerusCoin.git] / src / chain.h
CommitLineData
e8b5f0d5 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
17struct 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
51enum 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 */
75class CBlockIndex
76{
77public:
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. */
270class CDiskBlockIndex : public CBlockIndex
271{
272public:
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. */
334class CChain {
335private:
336 std::vector<CBlockIndex*> vChain;
337
338public:
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.057412 seconds and 4 git commands to generate.