Skip to content

src/blockchain/impl/block_tree_impl.hpp

Namespaces

Name
sgns
sgns::blockchain

Classes

Name
class sgns::blockchain::BlockTreeImpl

Functions

Name
OUTCOME_HPP_DECLARE_ERROR_2(sgns::blockchain , BlockTreeImpl::Error )

Functions Documentation

function OUTCOME_HPP_DECLARE_ERROR_2

OUTCOME_HPP_DECLARE_ERROR_2(
    sgns::blockchain ,
    BlockTreeImpl::Error 
)

Source code

#ifndef SUPERGENIUS_SRC_BLOCK_TREE_IMPL_HPP
#define SUPERGENIUS_SRC_BLOCK_TREE_IMPL_HPP

#include "blockchain/block_tree.hpp"

#include <boost/optional.hpp>
#include <functional>
#include <memory>
#include <unordered_set>

#include "blockchain/block_header_repository.hpp"
#include "blockchain/block_storage.hpp"
#include "base/logger.hpp"
#include "crypto/hasher.hpp"
#include "network/extrinsic_observer.hpp"

namespace sgns::blockchain {
  class BlockTreeImpl : public BlockTree {
    struct TreeNode : public std::enable_shared_from_this<TreeNode> {
        TreeNode( primitives::BlockHash     hash,
                  primitives::BlockNumber   depth,
                  std::shared_ptr<TreeNode> parent,
                  bool                      finalized = false );

        primitives::BlockHash   block_hash;
        primitives::BlockNumber depth;

        std::weak_ptr<TreeNode> parent;

        bool finalized;

        std::vector<std::shared_ptr<TreeNode>> children;

        std::shared_ptr<TreeNode> getByHash( const primitives::BlockHash &hash );

        bool operator==( const TreeNode &other ) const;
        bool operator!=( const TreeNode &other ) const;
    };

    struct TreeMeta {
      explicit TreeMeta(TreeNode &subtree_root_node);

      TreeMeta(std::unordered_set<primitives::BlockHash> leaves,
               TreeNode &deepest_leaf,
               TreeNode &last_finalized);

      std::unordered_set<primitives::BlockHash> leaves;
      std::reference_wrapper<TreeNode> deepest_leaf;

      std::reference_wrapper<TreeNode> last_finalized;
    };

   public:
    enum class Error {
      // target block number is past the given maximum number
      TARGET_IS_PAST_MAX = 1,
      // block resides on a dead fork
      BLOCK_ON_DEAD_END,
      // block exists in chain but not found when following all
      // leaves backwards.
      BLOCK_NOT_FOUND
    };

    static outcome::result<std::shared_ptr<BlockTreeImpl>> create(
        std::shared_ptr<BlockHeaderRepository> header_repo,
        std::shared_ptr<BlockStorage> storage,
        const primitives::BlockId &last_finalized_block,
        std::shared_ptr<network::ExtrinsicObserver> extrinsic_observer,
        std::shared_ptr<crypto::Hasher> hasher);

    ~BlockTreeImpl() override = default;

    [[nodiscard]] outcome::result<primitives::BlockHeader> getBlockHeader(
        const primitives::BlockId &block ) const override;

    [[nodiscard]] outcome::result<primitives::BlockBody> getBlockBody(
        const primitives::BlockId &block ) const override;

    [[nodiscard]] outcome::result<primitives::Justification> getBlockJustification(
        const primitives::BlockId &block ) const override;

    outcome::result<void> addBlockHeader(
        const primitives::BlockHeader &header) override;

    outcome::result<void> addBlock(const primitives::Block &block) override;

    outcome::result<void> addBlockBody(
        primitives::BlockNumber block_number,
        const primitives::BlockHash &block_hash,
        const primitives::BlockBody &body) override;

    outcome::result<void> finalize(
        const primitives::BlockHash &block,
        const primitives::Justification &justification) override;

    BlockHashVecRes getChainByBlock(
        const primitives::BlockHash &block) override;

    BlockHashVecRes getChainByBlock(const primitives::BlockHash &block,
                                    bool ascending,
                                    uint64_t maximum) override;
    BlockHashVecRes getChainByBlocks(
        const primitives::BlockHash &top_block,
        const primitives::BlockHash &bottom_block) override;

    bool hasDirectChain(const primitives::BlockHash &ancestor,
                        const primitives::BlockHash &descendant) override;

    BlockHashVecRes longestPath() override;

    [[nodiscard]] primitives::BlockInfo deepestLeaf() const override;

    [[nodiscard]] outcome::result<primitives::BlockInfo> getBestContaining(
        const primitives::BlockHash                    &target_hash,
        const boost::optional<primitives::BlockNumber> &max_number ) const override;

    [[nodiscard]] std::vector<primitives::BlockHash> getLeaves() const override;

    BlockHashVecRes getChildren(const primitives::BlockHash &block) override;

    [[nodiscard]] primitives::BlockInfo getLastFinalized() const override;

    std::string GetName() override
    {
        return "BlockTreeImpl";
    }

   private:
    BlockTreeImpl(
        std::shared_ptr<BlockHeaderRepository> header_repo,
        std::shared_ptr<BlockStorage> storage,
        std::shared_ptr<TreeNode> tree,
        std::shared_ptr<TreeMeta> meta,
        std::shared_ptr<network::ExtrinsicObserver> extrinsic_observer,
        std::shared_ptr<crypto::Hasher> hasher);

    outcome::result<primitives::BlockHash> walkBackUntilLess(
        const primitives::BlockHash &start,
        const primitives::BlockNumber &limit) const;

    std::vector<primitives::BlockHash> getLeavesSorted() const;

    static void collectDescendants(
        std::shared_ptr<TreeNode> node,
        std::vector<std::pair<primitives::BlockHash, primitives::BlockNumber>>
            &container);

    outcome::result<void> prune( std::shared_ptr<TreeNode> lastFinalizedNode );

    std::shared_ptr<BlockHeaderRepository> header_repo_;
    std::shared_ptr<BlockStorage> storage_;

    std::shared_ptr<TreeNode> tree_;
    std::shared_ptr<TreeMeta> tree_meta_;

    std::shared_ptr<network::ExtrinsicObserver> extrinsic_observer_;

    std::shared_ptr<crypto::Hasher> hasher_;
    base::Logger log_ = base::createLogger("BlockTreeImpl");
  };
}  // namespace sgns::blockchain

OUTCOME_HPP_DECLARE_ERROR_2(sgns::blockchain, BlockTreeImpl::Error);

#endif  // SUPERGENIUS_SRC_BLOCK_TREE_IMPL_HPP

Updated on 2026-03-04 at 13:10:44 -0800