Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 :
6 : #include "network/impl/block_loader_service.hpp"
7 :
8 : #include "backend/protobuf/block.hpp"
9 : #include "common/bind.hpp"
10 : #include "logger/logger.hpp"
11 :
12 : using namespace iroha;
13 : using namespace iroha::ametsuchi;
14 : using namespace iroha::network;
15 :
16 : BlockLoaderService::BlockLoaderService(
17 : std::shared_ptr<BlockQueryFactory> block_query_factory,
18 : std::shared_ptr<iroha::consensus::ConsensusResultCache>
19 : consensus_result_cache,
20 : logger::LoggerPtr log)
21 254 : : block_query_factory_(std::move(block_query_factory)),
22 254 : consensus_result_cache_(std::move(consensus_result_cache)),
23 254 : log_(std::move(log)) {}
24 :
25 : grpc::Status BlockLoaderService::retrieveBlocks(
26 : ::grpc::ServerContext *context,
27 : const proto::BlocksRequest *request,
28 : ::grpc::ServerWriter<::iroha::protocol::Block> *writer) {
29 3 : auto blocks = block_query_factory_->createBlockQuery() |
30 : [height = request->height()](const auto &block_query) {
31 3 : return block_query->getBlocksFrom(height);
32 : };
33 : std::for_each(blocks.begin(), blocks.end(), [&writer](const auto &block) {
34 3 : protocol::Block proto_block;
35 3 : *proto_block.mutable_block_v1() =
36 3 : std::dynamic_pointer_cast<shared_model::proto::Block>(block)
37 3 : ->getTransport();
38 :
39 3 : writer->Write(proto_block);
40 3 : });
41 3 : return grpc::Status::OK;
42 3 : }
43 :
44 : grpc::Status BlockLoaderService::retrieveBlock(
45 : ::grpc::ServerContext *context,
46 : const proto::BlockRequest *request,
47 : protocol::Block *response) {
48 4 : const auto hash = shared_model::crypto::Hash(request->hash());
49 4 : if (hash.size() == 0) {
50 0 : log_->error("Bad hash in request");
51 0 : return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
52 0 : "Bad hash provided");
53 : }
54 :
55 : // try to fetch block from the consensus cache
56 4 : auto block = consensus_result_cache_->get();
57 4 : if (block) {
58 2 : if (block->hash() == hash) {
59 : auto block_v1 =
60 1 : std::static_pointer_cast<shared_model::proto::Block>(block)
61 1 : ->getTransport();
62 1 : *response->mutable_block_v1() = block_v1;
63 1 : return grpc::Status::OK;
64 1 : } else {
65 1 : log_->info(
66 1 : "Requested to retrieve a block, but cache contains another block: "
67 : "requested {}, in cache {}",
68 1 : hash.hex(),
69 1 : block->hash().hex());
70 : }
71 1 : } else {
72 2 : log_->info(
73 2 : "Tried to retrieve a block from an empty cache: requested block hash "
74 : "{}",
75 2 : hash.hex());
76 : }
77 :
78 : // cache missed: notify and try to fetch the block from block storage itself
79 3 : auto blocks = block_query_factory_->createBlockQuery() |
80 : // TODO [IR-1757] Akvinikym 12.10.18: use block height to get one block
81 : // instead of the whole chain
82 : [](const auto &block_query) {
83 3 : return boost::make_optional(block_query->getBlocksFrom(1));
84 0 : };
85 3 : if (not blocks) {
86 0 : log_->error("Could not create block query to retrieve block from storage");
87 0 : return grpc::Status(grpc::StatusCode::INTERNAL, "internal error happened");
88 : }
89 :
90 3 : auto found_block = std::find_if(
91 : std::begin(*blocks), std::end(*blocks), [&hash](const auto &block) {
92 2 : return block->hash() == hash;
93 : });
94 3 : if (found_block == std::end(*blocks)) {
95 1 : log_->error("Could not retrieve a block from block storage: requested {}",
96 1 : hash.hex());
97 1 : return grpc::Status(grpc::StatusCode::NOT_FOUND, "Block not found");
98 : }
99 :
100 : auto block_v1 =
101 2 : std::static_pointer_cast<shared_model::proto::Block>(*found_block)
102 2 : ->getTransport();
103 2 : *response->mutable_block_v1() = block_v1;
104 2 : return grpc::Status::OK;
105 4 : }
|