PIVX Core  5.6.99
P2P Digital Currency
chain.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin developers
3 // Copyright (c) 2016-2021 The PIVX Core developers
4 // Distributed under the MIT software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include "chain.h"
8 #include "legacy/stakemodifier.h" // for ComputeNextStakeModifier
9 
10 
15 {
16  if (pindex == nullptr) {
17  vChain.clear();
18  return;
19  }
20  vChain.resize(pindex->nHeight + 1);
21  while (pindex && vChain[pindex->nHeight] != pindex) {
22  vChain[pindex->nHeight] = pindex;
23  pindex = pindex->pprev;
24  }
25 }
26 
28 {
29  int nStep = 1;
30  std::vector<uint256> vHave;
31  vHave.reserve(32);
32 
33  if (!pindex)
34  pindex = Tip();
35  while (pindex) {
36  vHave.push_back(pindex->GetBlockHash());
37  // Stop when we have added the genesis block.
38  if (pindex->nHeight == 0)
39  break;
40  // Exponentially larger steps back, plus the genesis block.
41  int nHeight = std::max(pindex->nHeight - nStep, 0);
42  if (Contains(pindex)) {
43  // Use O(1) CChain index if possible.
44  pindex = (*this)[nHeight];
45  } else {
46  // Otherwise, use O(log n) skiplist.
47  pindex = pindex->GetAncestor(nHeight);
48  }
49  if (vHave.size() > 10)
50  nStep *= 2;
51  }
52 
53  return CBlockLocator(vHave);
54 }
55 
56 const CBlockIndex* CChain::FindFork(const CBlockIndex* pindex) const
57 {
58  if (pindex == nullptr)
59  return nullptr;
60  if (pindex->nHeight > Height())
61  pindex = pindex->GetAncestor(Height());
62  while (pindex && !Contains(pindex))
63  pindex = pindex->pprev;
64  return pindex;
65 }
66 
68 {
69  std::vector<CBlockIndex*>::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), nTime,
70  [](CBlockIndex* pBlock, const int64_t& time) -> bool { return pBlock->GetBlockTimeMax() < time; });
71  return (lower == vChain.end() ? nullptr : *lower);
72 }
73 
75 int static inline InvertLowestOne(int n) { return n & (n - 1); }
76 
78 int static inline GetSkipHeight(int height)
79 {
80  if (height < 2)
81  return 0;
82  // Determine which height to jump back to. Any number strictly lower than height is acceptable,
83  // but the following expression seems to perform well in simulations (max 110 steps to go back
84  // up to 2**18 blocks).
85  return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height);
86 }
87 
88 const CBlockIndex* CBlockIndex::GetAncestor(int height) const
89 {
90  if (height > nHeight || height < 0) {
91  return nullptr;
92  }
93 
94  const CBlockIndex* pindexWalk = this;
95  int heightWalk = nHeight;
96  while (heightWalk > height) {
97  int heightSkip = GetSkipHeight(heightWalk);
98  int heightSkipPrev = GetSkipHeight(heightWalk - 1);
99  if (heightSkip == height ||
100  (heightSkip > height && !(heightSkipPrev < heightSkip - 2 && heightSkipPrev >= height))) {
101  // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
102  pindexWalk = pindexWalk->pskip;
103  heightWalk = heightSkip;
104  } else {
105  assert(pindexWalk->pprev);
106  pindexWalk = pindexWalk->pprev;
107  heightWalk--;
108  }
109  }
110  return pindexWalk;
111 }
112 
114 {
115  return const_cast<CBlockIndex*>(static_cast<const CBlockIndex*>(this)->GetAncestor(height));
116 }
117 
119 {
120  if (pprev)
121  pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
122 }
123 
125  nVersion{block.nVersion},
126  hashMerkleRoot{block.hashMerkleRoot},
127  hashFinalSaplingRoot(block.hashFinalSaplingRoot),
128  nTime{block.nTime},
129  nBits{block.nBits},
130  nNonce{block.nNonce}
131 {
132  if(block.nVersion > 3 && block.nVersion < 7)
134  if (block.IsProofOfStake())
135  SetProofOfStake();
136 }
137 
138 std::string CBlockIndex::ToString() const
139 {
140  return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
141  pprev, nHeight,
143  GetBlockHash().ToString());
144 }
145 
147 {
148  FlatFilePos ret;
149  if (nStatus & BLOCK_HAVE_DATA) {
150  ret.nFile = nFile;
151  ret.nPos = nDataPos;
152  }
153  return ret;
154 }
155 
157 {
158  FlatFilePos ret;
159  if (nStatus & BLOCK_HAVE_UNDO) {
160  ret.nFile = nFile;
161  ret.nPos = nUndoPos;
162  }
163  return ret;
164 }
165 
167 {
168  CBlockHeader block;
169  block.nVersion = nVersion;
170  if (pprev) block.hashPrevBlock = pprev->GetBlockHash();
172  block.nTime = nTime;
173  block.nBits = nBits;
174  block.nNonce = nNonce;
177  return block;
178 }
179 
181 {
183 }
184 
186 {
187  const Consensus::Params& consensus = Params().GetConsensus();
188  // Time Protocol v1: pindexPrev->MedianTimePast + 1
189  if (!consensus.IsTimeProtocolV2(nHeight+1))
190  return GetMedianTimePast();
191 
192  // on the transition from Time Protocol v1 to v2
193  // pindexPrev->nTime might be in the future (up to the allowed drift)
194  // so we allow the nBlockTimeProtocolV2 (PIVX v4.0) to be at most (180-14) seconds earlier than previous block
196  return GetBlockTime() - consensus.FutureBlockTimeDrift(nHeight) + consensus.FutureBlockTimeDrift(nHeight + 1);
197 
198  // Time Protocol v2: pindexPrev->nTime
199  return GetBlockTime();
200 }
201 
202 enum { nMedianTimeSpan = 11 };
203 
205 {
206  int64_t pmedian[nMedianTimeSpan];
207  int64_t* pbegin = &pmedian[nMedianTimeSpan];
208  int64_t* pend = &pmedian[nMedianTimeSpan];
209 
210  const CBlockIndex* pindex = this;
211  for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
212  *(--pbegin) = pindex->GetBlockTime();
213 
214  std::sort(pbegin, pend);
215  return pbegin[(pend - pbegin) / 2];
216 }
217 
219 {
220  unsigned int nEntropyBit = ((GetBlockHash().GetCheapHash()) & 1);
221  return nEntropyBit;
222 }
223 
224 bool CBlockIndex::SetStakeEntropyBit(unsigned int nEntropyBit)
225 {
226  if (nEntropyBit > 1)
227  return false;
228  nFlags |= (nEntropyBit ? BLOCK_STAKE_ENTROPY : 0);
229  return true;
230 }
231 
232 // Sets V1 stake modifier (uint64_t)
233 void CBlockIndex::SetStakeModifier(const uint64_t nStakeModifier, bool fGeneratedStakeModifier)
234 {
235  vStakeModifier.clear();
236  const size_t modSize = sizeof(nStakeModifier);
237  vStakeModifier.resize(modSize);
238  std::memcpy(vStakeModifier.data(), &nStakeModifier, modSize);
239  if (fGeneratedStakeModifier)
241 
242 }
243 
244 // Generates and sets new V1 stake modifier
246 {
247  // compute stake entropy bit for stake modifier
249  LogPrintf("%s : SetStakeEntropyBit() failed\n", __func__);
250  uint64_t nStakeModifier = 0;
251  bool fGeneratedStakeModifier = false;
252  if (!ComputeNextStakeModifier(pprev, nStakeModifier, fGeneratedStakeModifier))
253  LogPrintf("%s : ComputeNextStakeModifier() failed \n", __func__);
254  return SetStakeModifier(nStakeModifier, fGeneratedStakeModifier);
255 }
256 
257 // Sets V2 stake modifiers (uint256)
258 void CBlockIndex::SetStakeModifier(const uint256& nStakeModifier)
259 {
260  vStakeModifier.clear();
261  vStakeModifier.insert(vStakeModifier.begin(), nStakeModifier.begin(), nStakeModifier.end());
262 }
263 
264 // Generates and sets new V2 stake modifier
266 {
267  // Shouldn't be called on V1 modifier's blocks (or before setting pprev)
268  if (!Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V3_4)) return;
269  if (!pprev) throw std::runtime_error(strprintf("%s : ERROR: null pprev", __func__));
270 
271  // Generate Hash(prevoutId | prevModifier) - switch with genesis modifier (0) on upgrade block
272  CHashWriter ss(SER_GETHASH, 0);
273  ss << prevoutId;
274  ss << pprev->GetStakeModifierV2();
276 }
277 
278 // Returns V1 stake modifier (uint64_t)
280 {
282  return 0;
283  uint64_t nStakeModifier;
284  std::memcpy(&nStakeModifier, vStakeModifier.data(), vStakeModifier.size());
285  return nStakeModifier;
286 }
287 
288 // Returns V2 stake modifier (uint256)
290 {
291  if (vStakeModifier.empty() || !Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V3_4))
292  return UINT256_ZERO;
293  uint256 nStakeModifier;
294  std::memcpy(nStakeModifier.begin(), vStakeModifier.data(), vStakeModifier.size());
295  return nStakeModifier;
296 }
297 
299 {
300  // Sapling, update chain value
301  if (pprev) {
302  if (pprev->nChainSaplingValue) {
304  } else {
305  nChainSaplingValue = nullopt;
306  }
307  } else {
309  }
310 }
311 
313 bool CBlockIndex::IsValid(enum BlockStatus nUpTo) const
314 {
315  assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
317  return false;
318  return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
319 }
320 
324 {
325  assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
327  return false;
328  if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {
329  nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
330  return true;
331  }
332  return false;
333 }
334 
338 {
339  if (pa->nHeight > pb->nHeight) {
340  pa = pa->GetAncestor(pb->nHeight);
341  } else if (pb->nHeight > pa->nHeight) {
342  pb = pb->GetAncestor(pa->nHeight);
343  }
344 
345  while (pa != pb && pa && pb) {
346  pa = pa->pprev;
347  pb = pb->pprev;
348  }
349 
350  // Eventually all chain branches meet at the genesis block.
351  assert(pa == pb);
352  return pa;
353 }
354 
355 
@ nMedianTimeSpan
Definition: chain.cpp:202
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
Definition: chain.cpp:337
BlockStatus
Definition: chain.h:87
@ BLOCK_VALID_MASK
All validity bits.
Definition: chain.h:113
@ BLOCK_HAVE_UNDO
full block available in blk*.dat
Definition: chain.h:118
@ BLOCK_HAVE_DATA
Definition: chain.h:117
@ BLOCK_FAILED_MASK
descends from failed block
Definition: chain.h:123
@ BLOCK_STAKE_ENTROPY
Definition: chain.h:129
@ BLOCK_STAKE_MODIFIER
Definition: chain.h:130
const CChainParams & Params()
Return the currently selected parameters.
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: block.h:23
uint32_t nNonce
Definition: block.h:32
uint256 hashFinalSaplingRoot
Definition: block.h:34
uint32_t nBits
Definition: block.h:31
uint256 nAccumulatorCheckpoint
Definition: block.h:33
uint32_t nTime
Definition: block.h:30
int32_t nVersion
Definition: block.h:27
uint256 hashPrevBlock
Definition: block.h:28
uint256 hashMerkleRoot
Definition: block.h:29
Definition: block.h:80
bool IsProofOfStake() const
Definition: block.h:134
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:139
unsigned int nFlags
Definition: chain.h:181
uint256 hashMerkleRoot
Definition: chain.h:194
bool RaiseValidity(enum BlockStatus nUpTo)
Raise the validity level of this block index entry.
Definition: chain.cpp:323
CBlockIndex()
Definition: chain.h:207
uint256 GetStakeModifierV2() const
Definition: chain.cpp:289
std::string ToString() const
Definition: chain.cpp:138
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:145
void BuildSkip()
Build the skiplist pointer for this entry.
Definition: chain.cpp:118
unsigned int GetStakeEntropyBit() const
Definition: chain.cpp:218
std::vector< unsigned char > vStakeModifier
Definition: chain.h:180
CBlockHeader GetBlockHeader() const
Definition: chain.cpp:166
int nFile
Which # file this block is stored in (blk?????.dat)
Definition: chain.h:154
FlatFilePos GetBlockPos() const
Definition: chain.cpp:146
void SetNewStakeModifier()
Definition: chain.cpp:245
int64_t MaxFutureBlockTime() const
Definition: chain.cpp:180
void SetProofOfStake()
Definition: chain.h:226
uint32_t nTime
Definition: chain.h:196
void SetStakeModifier(const uint64_t nStakeModifier, bool fGeneratedStakeModifier)
Definition: chain.cpp:233
bool SetStakeEntropyBit(unsigned int nEntropyBit)
Definition: chain.cpp:224
uint32_t nNonce
Definition: chain.h:198
unsigned int nUndoPos
Byte offset within rev?????.dat where this block's undo data is stored.
Definition: chain.h:160
uint256 nAccumulatorCheckpoint
Definition: chain.h:199
uint256 GetBlockHash() const
Definition: chain.h:215
int64_t GetBlockTime() const
Definition: chain.h:216
void SetChainSaplingValue()
Definition: chain.cpp:298
int64_t GetMedianTimePast() const
Definition: chain.cpp:204
CAmount nSaplingValue
Change in value held by the Sapling circuit over this block.
Definition: chain.h:186
uint32_t nBits
Definition: chain.h:197
CBlockIndex * pskip
pointer to the index of some further predecessor of this block
Definition: chain.h:148
uint256 hashFinalSaplingRoot
Definition: chain.h:195
int64_t MinPastBlockTime() const
Definition: chain.cpp:185
FlatFilePos GetUndoPos() const
Definition: chain.cpp:156
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const
Check whether this block index entry is valid up to the passed validity level.
Definition: chain.cpp:313
int32_t nVersion
block header
Definition: chain.h:193
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:113
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:151
uint32_t nStatus
Verification status of this block. See enum BlockStatus.
Definition: chain.h:175
unsigned int nDataPos
Byte offset within blk?????.dat where this block's data is stored.
Definition: chain.h:157
Optional< CAmount > nChainSaplingValue
(memory only) Total value held by the Sapling circuit up to and including this block.
Definition: chain.h:190
uint64_t GetStakeModifierV1() const
Definition: chain.cpp:279
CBlockIndex * Tip(bool fProofOfStake=false) const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:405
CBlockLocator GetLocator(const CBlockIndex *pindex=nullptr) const
Return a CBlockLocator that refers to a block in this chain (by default the tip).
Definition: chain.cpp:27
int Height() const
Return the maximal height in the chain.
Definition: chain.h:450
const CBlockIndex * FindFork(const CBlockIndex *pindex) const
Find the last common block between this chain and a block index entry.
Definition: chain.cpp:56
std::vector< CBlockIndex * > vChain
Definition: chain.h:395
void SetTip(CBlockIndex *pindex)
Set/initialize a chain with a given tip.
Definition: chain.cpp:14
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
Definition: chain.h:435
CBlockIndex * FindEarliestAtLeast(int64_t nTime) const
Find the earliest block with timestamp equal or greater than the given.
Definition: chain.cpp:67
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:72
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:216
uint256 GetHash()
Definition: hash.h:236
std::string ToString() const
Definition: uint256.cpp:65
unsigned char * end()
Definition: uint256.h:68
unsigned char * begin()
Definition: uint256.h:63
256-bit opaque blob.
Definition: uint256.h:138
uint64_t GetCheapHash() const
A cheap hash function that just returns 64 bits from the result, it can be used when the contents are...
Definition: uint256.h:149
void * memcpy(void *a, const void *b, size_t c)
@ UPGRADE_V4_0
Definition: params.h:35
@ UPGRADE_V3_4
Definition: params.h:34
@ SER_GETHASH
Definition: serialize.h:176
bool ComputeNextStakeModifier(const CBlockIndex *pindexPrev, uint64_t &nStakeModifier, bool &fGeneratedStakeModifier)
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition: block.h:154
int nActivationHeight
Height of the first block for which the new consensus rules will be active.
Definition: params.h:56
Parameters that influence chain consensus.
Definition: params.h:171
bool IsTimeProtocolV2(const int nHeight) const
Definition: params.h:218
NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]
Definition: params.h:213
int FutureBlockTimeDrift(const int nHeight) const
Definition: params.h:221
int nFile
Definition: flatfile.h:16
unsigned int nPos
Definition: flatfile.h:17
int64_t GetAdjustedTime()
Definition: timedata.cpp:36
#define strprintf
Definition: tinyformat.h:1056
const uint256 UINT256_ZERO
constant uint256 instances
Definition: uint256.h:175
bool NetworkUpgradeActive(int nHeight, const Consensus::Params &params, Consensus::UpgradeIndex idx)
Returns true if the given network upgrade is active as of the given block height.
Definition: upgrades.cpp:107