15 case E::NO_CHAIN_BETWEEN_BLOCKS:
16 return "no chain exists between given blocks";
18 return "unknown error";
30 const std::shared_ptr<TreeNode> &
parent,
36 std::function<outcome::result<ExitToken>(
TreeNode const &node)>
const &op)
38 using ChildIdx = size_t;
39 std::map<primitives::BlockHash, ChildIdx> fork_choice;
42 if (current_node ==
nullptr) {
47 BOOST_ASSERT(current_node->depth == chain_end.
number);
50 while (current_node->depth > this->depth) {
51 auto curren_parent = current_node->parent.lock();
52 BOOST_ASSERT(curren_parent !=
nullptr);
54 if (curren_parent->children.size() > 1) {
55 const auto child_idx = std::find_if(curren_parent->children.begin(),
56 curren_parent->children.end(),
57 [current_node](
auto &
sptr) {
58 return sptr.get() == current_node;
60 - curren_parent->children.begin();
61 fork_choice[curren_parent->block_hash] = child_idx;
63 current_node = curren_parent.get();
65 if (current_node->block_hash != this->block_hash) {
71 OUTCOME_TRY(exit_token, op(*current_node));
73 return outcome::success();
75 if (current_node->children.size() == 1) {
76 current_node = current_node->children.front().get();
77 }
else if (current_node->children.size() > 1) {
78 auto child_idx = fork_choice[current_node->block_hash];
79 current_node = current_node->children[child_idx].get();
83 }
while (current_node->depth <= chain_end.
number);
85 return outcome::success();
91 std::queue<std::shared_ptr<const TreeNode>> nodes_to_scan;
92 nodes_to_scan.push(shared_from_this());
93 while (!nodes_to_scan.empty()) {
94 const auto &node = nodes_to_scan.front();
95 if (node->block_hash == hash) {
98 for (
const auto &child : node->children) {
99 nodes_to_scan.push(child);
107 const auto &other_parent = other.
parent;
108 auto parents_equal = (
parent.expired() && other_parent.expired())
109 || (!
parent.expired() && !other_parent.expired()
110 &&
parent.lock() == other_parent.lock());
117 return !(*
this == other);
121 const std::shared_ptr<TreeNode> &subtree_root_node,
122 std::optional<primitives::Justification> last_finalized_justification)
123 : deepest_leaf{subtree_root_node},
126 std::function<void(std::shared_ptr<TreeNode>)> handle =
127 [&](std::shared_ptr<TreeNode> node) {
129 while (node->children.size() == 1) {
130 node = node->children.front();
134 if (node->children.empty()) {
135 leaves.emplace(node->block_hash);
143 for (
const auto &child : node->children) {
149 handle(subtree_root_node);
156 : leaves{std::move(leaves)},
163 auto prev_root = root_;
164 auto prev_node = new_trie_root->parent.lock();
167 root_ = std::move(new_trie_root);
172 while (prev_node && prev_node != prev_root) {
173 prev_node->children.clear();
174 prev_node = prev_node->parent.lock();
177 metadata_ = std::make_shared<TreeMeta>(root_, justification);
178 root_->parent.reset();
182 BOOST_ASSERT(root_ !=
nullptr);
187 BOOST_ASSERT(root_ !=
nullptr);
192 BOOST_ASSERT(metadata_ !=
nullptr);
197 auto parent = new_node->parent.lock();
198 parent->children.push_back(new_node);
200 metadata_->leaves.insert(new_node->block_hash);
201 metadata_->leaves.erase(parent->block_hash);
202 BOOST_ASSERT(metadata_->deepest_leaf.lock() !=
nullptr);
203 if (new_node->depth > metadata_->deepest_leaf.lock()->depth) {
204 metadata_->deepest_leaf = new_node;
209 auto parent = node->parent.lock();
210 if (parent ==
nullptr) {
215 auto it = std::find(parent->children.begin(), parent->children.end(), node);
216 if (it != parent->children.end()) {
217 parent->children.erase(it);
220 metadata_->leaves.erase(node->block_hash);
221 if (parent->children.empty()) {
222 metadata_->leaves.insert(parent->block_hash);
225 BOOST_ASSERT(not metadata_->deepest_leaf.expired());
226 if (node == metadata_->deepest_leaf.lock()) {
227 metadata_->deepest_leaf = parent;
228 for (
auto it = metadata_->leaves.begin();
229 it != metadata_->leaves.end();) {
230 const auto &hash = *it++;
231 const auto leaf_node = root_->findByHash(hash);
232 if (leaf_node ==
nullptr) {
234 metadata_->leaves.erase(hash);
235 }
else if (leaf_node->depth > parent->depth) {
236 metadata_->deepest_leaf = leaf_node;
void removeFromMeta(const std::shared_ptr< TreeNode > &node)
A reversal of updateMeta - it's called upon block tree branch prunung to remove pruned block from lea...
bool operator==(const TreeNode &other) const
outcome::result< void > applyToChain(const primitives::BlockInfo &chain_end, std::function< outcome::result< ExitToken >(TreeNode const &node)> const &op) const
primitives::BlockNumber depth
std::shared_ptr< T > sptr
TreeMeta const & getMetadata() const
bool operator!=(const TreeNode &other) const
primitives::BlockHash block_hash
TreeNode const & getRoot() const
std::shared_ptr< const TreeNode > findByHash(const primitives::BlockHash &hash) const
TreeNode(const primitives::BlockHash &hash, primitives::BlockNumber depth, bool finalized=false)
void updateMeta(const std::shared_ptr< TreeNode > &new_node)
OUTCOME_CPP_DEFINE_CATEGORY(kagome::blockchain, TreeNode::Error, e)
std::weak_ptr< TreeNode > parent
void updateTreeRoot(std::shared_ptr< TreeNode > new_trie_root, primitives::Justification justification)