]> Git Repo - VerusCoin.git/blob - src/chain.cpp
test
[VerusCoin.git] / src / chain.cpp
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
10 /**
11  * CChain implementation
12  */
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
25 CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
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->nHeight > Height())
55         pindex = pindex->GetAncestor(Height());
56     while (pindex && !Contains(pindex))
57         pindex = pindex->pprev;
58     return pindex;
59 }
60
61 /** Turn the lowest '1' bit in the binary representation of a number into a '0'. */
62 int static inline InvertLowestOne(int n) { return n & (n - 1); }
63
64 /** Compute what height to jump back to with the CBlockIndex::pskip pointer. */
65 int static inline GetSkipHeight(int height) {
66     if (height < 2)
67         return 0;
68
69     // Determine which height to jump back to. Any number strictly lower than height is acceptable,
70     // but the following expression seems to perform well in simulations (max 110 steps to go back
71     // up to 2**18 blocks).
72     return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height);
73 }
74
75 CBlockIndex* CBlockIndex::GetAncestor(int height)
76 {
77     if (height > nHeight || height < 0)
78         return NULL;
79
80     CBlockIndex* pindexWalk = this;
81     int heightWalk = nHeight;
82     while (heightWalk > height) {
83         int heightSkip = GetSkipHeight(heightWalk);
84         int heightSkipPrev = GetSkipHeight(heightWalk - 1);
85         if (heightSkip == height ||
86             (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
87                                       heightSkipPrev >= height))) {
88             // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
89             pindexWalk = pindexWalk->pskip;
90             heightWalk = heightSkip;
91         } else {
92             pindexWalk = pindexWalk->pprev;
93             heightWalk--;
94         }
95     }
96     return pindexWalk;
97 }
98
99 const CBlockIndex* CBlockIndex::GetAncestor(int height) const
100 {
101     return const_cast<CBlockIndex*>(this)->GetAncestor(height);
102 }
103
104 void CBlockIndex::BuildSkip()
105 {
106     if (pprev)
107         pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
108 }
This page took 0.028558 seconds and 4 git commands to generate.