diff --git a/core/blockchain/CMakeLists.txt b/core/blockchain/CMakeLists.txt index 572ca9875e..eb2afb2da3 100644 --- a/core/blockchain/CMakeLists.txt +++ b/core/blockchain/CMakeLists.txt @@ -12,7 +12,6 @@ add_library(blockchain impl/block_storage_error.cpp impl/justification_storage_policy.cpp impl/block_storage_impl.cpp - impl/block_header_repository_impl.cpp genesis_block_hash.cpp ) target_link_libraries(blockchain diff --git a/core/blockchain/block_header_repository.hpp b/core/blockchain/block_header_repository.hpp index a18e6c73cf..5d1bb7afe3 100644 --- a/core/blockchain/block_header_repository.hpp +++ b/core/blockchain/block_header_repository.hpp @@ -54,13 +54,6 @@ namespace kagome::blockchain { virtual outcome::result getBlockHeader( const primitives::BlockHash &block_hash) const = 0; - /** - * @return status of a block with corresponding {@param block_hash} or a - * storage error - */ - virtual outcome::result getBlockStatus( - const primitives::BlockHash &block_hash) const = 0; - /** * @param id of a block which number is returned * @return block number or a none optional if the corresponding block header diff --git a/core/blockchain/block_tree.hpp b/core/blockchain/block_tree.hpp index 8ff72eb36a..fa14b403c3 100644 --- a/core/blockchain/block_tree.hpp +++ b/core/blockchain/block_tree.hpp @@ -10,6 +10,7 @@ #include #include +#include "blockchain/block_header_repository.hpp" #include "consensus/timeline/types.hpp" #include "outcome/outcome.hpp" #include "primitives/block.hpp" @@ -27,7 +28,7 @@ namespace kagome::blockchain { * production (handling forks, pruning the blocks, resolving child-parent * relations, etc) */ - class BlockTree { + class BlockTree : public BlockHeaderRepository { public: using BlockHashVecRes = outcome::result>; @@ -53,14 +54,6 @@ namespace kagome::blockchain { */ virtual bool has(const primitives::BlockHash &hash) const = 0; - /** - * Get block header by provided block id - * @param block_hash hash of the block header we are looking for - * @return result containing block header if it exists, error otherwise - */ - virtual outcome::result getBlockHeader( - const primitives::BlockHash &block_hash) const = 0; - /** * Get a body (extrinsics) of the block (if present) * @param block_hash hash of the block to get body for diff --git a/core/blockchain/impl/block_header_repository_impl.cpp b/core/blockchain/impl/block_header_repository_impl.cpp deleted file mode 100644 index 11afe95ed0..0000000000 --- a/core/blockchain/impl/block_header_repository_impl.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright Quadrivium LLC - * All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "blockchain/impl/block_header_repository_impl.hpp" - -#include - -#include "blockchain/block_tree_error.hpp" -#include "blockchain/impl/storage_util.hpp" -#include "scale/scale.hpp" - -using kagome::primitives::BlockHash; -using kagome::primitives::BlockNumber; -using kagome::storage::Space; - -namespace kagome::blockchain { - - BlockHeaderRepositoryImpl::BlockHeaderRepositoryImpl( - std::shared_ptr storage, - std::shared_ptr hasher) - : storage_{std::move(storage)}, hasher_{std::move(hasher)} { - BOOST_ASSERT(hasher_); - } - - outcome::result BlockHeaderRepositoryImpl::getNumberByHash( - const primitives::BlockHash &hash) const { - OUTCOME_TRY(header, getBlockHeader(hash)); - return header.number; - } - - outcome::result - BlockHeaderRepositoryImpl::getHashByNumber( - primitives::BlockNumber number) const { - auto num_to_idx_key = blockNumberToKey(number); - auto key_space = storage_->getSpace(Space::kLookupKey); - auto res = key_space->get(num_to_idx_key); - if (not res.has_value()) { - return BlockTreeError::HEADER_NOT_FOUND; - } - return primitives::BlockHash::fromSpan(res.value()); - } - - outcome::result - BlockHeaderRepositoryImpl::getBlockHeader( - const primitives::BlockHash &block_hash) const { - OUTCOME_TRY(header_opt, - getFromSpace(*storage_, Space::kHeader, block_hash)); - if (header_opt.has_value()) { - OUTCOME_TRY(header, - scale::decode(header_opt.value())); - header.hash_opt.emplace(block_hash); - return header; - } - return BlockTreeError::HEADER_NOT_FOUND; - } - - outcome::result BlockHeaderRepositoryImpl::getBlockStatus( - const primitives::BlockHash &block_hash) const { - return getBlockHeader(block_hash).has_value() ? BlockStatus::InChain - : BlockStatus::Unknown; - } - -} // namespace kagome::blockchain diff --git a/core/blockchain/impl/block_header_repository_impl.hpp b/core/blockchain/impl/block_header_repository_impl.hpp deleted file mode 100644 index a0b2d8eb06..0000000000 --- a/core/blockchain/impl/block_header_repository_impl.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright Quadrivium LLC - * All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "blockchain/block_header_repository.hpp" - -#include "crypto/hasher.hpp" -#include "storage/spaced_storage.hpp" - -namespace kagome::blockchain { - - class BlockHeaderRepositoryImpl : public BlockHeaderRepository { - public: - BlockHeaderRepositoryImpl(std::shared_ptr storage, - std::shared_ptr hasher); - - ~BlockHeaderRepositoryImpl() override = default; - - outcome::result getNumberByHash( - const primitives::BlockHash &block_hash) const override; - - outcome::result getHashByNumber( - primitives::BlockNumber block_number) const override; - - outcome::result getBlockHeader( - const primitives::BlockHash &block_hash) const override; - - outcome::result getBlockStatus( - const primitives::BlockHash &block_hash) const override; - - private: - std::shared_ptr storage_; - std::shared_ptr hasher_; - }; - -} // namespace kagome::blockchain diff --git a/core/blockchain/impl/block_tree_impl.cpp b/core/blockchain/impl/block_tree_impl.cpp index aa056ba2b5..58f8dede22 100644 --- a/core/blockchain/impl/block_tree_impl.cpp +++ b/core/blockchain/impl/block_tree_impl.cpp @@ -13,6 +13,7 @@ #include "blockchain/block_tree_error.hpp" #include "blockchain/impl/cached_tree.hpp" #include "blockchain/impl/justification_storage_policy.hpp" +#include "blockchain/impl/storage_util.hpp" #include "common/main_thread_pool.hpp" #include "consensus/babe/impl/babe_digests_util.hpp" #include "consensus/babe/is_primary.hpp" @@ -35,11 +36,8 @@ namespace kagome::blockchain { namespace { /// Function-helper for loading (and repair if it needed) of leaves outcome::result> loadLeaves( - const std::shared_ptr &storage, - const std::shared_ptr &header_repo, - const log::Logger &log) { + const std::shared_ptr &storage, const log::Logger &log) { BOOST_ASSERT(storage != nullptr); - BOOST_ASSERT(header_repo != nullptr); std::set block_tree_leaves; { @@ -49,16 +47,23 @@ namespace kagome::blockchain { block_tree_unordered_leaves.size()); for (auto &hash : block_tree_unordered_leaves) { - auto res = header_repo->getNumberById(hash); - if (res.has_error()) { - if (res == outcome::failure(BlockTreeError::HEADER_NOT_FOUND)) { + // get block nuber by hash + auto header_opt_res = storage->getBlockHeader(hash); + if (header_opt_res.has_error()) { + if (header_opt_res + == outcome::failure(BlockTreeError::HEADER_NOT_FOUND)) { SL_TRACE(log, "Leaf {} not found", hash); continue; } - SL_ERROR(log, "Leaf {} is corrupted: {}", hash, res.error()); - return res.as_failure(); + SL_ERROR( + log, "Leaf {} is corrupted: {}", hash, header_opt_res.error()); + return header_opt_res.as_failure(); } - auto number = res.value(); + if (not header_opt_res.value().has_value()) { + SL_TRACE(log, "Leaf {} not found", hash); + continue; + } + auto number = header_opt_res.value()->number; SL_TRACE(log, "Leaf {} found", primitives::BlockInfo(number, hash)); block_tree_leaves.emplace(number, hash); } @@ -95,7 +100,8 @@ namespace kagome::blockchain { } } - OUTCOME_TRY(hash, header_repo->getHashById(number)); + OUTCOME_TRY(hash_opt_res, storage->getBlockHash(number)); + primitives::BlockHash hash = hash_opt_res.value(); block_tree_leaves.emplace(number, hash); if (auto res = storage->setBlockTreeLeaves({hash}); res.has_error()) { @@ -114,7 +120,6 @@ namespace kagome::blockchain { outcome::result> BlockTreeImpl::create( const application::AppConfiguration &app_config, - std::shared_ptr header_repo, std::shared_ptr storage, std::shared_ptr extrinsic_observer, std::shared_ptr hasher, @@ -128,7 +133,6 @@ namespace kagome::blockchain { std::shared_ptr state_pruner, common::MainThreadPool &main_thread_pool) { BOOST_ASSERT(storage != nullptr); - BOOST_ASSERT(header_repo != nullptr); log::Logger log = log::createLogger("BlockTree", "block_tree"); @@ -147,7 +151,7 @@ namespace kagome::blockchain { OUTCOME_TRY(storage->getJustification(last_finalized_block_info.hash)); - OUTCOME_TRY(block_tree_leaves, loadLeaves(storage, header_repo, log)); + OUTCOME_TRY(block_tree_leaves, loadLeaves(storage, log)); BOOST_ASSERT_MSG(not block_tree_leaves.empty(), "Must be known or calculated at least one leaf"); @@ -275,7 +279,6 @@ namespace kagome::blockchain { std::shared_ptr block_tree( new BlockTreeImpl(app_config, - std::move(header_repo), std::move(storage), last_finalized_block_info, std::move(extrinsic_observer), @@ -320,7 +323,7 @@ namespace kagome::blockchain { log::Logger log = log::createLogger("BlockTree", "block_tree"); - OUTCOME_TRY(block_tree_leaves, loadLeaves(storage, header_repo, log)); + OUTCOME_TRY(block_tree_leaves, loadLeaves(storage, log)); BOOST_ASSERT_MSG(not block_tree_leaves.empty(), "Must be known or calculated at least one leaf"); @@ -410,7 +413,6 @@ namespace kagome::blockchain { BlockTreeImpl::BlockTreeImpl( const application::AppConfiguration &app_config, - std::shared_ptr header_repo, std::shared_ptr storage, const primitives::BlockInfo &finalized, std::shared_ptr extrinsic_observer, @@ -425,7 +427,7 @@ namespace kagome::blockchain { std::shared_ptr state_pruner, common::MainThreadPool &main_thread_pool) : block_tree_data_{BlockTreeData{ - .header_repo_ = std::move(header_repo), + .header_repo_ = nullptr, // Initialize with BlockTreeImpl in body .storage_ = std::move(storage), .state_pruner_ = std::move(state_pruner), .tree_ = std::make_unique(finalized), @@ -441,6 +443,7 @@ namespace kagome::blockchain { main_pool_handler_{main_thread_pool.handlerStarted()}, extrinsic_events_engine_{std::move(extrinsic_events_engine)} { block_tree_data_.sharedAccess([&](const BlockTreeData &p) { + p.header_repo_ = shared_from_this(); BOOST_ASSERT(p.header_repo_ != nullptr); BOOST_ASSERT(p.storage_ != nullptr); BOOST_ASSERT(p.tree_ != nullptr); @@ -1441,6 +1444,22 @@ namespace kagome::blockchain { }); } + // BlockHeaderRepository methods + outcome::result BlockTreeImpl::getNumberByHash( + const primitives::BlockHash &hash) const { + OUTCOME_TRY(header, getBlockHeader(hash)); + return header.number; + } + + outcome::result BlockTreeImpl::getHashByNumber( + primitives::BlockNumber number) const { + OUTCOME_TRY(block_hash_opt, getBlockHash(number)); + if (block_hash_opt.has_value()) { + return block_hash_opt.value(); + } + return BlockTreeError::HEADER_NOT_FOUND; + } + BlockTreeImpl::BlocksPruning::BlocksPruning(std::optional keep, primitives::BlockNumber finalized) : keep_{keep}, next_{max(finalized)} {} diff --git a/core/blockchain/impl/block_tree_impl.hpp b/core/blockchain/impl/block_tree_impl.hpp index c2e2ee74a5..4edbadf52b 100644 --- a/core/blockchain/impl/block_tree_impl.hpp +++ b/core/blockchain/impl/block_tree_impl.hpp @@ -21,6 +21,7 @@ #include "blockchain/block_header_repository.hpp" #include "blockchain/block_storage.hpp" #include "blockchain/block_tree_error.hpp" +#include "blockchain/impl/cached_tree.hpp" #include "consensus/babe/types/babe_configuration.hpp" #include "consensus/timeline/types.hpp" #include "crypto/hasher.hpp" @@ -40,7 +41,6 @@ namespace kagome { namespace kagome::blockchain { struct ReorgAndPrune; class TreeNode; - class CachedTree; } // namespace kagome::blockchain namespace kagome::common { @@ -59,7 +59,6 @@ namespace kagome::blockchain { /// Create an instance of block tree static outcome::result> create( const application::AppConfiguration &app_config, - std::shared_ptr header_repo, std::shared_ptr storage, std::shared_ptr extrinsic_observer, std::shared_ptr hasher, @@ -158,6 +157,13 @@ namespace kagome::blockchain { void removeUnfinalized() override; + // BlockHeaderRepository methods + outcome::result getNumberByHash( + const primitives::BlockHash &block_hash) const override; + + outcome::result getHashByNumber( + primitives::BlockNumber block_number) const override; + private: struct BlocksPruning { BlocksPruning(std::optional keep, @@ -170,7 +176,7 @@ namespace kagome::blockchain { }; struct BlockTreeData { - std::shared_ptr header_repo_; + mutable std::shared_ptr header_repo_; std::shared_ptr storage_; std::shared_ptr state_pruner_; std::unique_ptr tree_; @@ -190,7 +196,6 @@ namespace kagome::blockchain { */ BlockTreeImpl( const application::AppConfiguration &app_config, - std::shared_ptr header_repo, std::shared_ptr storage, const primitives::BlockInfo &finalized, std::shared_ptr extrinsic_observer, diff --git a/core/injector/application_injector.cpp b/core/injector/application_injector.cpp index 6e063f3f57..e0f3f89125 100644 --- a/core/injector/application_injector.cpp +++ b/core/injector/application_injector.cpp @@ -56,7 +56,6 @@ #include "authorship/impl/block_builder_impl.hpp" #include "authorship/impl/proposer_impl.hpp" #include "benchmark/block_execution_benchmark.hpp" -#include "blockchain/impl/block_header_repository_impl.hpp" #include "blockchain/impl/block_storage_impl.hpp" #include "blockchain/impl/block_tree_impl.hpp" #include "blockchain/impl/justification_storage_policy.hpp" @@ -345,6 +344,10 @@ namespace { template sptr get_block_tree(const Injector &injector) { + static std::optional> cached = std::nullopt; + if (cached.has_value()) { + return cached.value(); + } auto chain_events_engine = injector .template create(); @@ -352,7 +355,6 @@ namespace { // clang-format off auto block_tree_res = blockchain::BlockTreeImpl::create( injector.template create(), - injector.template create>(), injector.template create>(), injector.template create>(), injector.template create>(), @@ -375,6 +377,7 @@ namespace { runtime_upgrade_tracker->subscribeToBlockchainEvents(chain_events_engine, block_tree); + cached = block_tree; return block_tree; } @@ -744,7 +747,8 @@ namespace { di::bind.template to(), bind_by_lambda( [](const auto &injector) { return get_block_tree(injector); }), - di::bind.template to(), + bind_by_lambda( + [](const auto &injector) { return get_block_tree(injector); }), di::bind.template to(), di::bind.template to(), di::bind.template to(), diff --git a/core/utils/kagome_db_editor.cpp b/core/utils/kagome_db_editor.cpp index eb3ad29561..25948b6f5f 100644 --- a/core/utils/kagome_db_editor.cpp +++ b/core/utils/kagome_db_editor.cpp @@ -15,7 +15,6 @@ #include #include "blockchain/block_storage_error.hpp" -#include "blockchain/impl/block_header_repository_impl.hpp" #include "blockchain/impl/block_storage_impl.hpp" #include "blockchain/impl/block_tree_impl.hpp" #include "blockchain/impl/storage_util.hpp" @@ -268,7 +267,7 @@ int db_editor_main(int argc, const char **argv) { }), di::bind.to(factory), di::bind.template to(), - di::bind.template to(), + di::bind.template to(), di::bind.template to()); auto hasher = injector.template create>();