Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin developers
3 : // Copyright (c) 2011-2013 The PPCoin developers
4 : // Copyright (c) 2013-2014 The NovaCoin Developers
5 : // Copyright (c) 2014-2018 The BlackCoin Developers
6 : // Copyright (c) 2015-2021 The PIVX Core developers
7 : // Distributed under the MIT software license, see the accompanying
8 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
9 :
10 : #ifndef PIVX_CHAIN_H
11 : #define PIVX_CHAIN_H
12 :
13 : #include "chainparams.h"
14 : #include "flatfile.h"
15 : #include "optional.h"
16 : #include "primitives/block.h"
17 : #include "timedata.h"
18 : #include "tinyformat.h"
19 : #include "uint256.h"
20 : #include "util/system.h"
21 : #include "libzerocoin/Denominations.h"
22 :
23 : #include <vector>
24 :
25 : /**
26 : * Timestamp window used as a grace period by code that compares external
27 : * timestamps (such as timestamps passed to RPCs, or wallet key creation times)
28 : * to block timestamps.
29 : */
30 : static constexpr int64_t TIMESTAMP_WINDOW = 2 * 60 * 60;
31 :
32 : class CBlockFileInfo
33 : {
34 : public:
35 : unsigned int nBlocks; //!< number of blocks stored in file
36 : unsigned int nSize; //!< number of used bytes of block file
37 : unsigned int nUndoSize; //!< number of used bytes in the undo file
38 : unsigned int nHeightFirst; //!< lowest height of block in file
39 : unsigned int nHeightLast; //!< highest height of block in file
40 : uint64_t nTimeFirst; //!< earliest time of block in file
41 : uint64_t nTimeLast; //!< latest time of block in file
42 :
43 1521 : SERIALIZE_METHODS(CBlockFileInfo, obj)
44 : {
45 488 : READWRITE(VARINT(obj.nBlocks));
46 488 : READWRITE(VARINT(obj.nSize));
47 488 : READWRITE(VARINT(obj.nUndoSize));
48 488 : READWRITE(VARINT(obj.nHeightFirst));
49 488 : READWRITE(VARINT(obj.nHeightLast));
50 488 : READWRITE(VARINT(obj.nTimeFirst));
51 488 : READWRITE(VARINT(obj.nTimeLast));
52 488 : }
53 :
54 828 : void SetNull()
55 : {
56 828 : nBlocks = 0;
57 828 : nSize = 0;
58 828 : nUndoSize = 0;
59 828 : nHeightFirst = 0;
60 828 : nHeightLast = 0;
61 828 : nTimeFirst = 0;
62 828 : nTimeLast = 0;
63 : }
64 :
65 828 : CBlockFileInfo()
66 828 : {
67 828 : SetNull();
68 : }
69 :
70 : std::string ToString() const;
71 :
72 : /** update statistics (does not update nSize) */
73 41476 : void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn)
74 : {
75 41476 : if (nBlocks == 0 || nHeightFirst > nHeightIn)
76 317 : nHeightFirst = nHeightIn;
77 41476 : if (nBlocks == 0 || nTimeFirst > nTimeIn)
78 317 : nTimeFirst = nTimeIn;
79 41476 : nBlocks++;
80 41476 : if (nHeightIn > nHeightLast)
81 40931 : nHeightLast = nHeightIn;
82 41476 : if (nTimeIn > nTimeLast)
83 17145 : nTimeLast = nTimeIn;
84 : }
85 : };
86 :
87 : enum BlockStatus {
88 : //! Unused.
89 : BLOCK_VALID_UNKNOWN = 0,
90 :
91 : //! Parsed, version ok, hash satisfies claimed PoW, 1 <= vtx count <= max, timestamp not in future
92 : BLOCK_VALID_HEADER = 1,
93 :
94 : //! All parent headers found, difficulty matches, timestamp >= median previous, checkpoint. Implies all parents
95 : //! are also at least TREE.
96 : BLOCK_VALID_TREE = 2,
97 :
98 : /**
99 : * Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids,
100 : * sigops, size, merkle root. Implies all parents are at least TREE but not necessarily TRANSACTIONS. When all
101 : * parent blocks also have TRANSACTIONS, CBlockIndex::nChainTx will be set.
102 : */
103 : BLOCK_VALID_TRANSACTIONS = 3,
104 :
105 : //! Outputs do not overspend inputs, no double spends, coinbase output ok, immature coinbase spends.
106 : //! Implies all parents are also at least CHAIN.
107 : BLOCK_VALID_CHAIN = 4,
108 :
109 : //! Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
110 : BLOCK_VALID_SCRIPTS = 5,
111 :
112 : //! All validity bits.
113 : BLOCK_VALID_MASK = BLOCK_VALID_HEADER | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS |
114 : BLOCK_VALID_CHAIN |
115 : BLOCK_VALID_SCRIPTS,
116 :
117 : BLOCK_HAVE_DATA = 8, //! full block available in blk*.dat
118 : BLOCK_HAVE_UNDO = 16, //! undo data available in rev*.dat
119 : BLOCK_HAVE_MASK = BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO,
120 :
121 : BLOCK_FAILED_VALID = 32, //! stage after last reached validness failed
122 : BLOCK_FAILED_CHILD = 64, //! descends from failed block
123 : BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
124 : };
125 :
126 : // BlockIndex flags
127 : enum {
128 : BLOCK_PROOF_OF_STAKE = (1 << 0), // is proof-of-stake block
129 : BLOCK_STAKE_ENTROPY = (1 << 1), // entropy bit for stake modifier
130 : BLOCK_STAKE_MODIFIER = (1 << 2), // regenerated stake modifier
131 : };
132 :
133 : /** The block chain is a tree shaped structure starting with the
134 : * genesis block at the root, with each block potentially having multiple
135 : * candidates to be the next block. A blockindex may have multiple pprev pointing
136 : * to it, but at most one of them can be part of the currently active branch.
137 : */
138 857497 : class CBlockIndex
139 : {
140 : public:
141 : //! pointer to the hash of the block, if any. memory is owned by this CBlockIndex
142 : const uint256* phashBlock{nullptr};
143 :
144 : //! pointer to the index of the predecessor of this block
145 : CBlockIndex* pprev{nullptr};
146 :
147 : //! pointer to the index of some further predecessor of this block
148 : CBlockIndex* pskip{nullptr};
149 :
150 : //! height of the entry in the chain. The genesis block has height 0
151 : int nHeight{0};
152 :
153 : //! Which # file this block is stored in (blk?????.dat)
154 : int nFile{0};
155 :
156 : //! Byte offset within blk?????.dat where this block's data is stored
157 : unsigned int nDataPos{0};
158 :
159 : //! Byte offset within rev?????.dat where this block's undo data is stored
160 : unsigned int nUndoPos{0};
161 :
162 : //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
163 : arith_uint256 nChainWork{};
164 :
165 : //! Number of transactions in this block.
166 : //! Note: in a potential headers-first mode, this number cannot be relied upon
167 : unsigned int nTx{0};
168 :
169 : //! (memory only) Number of transactions in the chain up to and including this block.
170 : //! This value will be non-zero only if and only if transactions for this block and all its parents are available.
171 : //! Change to 64-bit type when necessary; won't happen before 2030
172 : unsigned int nChainTx{0};
173 :
174 : //! Verification status of this block. See enum BlockStatus
175 : uint32_t nStatus{0};
176 :
177 : // proof-of-stake specific fields
178 : // char vector holding the stake modifier bytes. It is empty for PoW blocks.
179 : // Modifier V1 is 64 bit while modifier V2 is 256 bit.
180 : std::vector<unsigned char> vStakeModifier{};
181 : unsigned int nFlags{0};
182 :
183 : //! Change in value held by the Sapling circuit over this block.
184 : //! Not a Optional because this was added before Sapling activated, so we can
185 : //! rely on the invariant that every block before this was added had nSaplingValue = 0.
186 : CAmount nSaplingValue{0};
187 :
188 : //! (memory only) Total value held by the Sapling circuit up to and including this block.
189 : //! Will be nullopt if nChainTx is zero.
190 : Optional<CAmount> nChainSaplingValue{nullopt};
191 :
192 : //! block header
193 : int32_t nVersion{0};
194 : uint256 hashMerkleRoot{};
195 : uint256 hashFinalSaplingRoot{};
196 : uint32_t nTime{0};
197 : uint32_t nBits{0};
198 : uint32_t nNonce{0};
199 : uint256 nAccumulatorCheckpoint{};
200 :
201 : //! (memory only) Sequential id assigned to distinguish order in which blocks are received.
202 : uint32_t nSequenceId{0};
203 :
204 : //! (memory only) Maximum nTime in the chain upto and including this block.
205 : unsigned int nTimeMax{0};
206 :
207 2462892 : CBlockIndex() {}
208 : explicit CBlockIndex(const CBlock& block);
209 :
210 : std::string ToString() const;
211 :
212 : FlatFilePos GetBlockPos() const;
213 : FlatFilePos GetUndoPos() const;
214 : CBlockHeader GetBlockHeader() const;
215 5829242 : uint256 GetBlockHash() const { return *phashBlock; }
216 5735697 : int64_t GetBlockTime() const { return (int64_t)nTime; }
217 168682 : int64_t GetBlockTimeMax() const { return (int64_t)nTimeMax; }
218 :
219 : int64_t GetMedianTimePast() const;
220 :
221 : int64_t MaxFutureBlockTime() const;
222 : int64_t MinPastBlockTime() const;
223 :
224 1388534 : bool IsProofOfStake() const { return (nFlags & BLOCK_PROOF_OF_STAKE); }
225 : bool IsProofOfWork() const { return !IsProofOfStake(); }
226 15295 : void SetProofOfStake() { nFlags |= BLOCK_PROOF_OF_STAKE; }
227 :
228 : // Stake Modifier
229 : unsigned int GetStakeEntropyBit() const;
230 : bool SetStakeEntropyBit(unsigned int nEntropyBit);
231 2005606 : bool GeneratedStakeModifier() const { return (nFlags & BLOCK_STAKE_MODIFIER); }
232 : void SetStakeModifier(const uint64_t nStakeModifier, bool fGeneratedStakeModifier);
233 : void SetNewStakeModifier(); // generates and sets new v1 modifier
234 : void SetStakeModifier(const uint256& nStakeModifier);
235 : void SetNewStakeModifier(const uint256& prevoutId); // generates and sets new v2 modifier
236 : uint64_t GetStakeModifierV1() const;
237 : uint256 GetStakeModifierV2() const;
238 :
239 : // Update Sapling chain value
240 : void SetChainSaplingValue();
241 :
242 : //! Check whether this block index entry is valid up to the passed validity level.
243 : bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const;
244 : //! Raise the validity level of this block index entry.
245 : //! Returns true if the validity was changed.
246 : bool RaiseValidity(enum BlockStatus nUpTo);
247 : //! Build the skiplist pointer for this entry.
248 : void BuildSkip();
249 : //! Efficiently find an ancestor of this block.
250 : CBlockIndex* GetAncestor(int height);
251 : const CBlockIndex* GetAncestor(int height) const;
252 : };
253 :
254 : /** Find the forking point between two chain tips. */
255 : const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb);
256 :
257 : /** Used to marshal pointers into hashes for db storage. */
258 :
259 : // New serialization introduced with 4.0.99
260 : static const int DBI_OLD_SER_VERSION = 4009900;
261 : static const int DBI_SER_VERSION_NO_ZC = 4009902; // removes mapZerocoinSupply, nMoneySupply
262 :
263 143725 : class CDiskBlockIndex : public CBlockIndex
264 : {
265 : public:
266 : uint256 hashPrev;
267 :
268 32806 : CDiskBlockIndex()
269 32806 : {
270 32806 : hashPrev = UINT256_ZERO;
271 32806 : }
272 :
273 39236 : explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex)
274 : {
275 39236 : hashPrev = (pprev ? pprev->GetBlockHash() : UINT256_ZERO);
276 39236 : }
277 :
278 144084 : SERIALIZE_METHODS(CDiskBlockIndex, obj)
279 : {
280 72042 : int nSerVersion = s.GetVersion();
281 72042 : if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT_MODE(nSerVersion, VarIntMode::NONNEGATIVE_SIGNED));
282 :
283 72042 : READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));
284 72042 : READWRITE(VARINT(obj.nStatus));
285 72042 : READWRITE(VARINT(obj.nTx));
286 72042 : if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));
287 72042 : if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos));
288 72042 : if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos));
289 :
290 72042 : if (nSerVersion >= DBI_SER_VERSION_NO_ZC) {
291 : // Serialization with CLIENT_VERSION = 4009902+
292 72042 : READWRITE(obj.nFlags);
293 72042 : READWRITE(obj.nVersion);
294 72042 : READWRITE(obj.vStakeModifier);
295 72042 : READWRITE(obj.hashPrev);
296 72042 : READWRITE(obj.hashMerkleRoot);
297 72042 : READWRITE(obj.nTime);
298 72042 : READWRITE(obj.nBits);
299 72042 : READWRITE(obj.nNonce);
300 72042 : if(obj.nVersion > 3 && obj.nVersion < 7)
301 10786 : READWRITE(obj.nAccumulatorCheckpoint);
302 :
303 : // Sapling blocks
304 72042 : if (obj.nVersion >= 8) {
305 21365 : READWRITE(obj.hashFinalSaplingRoot);
306 21365 : READWRITE(obj.nSaplingValue);
307 : }
308 0 : } else if (nSerVersion > DBI_OLD_SER_VERSION && ser_action.ForRead()) {
309 : // Serialization with CLIENT_VERSION = 4009901
310 0 : std::map<libzerocoin::CoinDenomination, int64_t> mapZerocoinSupply;
311 0 : int64_t nMoneySupply = 0;
312 0 : READWRITE(nMoneySupply);
313 0 : READWRITE(obj.nFlags);
314 0 : READWRITE(obj.nVersion);
315 0 : READWRITE(obj.vStakeModifier);
316 0 : READWRITE(obj.hashPrev);
317 0 : READWRITE(obj.hashMerkleRoot);
318 0 : READWRITE(obj.nTime);
319 0 : READWRITE(obj.nBits);
320 0 : READWRITE(obj.nNonce);
321 0 : if (obj.nVersion > 3) {
322 0 : READWRITE(mapZerocoinSupply);
323 0 : if (obj.nVersion < 7) READWRITE(obj.nAccumulatorCheckpoint);
324 : }
325 : } else if (ser_action.ForRead()) {
326 : // Serialization with CLIENT_VERSION = 4009900-
327 0 : int64_t nMint = 0;
328 0 : uint256 hashNext{};
329 0 : int64_t nMoneySupply = 0;
330 0 : READWRITE(nMint);
331 0 : READWRITE(nMoneySupply);
332 0 : READWRITE(obj.nFlags);
333 0 : if (!Params().GetConsensus().NetworkUpgradeActive(obj.nHeight, Consensus::UPGRADE_V3_4)) {
334 0 : uint64_t nStakeModifier = 0;
335 0 : READWRITE(nStakeModifier);
336 0 : SER_READ(obj, obj.SetStakeModifier(nStakeModifier, obj.GeneratedStakeModifier()));
337 : } else {
338 0 : uint256 nStakeModifierV2;
339 0 : READWRITE(nStakeModifierV2);
340 0 : SER_READ(obj, obj.SetStakeModifier(nStakeModifierV2));
341 : }
342 0 : if (obj.IsProofOfStake()) {
343 0 : COutPoint prevoutStake;
344 0 : unsigned int nStakeTime = 0;
345 0 : READWRITE(prevoutStake);
346 0 : READWRITE(nStakeTime);
347 : }
348 0 : READWRITE(obj.nVersion);
349 0 : READWRITE(obj.hashPrev);
350 0 : READWRITE(hashNext);
351 0 : READWRITE(obj.hashMerkleRoot);
352 0 : READWRITE(obj.nTime);
353 0 : READWRITE(obj.nBits);
354 0 : READWRITE(obj.nNonce);
355 0 : if (obj.nVersion > 3) {
356 0 : std::map<libzerocoin::CoinDenomination, int64_t> mapZerocoinSupply;
357 0 : std::vector<libzerocoin::CoinDenomination> vMintDenominationsInBlock;
358 0 : READWRITE(obj.nAccumulatorCheckpoint);
359 0 : READWRITE(mapZerocoinSupply);
360 0 : READWRITE(vMintDenominationsInBlock);
361 : }
362 : }
363 72042 : }
364 :
365 32806 : uint256 GetBlockHash() const
366 : {
367 32806 : CBlockHeader block;
368 32806 : block.nVersion = nVersion;
369 32806 : block.hashPrevBlock = hashPrev;
370 32806 : block.hashMerkleRoot = hashMerkleRoot;
371 32806 : block.nTime = nTime;
372 32806 : block.nBits = nBits;
373 32806 : block.nNonce = nNonce;
374 32806 : if (nVersion > 3 && nVersion < 7)
375 8008 : block.nAccumulatorCheckpoint = nAccumulatorCheckpoint;
376 32806 : if (nVersion >= 8)
377 1699 : block.hashFinalSaplingRoot = hashFinalSaplingRoot;
378 32806 : return block.GetHash();
379 : }
380 :
381 :
382 : std::string ToString() const
383 : {
384 : return strprintf("CDiskBlockIndex(%s\n hashBlock=%s, hashPrev=%s)",
385 : CBlockIndex::ToString(),
386 : GetBlockHash().ToString(),
387 : hashPrev.ToString());
388 : }
389 : };
390 :
391 : /** An in-memory indexed chain of blocks. */
392 6 : class CChain
393 : {
394 : private:
395 : std::vector<CBlockIndex*> vChain;
396 :
397 : public:
398 : /** Returns the index entry for the genesis block of this chain, or nullptr if none. */
399 124786 : CBlockIndex* Genesis() const
400 : {
401 124786 : return vChain.size() > 0 ? vChain[0] : nullptr;
402 : }
403 :
404 : /** Returns the index entry for the tip of this chain, or nullptr if none. */
405 34160650 : CBlockIndex* Tip(bool fProofOfStake = false) const
406 : {
407 34160650 : if (vChain.size() < 1)
408 : return nullptr;
409 :
410 34074270 : CBlockIndex* pindex = vChain[vChain.size() - 1];
411 :
412 34074270 : if (fProofOfStake) {
413 : while (pindex && pindex->pprev && !pindex->IsProofOfStake())
414 : pindex = pindex->pprev;
415 : }
416 : return pindex;
417 : }
418 :
419 : /** Returns the index entry at a particular height in this chain, or nullptr if no such height exists. */
420 400475 : CBlockIndex* operator[](int nHeight) const
421 : {
422 400475 : if (nHeight < 0 || nHeight >= (int)vChain.size())
423 : return nullptr;
424 356557 : return vChain[nHeight];
425 : }
426 :
427 : /** Compare two chains efficiently. */
428 : friend bool operator==(const CChain& a, const CChain& b)
429 : {
430 : return a.vChain.size() == b.vChain.size() &&
431 : a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1];
432 : }
433 :
434 : /** Efficiently check whether a block is present in this chain. */
435 303470 : bool Contains(const CBlockIndex* pindex) const
436 : {
437 542148 : return (*this)[pindex->nHeight] == pindex;
438 : }
439 :
440 : /** Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip. */
441 32396 : CBlockIndex* Next(const CBlockIndex* pindex) const
442 : {
443 64792 : if (Contains(pindex))
444 32396 : return (*this)[pindex->nHeight + 1];
445 : else
446 : return nullptr;
447 : }
448 :
449 : /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
450 2201705 : int Height() const
451 : {
452 2156916 : return vChain.size() - 1;
453 : }
454 :
455 : /** Set/initialize a chain with a given tip. */
456 : void SetTip(CBlockIndex* pindex);
457 :
458 : /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
459 : CBlockLocator GetLocator(const CBlockIndex* pindex = nullptr) const;
460 :
461 : /** Find the last common block between this chain and a block index entry. */
462 : const CBlockIndex* FindFork(const CBlockIndex* pindex) const;
463 :
464 : /** Find the earliest block with timestamp equal or greater than the given. */
465 : CBlockIndex* FindEarliestAtLeast(int64_t nTime) const;
466 : };
467 :
468 : #endif // PIVX_CHAIN_H
|