Dash Core  0.12.2.1
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 Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "chain.h"
7 
8 using namespace std;
9 
13 void CChain::SetTip(CBlockIndex *pindex) {
14  if (pindex == NULL) {
15  vChain.clear();
16  return;
17  }
18  vChain.resize(pindex->nHeight + 1);
19  while (pindex && vChain[pindex->nHeight] != pindex) {
20  vChain[pindex->nHeight] = pindex;
21  pindex = pindex->pprev;
22  }
23 }
24 
26  int nStep = 1;
27  std::vector<uint256> vHave;
28  vHave.reserve(32);
29 
30  if (!pindex)
31  pindex = Tip();
32  while (pindex) {
33  vHave.push_back(pindex->GetBlockHash());
34  // Stop when we have added the genesis block.
35  if (pindex->nHeight == 0)
36  break;
37  // Exponentially larger steps back, plus the genesis block.
38  int nHeight = std::max(pindex->nHeight - nStep, 0);
39  if (Contains(pindex)) {
40  // Use O(1) CChain index if possible.
41  pindex = (*this)[nHeight];
42  } else {
43  // Otherwise, use O(log n) skiplist.
44  pindex = pindex->GetAncestor(nHeight);
45  }
46  if (vHave.size() > 10)
47  nStep *= 2;
48  }
49 
50  return CBlockLocator(vHave);
51 }
52 
53 const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
54  if (pindex == NULL) {
55  return NULL;
56  }
57  if (pindex->nHeight > Height())
58  pindex = pindex->GetAncestor(Height());
59  while (pindex && !Contains(pindex))
60  pindex = pindex->pprev;
61  return pindex;
62 }
63 
65 int static inline InvertLowestOne(int n) { return n & (n - 1); }
66 
68 int static inline GetSkipHeight(int height) {
69  if (height < 2)
70  return 0;
71 
72  // Determine which height to jump back to. Any number strictly lower than height is acceptable,
73  // but the following expression seems to perform well in simulations (max 110 steps to go back
74  // up to 2**18 blocks).
75  return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height);
76 }
77 
79 {
80  if (height > nHeight || height < 0)
81  return NULL;
82 
83  CBlockIndex* pindexWalk = this;
84  int heightWalk = nHeight;
85  while (heightWalk > height) {
86  int heightSkip = GetSkipHeight(heightWalk);
87  int heightSkipPrev = GetSkipHeight(heightWalk - 1);
88  if (pindexWalk->pskip != NULL &&
89  (heightSkip == height ||
90  (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
91  heightSkipPrev >= height)))) {
92  // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
93  pindexWalk = pindexWalk->pskip;
94  heightWalk = heightSkip;
95  } else {
96  assert(pindexWalk->pprev);
97  pindexWalk = pindexWalk->pprev;
98  heightWalk--;
99  }
100  }
101  return pindexWalk;
102 }
103 
104 const CBlockIndex* CBlockIndex::GetAncestor(int height) const
105 {
106  return const_cast<CBlockIndex*>(this)->GetAncestor(height);
107 }
108 
110 {
111  if (pprev)
112  pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
113 }
void SetTip(CBlockIndex *pindex)
Definition: chain.cpp:13
CBlockIndex * pskip
pointer to the index of some further predecessor of this block
Definition: chain.h:110
const CBlockIndex * FindFork(const CBlockIndex *pindex) const
Definition: chain.cpp:53
static int InvertLowestOne(int n)
Definition: chain.cpp:65
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:78
uint256 GetBlockHash() const
Definition: chain.h:218
static int GetSkipHeight(int height)
Definition: chain.cpp:68
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:107
CBlockLocator GetLocator(const CBlockIndex *pindex=NULL) const
Definition: chain.cpp:25
void BuildSkip()
Build the skiplist pointer for this entry.
Definition: chain.cpp:109
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:113