Skip to content

Commit 3635d62

Browse files
committed
chain: make use of pskip in LastCommonAncestor (optimization)
By using the pskip pointer, which regularly allows jumping back much faster than pprev, the forking point between two CBlockIndex entries can be found much faster. A simulation shows that no more than 136 steps are needed to jump anywhere within the first 2^20 block heights, and on average 65 jumps for uniform forking points around that height.
1 parent 2e09d66 commit 3635d62

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

src/chain.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <chain.h>
77
#include <tinyformat.h>
8+
#include <util/check.h>
89
#include <util/time.h>
910

1011
std::string CBlockFileInfo::ToString() const
@@ -158,18 +159,26 @@ int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& fr
158159
/** Find the last common ancestor two blocks have.
159160
* Both pa and pb must be non-nullptr. */
160161
const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb) {
162+
// First rewind to the last common height (the forking point cannot be past one of the two).
161163
if (pa->nHeight > pb->nHeight) {
162164
pa = pa->GetAncestor(pb->nHeight);
163165
} else if (pb->nHeight > pa->nHeight) {
164166
pb = pb->GetAncestor(pa->nHeight);
165167
}
166-
167-
while (pa != pb && pa && pb) {
168+
while (pa != pb) {
169+
// Jump back until pa and pb have a common "skip" ancestor.
170+
while (pa->pskip != pb->pskip) {
171+
// This logic relies on the property that equal-height blocks have equal-height skip
172+
// pointers.
173+
Assume(pa->nHeight == pb->nHeight);
174+
Assume(pa->pskip->nHeight == pb->pskip->nHeight);
175+
pa = pa->pskip;
176+
pb = pb->pskip;
177+
}
178+
// At this point, pa and pb are different, but have equal pskip. The forking point lies in
179+
// between pa/pb on the one end, and pa->pskip/pb->pskip on the other end.
168180
pa = pa->pprev;
169181
pb = pb->pprev;
170182
}
171-
172-
// Eventually all chain branches meet at the genesis block.
173-
assert(pa == pb);
174183
return pa;
175184
}

0 commit comments

Comments
 (0)