aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2016-04-19 10:44:44 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2016-04-19 10:44:47 +0200
commit4205ad7ca2b159cc463d5a27e17e013c9dba8570 (patch)
tree4741c78076bbafe58e36efbaddd11da41d29ae9a
parentfa9d86f8c4f4aba2c284f1db2cc8d0a1e89a9ce6 (diff)
parent87049e832d97d4f2808c0b479b21fc7b16c86934 (diff)
downloadbitcoin-4205ad7ca2b159cc463d5a27e17e013c9dba8570.tar.xz
Merge #7827: Speed up getchaintips.
87049e8 Speed up getchaintips. (mrbandrews)
-rw-r--r--src/rpc/blockchain.cpp29
1 files changed, 21 insertions, 8 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 88f6278b2a..5de2394e24 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -815,17 +815,30 @@ UniValue getchaintips(const UniValue& params, bool fHelp)
LOCK(cs_main);
- /* Build up a list of chain tips. We start with the list of all
- known blocks, and successively remove blocks that appear as pprev
- of another block. */
+ /*
+ * Idea: the set of chain tips is chainActive.tip, plus orphan blocks which do not have another orphan building off of them.
+ * Algorithm:
+ * - Make one pass through mapBlockIndex, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
+ * - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip.
+ * - add chainActive.Tip()
+ */
std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
- BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
- setTips.insert(item.second);
+ std::set<const CBlockIndex*> setOrphans;
+ std::set<const CBlockIndex*> setPrevs;
+
BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
{
- const CBlockIndex* pprev = item.second->pprev;
- if (pprev)
- setTips.erase(pprev);
+ if (!chainActive.Contains(item.second)) {
+ setOrphans.insert(item.second);
+ setPrevs.insert(item.second->pprev);
+ }
+ }
+
+ for (std::set<const CBlockIndex*>::iterator it = setOrphans.begin(); it != setOrphans.end(); ++it)
+ {
+ if (setPrevs.erase(*it) == 0) {
+ setTips.insert(*it);
+ }
}
// Always report the currently active tip.