@@ -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