]> Git Repo - VerusCoin.git/blame - src/chain.h
Make GetSerializeSize a wrapper on top of CSizeComputer
[VerusCoin.git] / src / chain.h
CommitLineData
e8b5f0d5 1// Copyright (c) 2009-2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
7bec6dd2 3// Distributed under the MIT software license, see the accompanying
e8b5f0d5 4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
84738627
PJ
6#ifndef BITCOIN_CHAIN_H
7#define BITCOIN_CHAIN_H
e8b5f0d5 8
734f85c4 9#include "arith_uint256.h"
d2270111 10#include "primitives/block.h"
e8b5f0d5 11#include "pow.h"
85c579e3 12#include "tinyformat.h"
e8b5f0d5 13#include "uint256.h"
14
15#include <vector>
16
17#include <boost/foreach.hpp>
18
ad6a36ad
JG
19static const int SPROUT_VALUE_VERSION = 1001400;
20
e8b5f0d5 21struct CDiskBlockPos
22{
23 int nFile;
24 unsigned int nPos;
25
26 ADD_SERIALIZE_METHODS;
27
28 template <typename Stream, typename Operation>
29 inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
30 READWRITE(VARINT(nFile));
31 READWRITE(VARINT(nPos));
32 }
33
34 CDiskBlockPos() {
35 SetNull();
36 }
37
38 CDiskBlockPos(int nFileIn, unsigned int nPosIn) {
39 nFile = nFileIn;
40 nPos = nPosIn;
41 }
42
43 friend bool operator==(const CDiskBlockPos &a, const CDiskBlockPos &b) {
44 return (a.nFile == b.nFile && a.nPos == b.nPos);
45 }
46
47 friend bool operator!=(const CDiskBlockPos &a, const CDiskBlockPos &b) {
48 return !(a == b);
49 }
50
51 void SetNull() { nFile = -1; nPos = 0; }
52 bool IsNull() const { return (nFile == -1); }
f5791c6a
WL
53
54 std::string ToString() const
55 {
56 return strprintf("CBlockDiskPos(nFile=%i, nPos=%i)", nFile, nPos);
57 }
58
e8b5f0d5 59};
60
0e2b1ae2 61enum BlockStatus: uint32_t {
2fdc3351 62 //! Unused.
e8b5f0d5 63 BLOCK_VALID_UNKNOWN = 0,
341735eb 64
2fdc3351 65 //! Parsed, version ok, hash satisfies claimed PoW, 1 <= vtx count <= max, timestamp not in future
341735eb
PW
66 BLOCK_VALID_HEADER = 1,
67
2fdc3351
MF
68 //! All parent headers found, difficulty matches, timestamp >= median previous, checkpoint. Implies all parents
69 //! are also at least TREE.
341735eb
PW
70 BLOCK_VALID_TREE = 2,
71
2fdc3351
MF
72 /**
73 * Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids,
74 * sigops, size, merkle root. Implies all parents are at least TREE but not necessarily TRANSACTIONS. When all
75 * parent blocks also have TRANSACTIONS, CBlockIndex::nChainTx will be set.
76 */
341735eb
PW
77 BLOCK_VALID_TRANSACTIONS = 3,
78
b05a89b2 79 //! Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends, BIP30.
2fdc3351 80 //! Implies all parents are also at least CHAIN.
341735eb
PW
81 BLOCK_VALID_CHAIN = 4,
82
2fdc3351 83 //! Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
341735eb
PW
84 BLOCK_VALID_SCRIPTS = 5,
85
2fdc3351 86 //! All validity bits.
e8b5f0d5 87 BLOCK_VALID_MASK = BLOCK_VALID_HEADER | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS |
88 BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS,
89
2fdc3351
MF
90 BLOCK_HAVE_DATA = 8, //! full block available in blk*.dat
91 BLOCK_HAVE_UNDO = 16, //! undo data available in rev*.dat
e8b5f0d5 92 BLOCK_HAVE_MASK = BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO,
93
2fdc3351
MF
94 BLOCK_FAILED_VALID = 32, //! stage after last reached validness failed
95 BLOCK_FAILED_CHILD = 64, //! descends from failed block
e8b5f0d5 96 BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
89f20450 97
9e851450 98 BLOCK_ACTIVATES_UPGRADE = 128, //! block activates a network upgrade
e8b5f0d5 99};
100
9e851450
JG
101//! Short-hand for the highest consensus validity we implement.
102//! Blocks with this validity are assumed to satisfy all consensus rules.
103static const BlockStatus BLOCK_VALID_CONSENSUS = BLOCK_VALID_SCRIPTS;
104
e8b5f0d5 105/** The block chain is a tree shaped structure starting with the
106 * genesis block at the root, with each block potentially having multiple
107 * candidates to be the next block. A blockindex may have multiple pprev pointing
108 * to it, but at most one of them can be part of the currently active branch.
109 */
110class CBlockIndex
111{
112public:
bf7835c2 113 //! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
e8b5f0d5 114 const uint256* phashBlock;
115
2fdc3351 116 //! pointer to the index of the predecessor of this block
e8b5f0d5 117 CBlockIndex* pprev;
118
2fdc3351 119 //! pointer to the index of some further predecessor of this block
e8b5f0d5 120 CBlockIndex* pskip;
121
2fdc3351 122 //! height of the entry in the chain. The genesis block has height 0
e8b5f0d5 123 int nHeight;
124
2fdc3351 125 //! Which # file this block is stored in (blk?????.dat)
e8b5f0d5 126 int nFile;
127
2fdc3351 128 //! Byte offset within blk?????.dat where this block's data is stored
e8b5f0d5 129 unsigned int nDataPos;
130
2fdc3351 131 //! Byte offset within rev?????.dat where this block's undo data is stored
e8b5f0d5 132 unsigned int nUndoPos;
133
2fdc3351 134 //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
734f85c4 135 arith_uint256 nChainWork;
e8b5f0d5 136
2fdc3351
MF
137 //! Number of transactions in this block.
138 //! Note: in a potential headers-first mode, this number cannot be relied upon
e8b5f0d5 139 unsigned int nTx;
140
2fdc3351
MF
141 //! (memory only) Number of transactions in the chain up to and including this block.
142 //! This value will be non-zero only if and only if transactions for this block and all its parents are available.
143 //! Change to 64-bit type when necessary; won't happen before 2030
144 unsigned int nChainTx;
e8b5f0d5 145
2fdc3351 146 //! Verification status of this block. See enum BlockStatus
e8b5f0d5 147 unsigned int nStatus;
148
9e851450 149 //! Branch ID corresponding to the consensus rules used to validate this block.
828940b1 150 //! Only cached if block validity is BLOCK_VALID_CONSENSUS.
9e851450 151 //! Persisted at each activation height, memory-only for intervening blocks.
828940b1 152 boost::optional<uint32_t> nCachedBranchId;
9e851450 153
b6961fc1
JG
154 //! The anchor for the tree state up to the start of this block
155 uint256 hashAnchor;
156
0bc1e2c4
JG
157 //! (memory only) The anchor for the tree state up to the end of this block
158 uint256 hashAnchorEnd;
159
ad6a36ad
JG
160 //! Change in value held by the Sprout circuit over this block.
161 //! Will be boost::none for older blocks on old nodes until a reindex has taken place.
162 boost::optional<CAmount> nSproutValue;
163
164 //! (memory only) Total value held by the Sprout circuit up to and including this block.
165 //! Will be boost::none for on old nodes until a reindex has taken place.
166 //! Will be boost::none if nChainTx is zero.
167 boost::optional<CAmount> nChainSproutValue;
168
2fdc3351 169 //! block header
e8b5f0d5 170 int nVersion;
171 uint256 hashMerkleRoot;
a8d384ae 172 uint256 hashReserved;
e8b5f0d5 173 unsigned int nTime;
174 unsigned int nBits;
fdda3c50 175 uint256 nNonce;
5be6abbf 176 std::vector<unsigned char> nSolution;
e8b5f0d5 177
2fdc3351 178 //! (memory only) Sequential id assigned to distinguish order in which blocks are received.
e8b5f0d5 179 uint32_t nSequenceId;
180
181 void SetNull()
182 {
183 phashBlock = NULL;
184 pprev = NULL;
185 pskip = NULL;
186 nHeight = 0;
187 nFile = 0;
188 nDataPos = 0;
189 nUndoPos = 0;
734f85c4 190 nChainWork = arith_uint256();
e8b5f0d5 191 nTx = 0;
192 nChainTx = 0;
193 nStatus = 0;
828940b1 194 nCachedBranchId = boost::none;
b6961fc1 195 hashAnchor = uint256();
0bc1e2c4 196 hashAnchorEnd = uint256();
e8b5f0d5 197 nSequenceId = 0;
ad6a36ad
JG
198 nSproutValue = boost::none;
199 nChainSproutValue = boost::none;
e8b5f0d5 200
201 nVersion = 0;
4f152496 202 hashMerkleRoot = uint256();
a8d384ae 203 hashReserved = uint256();
e8b5f0d5 204 nTime = 0;
205 nBits = 0;
fdda3c50
JG
206 nNonce = uint256();
207 nSolution.clear();
e8b5f0d5 208 }
209
210 CBlockIndex()
211 {
212 SetNull();
213 }
214
341735eb 215 CBlockIndex(const CBlockHeader& block)
e8b5f0d5 216 {
217 SetNull();
218
219 nVersion = block.nVersion;
220 hashMerkleRoot = block.hashMerkleRoot;
a8d384ae 221 hashReserved = block.hashReserved;
e8b5f0d5 222 nTime = block.nTime;
223 nBits = block.nBits;
224 nNonce = block.nNonce;
fdda3c50 225 nSolution = block.nSolution;
e8b5f0d5 226 }
227
228 CDiskBlockPos GetBlockPos() const {
229 CDiskBlockPos ret;
230 if (nStatus & BLOCK_HAVE_DATA) {
231 ret.nFile = nFile;
232 ret.nPos = nDataPos;
233 }
234 return ret;
235 }
236
237 CDiskBlockPos GetUndoPos() const {
238 CDiskBlockPos ret;
239 if (nStatus & BLOCK_HAVE_UNDO) {
240 ret.nFile = nFile;
241 ret.nPos = nUndoPos;
242 }
243 return ret;
244 }
245
246 CBlockHeader GetBlockHeader() const
247 {
248 CBlockHeader block;
249 block.nVersion = nVersion;
250 if (pprev)
251 block.hashPrevBlock = pprev->GetBlockHash();
252 block.hashMerkleRoot = hashMerkleRoot;
a8d384ae 253 block.hashReserved = hashReserved;
e8b5f0d5 254 block.nTime = nTime;
255 block.nBits = nBits;
256 block.nNonce = nNonce;
fdda3c50 257 block.nSolution = nSolution;
e8b5f0d5 258 return block;
259 }
260
261 uint256 GetBlockHash() const
262 {
263 return *phashBlock;
264 }
265
266 int64_t GetBlockTime() const
267 {
268 return (int64_t)nTime;
269 }
270
e8b5f0d5 271 enum { nMedianTimeSpan=11 };
272
273 int64_t GetMedianTimePast() const
274 {
275 int64_t pmedian[nMedianTimeSpan];
276 int64_t* pbegin = &pmedian[nMedianTimeSpan];
277 int64_t* pend = &pmedian[nMedianTimeSpan];
278
279 const CBlockIndex* pindex = this;
280 for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
281 *(--pbegin) = pindex->GetBlockTime();
282
283 std::sort(pbegin, pend);
284 return pbegin[(pend - pbegin)/2];
285 }
286
e8b5f0d5 287 std::string ToString() const
288 {
289 return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
290 pprev, nHeight,
291 hashMerkleRoot.ToString(),
292 GetBlockHash().ToString());
293 }
294
2fdc3351 295 //! Check whether this block index entry is valid up to the passed validity level.
e8b5f0d5 296 bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const
297 {
298 assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
299 if (nStatus & BLOCK_FAILED_MASK)
300 return false;
301 return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
302 }
303
2fdc3351
MF
304 //! Raise the validity level of this block index entry.
305 //! Returns true if the validity was changed.
e8b5f0d5 306 bool RaiseValidity(enum BlockStatus nUpTo)
307 {
308 assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
309 if (nStatus & BLOCK_FAILED_MASK)
310 return false;
311 if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {
312 nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
313 return true;
314 }
315 return false;
316 }
317
2fdc3351 318 //! Build the skiplist pointer for this entry.
e8b5f0d5 319 void BuildSkip();
320
2fdc3351 321 //! Efficiently find an ancestor of this block.
e8b5f0d5 322 CBlockIndex* GetAncestor(int height);
323 const CBlockIndex* GetAncestor(int height) const;
324};
325
326/** Used to marshal pointers into hashes for db storage. */
327class CDiskBlockIndex : public CBlockIndex
328{
329public:
330 uint256 hashPrev;
331
332 CDiskBlockIndex() {
4f152496 333 hashPrev = uint256();
e8b5f0d5 334 }
335
63d1ae55 336 explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex) {
4f152496 337 hashPrev = (pprev ? pprev->GetBlockHash() : uint256());
e8b5f0d5 338 }
339
340 ADD_SERIALIZE_METHODS;
341
342 template <typename Stream, typename Operation>
343 inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
344 if (!(nType & SER_GETHASH))
345 READWRITE(VARINT(nVersion));
346
347 READWRITE(VARINT(nHeight));
348 READWRITE(VARINT(nStatus));
349 READWRITE(VARINT(nTx));
350 if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO))
351 READWRITE(VARINT(nFile));
352 if (nStatus & BLOCK_HAVE_DATA)
353 READWRITE(VARINT(nDataPos));
354 if (nStatus & BLOCK_HAVE_UNDO)
355 READWRITE(VARINT(nUndoPos));
828940b1
JG
356 if (nStatus & BLOCK_ACTIVATES_UPGRADE) {
357 if (ser_action.ForRead()) {
358 uint32_t branchId;
359 READWRITE(branchId);
360 nCachedBranchId = branchId;
361 } else {
362 // nCachedBranchId must always be set if BLOCK_ACTIVATES_UPGRADE is set.
363 assert(nCachedBranchId);
364 uint32_t branchId = *nCachedBranchId;
365 READWRITE(branchId);
366 }
367 }
b6961fc1 368 READWRITE(hashAnchor);
e8b5f0d5 369
370 // block header
371 READWRITE(this->nVersion);
372 READWRITE(hashPrev);
373 READWRITE(hashMerkleRoot);
a8d384ae 374 READWRITE(hashReserved);
e8b5f0d5 375 READWRITE(nTime);
376 READWRITE(nBits);
377 READWRITE(nNonce);
fdda3c50 378 READWRITE(nSolution);
ad6a36ad
JG
379
380 // Only read/write nSproutValue if the client version used to create
381 // this index was storing them.
9d0c70e9 382 if ((nType & SER_DISK) && (nVersion >= SPROUT_VALUE_VERSION)) {
ad6a36ad
JG
383 READWRITE(nSproutValue);
384 }
e8b5f0d5 385 }
386
387 uint256 GetBlockHash() const
388 {
389 CBlockHeader block;
390 block.nVersion = nVersion;
391 block.hashPrevBlock = hashPrev;
392 block.hashMerkleRoot = hashMerkleRoot;
a8d384ae 393 block.hashReserved = hashReserved;
e8b5f0d5 394 block.nTime = nTime;
395 block.nBits = nBits;
396 block.nNonce = nNonce;
fdda3c50 397 block.nSolution = nSolution;
e8b5f0d5 398 return block.GetHash();
399 }
400
401
402 std::string ToString() const
403 {
404 std::string str = "CDiskBlockIndex(";
405 str += CBlockIndex::ToString();
406 str += strprintf("\n hashBlock=%s, hashPrev=%s)",
407 GetBlockHash().ToString(),
408 hashPrev.ToString());
409 return str;
410 }
411};
412
413/** An in-memory indexed chain of blocks. */
414class CChain {
415private:
416 std::vector<CBlockIndex*> vChain;
417
418public:
419 /** Returns the index entry for the genesis block of this chain, or NULL if none. */
420 CBlockIndex *Genesis() const {
421 return vChain.size() > 0 ? vChain[0] : NULL;
422 }
423
424 /** Returns the index entry for the tip of this chain, or NULL if none. */
425 CBlockIndex *Tip() const {
426 return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL;
427 }
428
429 /** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */
430 CBlockIndex *operator[](int nHeight) const {
431 if (nHeight < 0 || nHeight >= (int)vChain.size())
432 return NULL;
433 return vChain[nHeight];
434 }
435
436 /** Compare two chains efficiently. */
437 friend bool operator==(const CChain &a, const CChain &b) {
438 return a.vChain.size() == b.vChain.size() &&
439 a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1];
440 }
441
442 /** Efficiently check whether a block is present in this chain. */
443 bool Contains(const CBlockIndex *pindex) const {
444 return (*this)[pindex->nHeight] == pindex;
445 }
446
447 /** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */
448 CBlockIndex *Next(const CBlockIndex *pindex) const {
449 if (Contains(pindex))
450 return (*this)[pindex->nHeight + 1];
451 else
452 return NULL;
453 }
454
455 /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
456 int Height() const {
457 return vChain.size() - 1;
458 }
459
b7ae2c17 460 /** Set/initialize a chain with a given tip. */
461 void SetTip(CBlockIndex *pindex);
e8b5f0d5 462
463 /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
464 CBlockLocator GetLocator(const CBlockIndex *pindex = NULL) const;
465
466 /** Find the last common block between this chain and a block index entry. */
467 const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
468};
469
84738627 470#endif // BITCOIN_CHAIN_H
This page took 0.165196 seconds and 4 git commands to generate.