Kagome
Polkadot Runtime Engine in C++17
chain_api_impl.cpp
Go to the documentation of this file.
1 
7 
8 #include <jsonrpc-lean/fault.h>
9 
11 #include "common/hexutil.hpp"
12 #include "common/visitor.hpp"
13 
16  switch (e) {
17  case E::BLOCK_NOT_FOUND:
18  return "The requested block is not found";
19  case E::HEADER_NOT_FOUND:
20  return "The requested block header is not found";
21  }
22  return "Unknown Chain API error";
23 }
24 
25 namespace kagome::api {
28 
30  std::shared_ptr<blockchain::BlockHeaderRepository> block_repo,
31  std::shared_ptr<blockchain::BlockTree> block_tree,
32  std::shared_ptr<blockchain::BlockStorage> block_storage)
33  : header_repo_{std::move(block_repo)},
34  block_tree_{std::move(block_tree)},
35  block_storage_{std::move(block_storage)} {
36  BOOST_ASSERT_MSG(header_repo_ != nullptr,
37  "block repo parameter is nullptr");
38  BOOST_ASSERT_MSG(block_tree_ != nullptr, "block tree parameter is nullptr");
39  BOOST_ASSERT(block_storage_);
40  }
41 
42  outcome::result<BlockHash> ChainApiImpl::getBlockHash() const {
43  auto last_finalized = block_tree_->getLastFinalized();
44  return last_finalized.hash;
45  }
46  outcome::result<common::Hash256> ChainApiImpl::getBlockHash(
47  BlockNumber value) const {
48  return header_repo_->getHashByNumber(value);
49  }
50 
52  std::shared_ptr<api::ApiService> const &api_service) {
53  BOOST_ASSERT(api_service != nullptr);
54  api_service_ = api_service;
55  }
56 
57  outcome::result<BlockHash> ChainApiImpl::getBlockHash(
58  std::string_view value) const {
59  // despite w3f specification says, that request contains 32-bit
60  // unsigned integer, we are free to decode more capacious number,
61  // since BlockNumber, which is really being requested
62  // is defined as uint64_t
63  OUTCOME_TRY(number, common::unhexNumber<BlockNumber>(value));
64  return getBlockHash(number);
65  }
66 
67  outcome::result<std::vector<BlockHash>> ChainApiImpl::getBlockHash(
68  gsl::span<const ValueType> values) const {
69  std::vector<BlockHash> results;
70  results.reserve(values.size());
71 
72  for (const auto &v : values) {
73  auto &&res = kagome::visit_in_place(
74  v,
75  [this](BlockNumber number) { return getBlockHash(number); },
76  [this](std::string_view hex_string) {
77  return getBlockHash(hex_string);
78  });
79  OUTCOME_TRY(r, res);
80  results.emplace_back(r);
81  }
82 
83  return results;
84  }
85 
86  outcome::result<primitives::BlockData> ChainApiImpl::getBlock(
87  std::string_view hash) {
88  OUTCOME_TRY(h, primitives::BlockHash::fromHexWithPrefix(hash));
89  OUTCOME_TRY(block, block_storage_->getBlockData(h));
90  if (block) return block.value();
92  }
93 
94  outcome::result<primitives::BlockData> ChainApiImpl::getBlock() {
95  auto last_finalized_info = block_tree_->getLastFinalized();
96  OUTCOME_TRY(block, block_storage_->getBlockData(last_finalized_info.hash));
97  if (block) return block.value();
99  }
100 
101  outcome::result<primitives::BlockHash> ChainApiImpl::getFinalizedHead()
102  const {
103  return block_tree_->getLastFinalized().hash;
104  }
105 
106  outcome::result<uint32_t> ChainApiImpl::subscribeFinalizedHeads() {
107  if (auto api_service = api_service_.lock())
108  return api_service->subscribeFinalizedHeads();
109 
110  throw jsonrpc::InternalErrorFault(
111  "Internal error. Api service not initialized.");
112  }
113 
115  uint32_t subscription_id) {
116  if (auto api_service = api_service_.lock()) {
117  OUTCOME_TRY(api_service->unsubscribeFinalizedHeads(subscription_id));
118  // any non-error result is considered as success
119  return outcome::success();
120  }
121 
122  throw jsonrpc::InternalErrorFault(
123  "Internal error. Api service not initialized.");
124  }
125 
126  outcome::result<uint32_t> ChainApiImpl::subscribeNewHeads() {
127  if (auto api_service = api_service_.lock())
128  return api_service->subscribeNewHeads();
129 
130  throw jsonrpc::InternalErrorFault(
131  "Internal error. Api service not initialized.");
132  }
133 
134  outcome::result<void> ChainApiImpl::unsubscribeNewHeads(
135  uint32_t subscription_id) {
136  if (auto api_service = api_service_.lock()) {
137  OUTCOME_TRY(api_service->unsubscribeNewHeads(subscription_id));
138  return outcome::success();
139  }
140 
141  throw jsonrpc::InternalErrorFault(
142  "Internal error. Api service not initialized.");
143  }
144 
145 } // namespace kagome::api
outcome::result< primitives::BlockData > getBlock() override
outcome::result< uint32_t > subscribeNewHeads() override
OUTCOME_CPP_DEFINE_CATEGORY(kagome::api, ChainApiImpl::Error, e)
outcome::result< void > unsubscribeFinalizedHeads(uint32_t subscription_id) override
std::shared_ptr< blockchain::BlockHeaderRepository > header_repo_
std::shared_ptr< blockchain::BlockStorage > block_storage_
primitives::BlockNumber BlockNumber
Definition: chain_api.hpp:26
static outcome::result< Blob< size_ > > fromHexWithPrefix(std::string_view hex)
Definition: blob.hpp:197
uint32_t BlockNumber
Definition: common.hpp:18
std::shared_ptr< blockchain::BlockTree > block_tree_
common::Hash256 BlockHash
Definition: block_id.hpp:15
ChainApiImpl(std::shared_ptr< blockchain::BlockHeaderRepository > block_repo, std::shared_ptr< blockchain::BlockTree > block_tree, std::shared_ptr< blockchain::BlockStorage > block_storage)
outcome::result< primitives::BlockHash > getFinalizedHead() const override
outcome::result< BlockHash > getBlockHash() const override
std::weak_ptr< api::ApiService > api_service_
void setApiService(std::shared_ptr< api::ApiService > const &api_service) override
outcome::result< uint32_t > subscribeFinalizedHeads() override
outcome::result< void > unsubscribeNewHeads(uint32_t subscription_id) override