veriblock-pop-cpp
C++11 Libraries for leveraging VeriBlock Proof-Of-Proof blockchain technology.
tree_algo.hpp
1// Copyright (c) 2019-2022 Xenios SEZC
2// https://www.veriblock.org
3// Distributed under the MIT software license, see the accompanying
4// file LICENSE or http://www.opensource.org/licenses/mit-license.php.
5
6#ifndef ALTINTEGRATION_TREE_ALGO_HPP
7#define ALTINTEGRATION_TREE_ALGO_HPP
8
9#include <functional>
10#include <stack>
11#include <unordered_set>
12
13#include "block_index.hpp"
14
15namespace altintegration {
16
18template <typename Block>
20 BlockIndex<Block>& index,
21 const std::function<void(BlockIndex<Block>&)>& visit,
22 const std::function<bool(BlockIndex<Block>&)>& shouldVisit) {
23 using index_t = BlockIndex<Block>;
24 std::unordered_set<index_t*> set;
25 std::stack<index_t*> stack;
26 stack.push(&index);
27 while (!stack.empty()) {
28 auto* item = stack.top();
29 if (set.count(item) > 0) {
30 visit(*item);
31 stack.pop();
32 } else {
33 for (auto* next : item->pnext) {
34 if (shouldVisit(*next)) {
35 stack.push(next);
36 }
37 }
38 set.insert(item);
39 }
40 }
41}
42
44template <typename Block>
46 const std::function<bool(BlockIndex<Block>&)>& visit) {
47 if (!visit(index)) {
48 // we should not continue traversal of this subtree
49 return;
50 }
51
52 // because pnext can be modified while iterating, we make a copy and iterate
53 // over a copy
54 auto copy = index.pnext;
55 for (auto* pnext : copy) {
56 VBK_ASSERT(pnext != nullptr);
57 forEachNodePreorder(*pnext, visit);
58 }
59}
60
62template <typename Block>
64 BlockIndex<Block>& index,
65 const std::function<bool(BlockIndex<Block>&)>& shouldContinue) {
66 for (auto* pnext : index.pnext) {
67 VBK_ASSERT(pnext != nullptr);
68 if (shouldContinue(*pnext)) {
69 forEachNextNodePreorder(*pnext, shouldContinue);
70 }
71 }
72}
73
78template <typename Block>
79std::vector<BlockIndex<Block>*> findValidTips(BlockIndex<Block>& index) {
80 using index_t = BlockIndex<Block>;
81 std::vector<index_t*> ret{};
82 forEachNodePreorder<Block>(index, [&ret](index_t& next) -> bool {
83 if (!next.isValid()) {
84 // this is invalid subtree
85 return false;
86 }
87
88 // this is valid subtree
89 if (next.isValidTip()) {
90 ret.push_back(&next);
91 // do not continue, as there are no valid next blocks
92 return false;
93 }
94
95 return true;
96 });
97
98 return ret;
99}
100
105template <typename Block>
106std::vector<BlockIndex<Block>*> findValidTips(
107 const std::unordered_set<BlockIndex<Block>*>& tips,
108 BlockIndex<Block>& index) {
109 using index_t = BlockIndex<Block>;
110 std::vector<index_t*> ret{};
111 for (auto* tip : tips) {
112 auto* ancestor = tip->getAncestor(index.getHeight());
113 if (ancestor == &index) {
114 ret.push_back(tip);
115 }
116 }
117
118 return ret;
119}
120
121} // namespace altintegration
122
123#endif // ALTINTEGRATION_TREE_ALGO_HPP
Defines logging helpers.
Definition: block.hpp:14
void forEachNodePostorder(BlockIndex< Block > &index, const std::function< void(BlockIndex< Block > &)> &visit, const std::function< bool(BlockIndex< Block > &)> &shouldVisit)
Postorder tree traversal algorithm.
Definition: tree_algo.hpp:19
std::vector< BlockIndex< Block > * > findValidTips(BlockIndex< Block > &index)
Find all tips after given block, including given block.
Definition: tree_algo.hpp:79
void forEachNodePreorder(BlockIndex< Block > &index, const std::function< bool(BlockIndex< Block > &)> &visit)
iterate across all subtrees starting (and including) given 'index'
Definition: tree_algo.hpp:45
void forEachNextNodePreorder(BlockIndex< Block > &index, const std::function< bool(BlockIndex< Block > &)> &shouldContinue)
iterate across all subtrees starting (and excluding) given 'index'
Definition: tree_algo.hpp:63
A node in a block tree.
Definition: block_index.hpp:31
std::set< BlockIndex * > pnext
(memory only) a set of pointers for forward iteration
Definition: block_index.hpp:42
const BlockIndex * getAncestor(height_t _height) const