Skip to content

Commit 4f5bb79

Browse files
laanwjcodablock
authored andcommitted
Merge bitcoin#7827: Speed up getchaintips.
87049e8 Speed up getchaintips. (mrbandrews)
1 parent 1b17e94 commit 4f5bb79

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

src/rpc/blockchain.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -959,17 +959,30 @@ UniValue getchaintips(const UniValue& params, bool fHelp)
959959

960960
LOCK(cs_main);
961961

962-
/* Build up a list of chain tips. We start with the list of all
963-
known blocks, and successively remove blocks that appear as pprev
964-
of another block. */
962+
/*
963+
* Idea: the set of chain tips is chainActive.tip, plus orphan blocks which do not have another orphan building off of them.
964+
* Algorithm:
965+
* - Make one pass through mapBlockIndex, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
966+
* - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip.
967+
* - add chainActive.Tip()
968+
*/
965969
std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
966-
BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
967-
setTips.insert(item.second);
970+
std::set<const CBlockIndex*> setOrphans;
971+
std::set<const CBlockIndex*> setPrevs;
972+
968973
BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
969974
{
970-
const CBlockIndex* pprev = item.second->pprev;
971-
if (pprev)
972-
setTips.erase(pprev);
975+
if (!chainActive.Contains(item.second)) {
976+
setOrphans.insert(item.second);
977+
setPrevs.insert(item.second->pprev);
978+
}
979+
}
980+
981+
for (std::set<const CBlockIndex*>::iterator it = setOrphans.begin(); it != setOrphans.end(); ++it)
982+
{
983+
if (setPrevs.erase(*it) == 0) {
984+
setTips.insert(*it);
985+
}
973986
}
974987

975988
// Always report the currently active tip.

0 commit comments

Comments
 (0)