]> Git Repo - VerusCoin.git/blob - src/chain.cpp
Merge branch 'dev' into assetchain-conf
[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     lastTip = pindex;
15     if (pindex == NULL) {
16         vChain.clear();
17         return;
18     }
19     vChain.resize(pindex->nHeight + 1);
20     while (pindex && vChain[pindex->nHeight] != pindex) {
21         vChain[pindex->nHeight] = pindex;
22         pindex = pindex->pprev;
23     }
24 }
25
26 CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
27     int nStep = 1;
28     std::vector<uint256> vHave;
29     vHave.reserve(32);
30
31     if (!pindex)
32         pindex = Tip();
33     while (pindex) {
34         vHave.push_back(pindex->GetBlockHash());
35         // Stop when we have added the genesis block.
36         if (pindex->nHeight == 0)
37             break;
38         // Exponentially larger steps back, plus the genesis block.
39         int nHeight = std::max(pindex->nHeight - nStep, 0);
40         if (Contains(pindex)) {
41             // Use O(1) CChain index if possible.
42             pindex = (*this)[nHeight];
43         } else {
44             // Otherwise, use O(log n) skiplist.
45             pindex = pindex->GetAncestor(nHeight);
46         }
47         if (vHave.size() > 10)
48             nStep *= 2;
49     }
50
51     return CBlockLocator(vHave);
52 }
53
54 const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
55     if ( pindex == 0 )
56         return(0);
57     if (pindex->nHeight > Height())
58         pindex = pindex->GetAncestor(Height());
59     while (pindex && !Contains(pindex))
60         pindex = pindex->pprev;
61     return pindex;
62 }
63
64 /** Turn the lowest '1' bit in the binary representation of a number into a '0'. */
65 int static inline InvertLowestOne(int n) { return n & (n - 1); }
66
67 /** Compute what height to jump back to with the CBlockIndex::pskip pointer. */
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
78 CBlockIndex* CBlockIndex::GetAncestor(int height)
79 {
80     if (height > nHeight || height < 0)
81         return NULL;
82
83     CBlockIndex* pindexWalk = this;
84     int heightWalk = nHeight;
85     while ( heightWalk > height && pindexWalk != 0 )
86     {
87         int heightSkip = GetSkipHeight(heightWalk);
88         int heightSkipPrev = GetSkipHeight(heightWalk - 1);
89         if (pindexWalk->pskip != NULL &&
90             (heightSkip == height ||
91              (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
92                                        heightSkipPrev >= height)))) {
93             // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
94             pindexWalk = pindexWalk->pskip;
95             heightWalk = heightSkip;
96         } else {
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
109 void CBlockIndex::BuildSkip()
110 {
111     if (pprev)
112         pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
113 }
This page took 0.029806 seconds and 4 git commands to generate.