hyperledger/iroha
Iroha - A simple, decentralized ledger http://iroha.tech
query_template.hpp
Go to the documentation of this file.
1 
6 #ifndef IROHA_PROTO_QUERY_BUILDER_TEMPLATE_HPP
7 #define IROHA_PROTO_QUERY_BUILDER_TEMPLATE_HPP
8 
9 #include <google/protobuf/util/time_util.h>
10 
11 #include <boost/range/algorithm/for_each.hpp>
12 #include <optional>
13 #include <string_view>
14 
21 #include "module/irohad/common/validators_config.hpp"
22 #include "queries.pb.h"
24 
25 namespace shared_model {
26  namespace proto {
27 
36  template <int S = 0,
38  typename BT = UnsignedWrapper<Query>>
39  class /*[[deprecated]]*/ TemplateQueryBuilder {
40  private:
41  template <int, typename, typename>
42  friend class TemplateQueryBuilder;
43 
44  enum RequiredFields {
45  CreatedTime,
46  CreatorAccountId,
47  QueryField,
48  QueryCounter,
49  TOTAL
50  };
51 
52  template <int s>
54 
55  using ProtoQuery = iroha::protocol::Query;
56 
57  template <int Sp>
59  : query_(o.query_), stateless_validator_(o.stateless_validator_) {}
60 
67  template <int Fields, typename Transformation>
68  auto transform(Transformation t) const {
69  NextBuilder<Fields> copy = *this;
70  t(copy.query_);
71  return copy;
72  }
73 
80  template <typename Transformation>
81  auto queryField(Transformation t) const {
82  NextBuilder<QueryField> copy = *this;
83  t(copy.query_.mutable_payload());
84  return copy;
85  }
86 
88  template <typename PageMetaPayload>
89  static auto setTxPaginationMeta(
90  PageMetaPayload * page_meta_payload,
92  const std::optional<interface::types::HashType> &first_hash =
93  std::nullopt,
94  const interface::Ordering *ordering = nullptr,
95  const std::optional<interface::types::TimestampType> &first_tx_time =
96  std::nullopt,
97  const std::optional<interface::types::TimestampType> &last_tx_time =
98  std::nullopt,
99  const std::optional<interface::types::HeightType> &first_tx_height =
100  std::nullopt,
101  const std::optional<interface::types::HeightType> &last_tx_height =
102  std::nullopt) {
103  auto from_interface_2_proto_field =
104  [](interface::Ordering::Field value) {
105  switch (value) {
108 
110  return iroha::protocol::Field::kPosition;
111 
112  default:
113  BOOST_ASSERT_MSG(false, "Unexpected Field value!");
114  return iroha::protocol::Field::kCreatedTime; //FIXME -Wreturn-type
115  }
116  };
117 
118  auto from_interface_2_proto_direction =
120  switch (value) {
122  return iroha::protocol::Direction::kAscending;
123 
125  return iroha::protocol::Direction::kDescending;
126 
127  default: {
128  BOOST_ASSERT_MSG(false, "Unexpected Direction value!");
129  return iroha::protocol::Direction::kAscending; // suppress -Wreturn-type=error
130  }
131  }
132  };
133 
134  page_meta_payload->set_page_size(page_size);
135  if (first_hash) {
136  page_meta_payload->set_first_tx_hash(first_hash->hex());
137  }
138  if (first_tx_time) {
139  auto timestamp_begin = new google::protobuf::Timestamp{
140  google::protobuf::util::TimeUtil::MillisecondsToTimestamp(
141  first_tx_time.value())};
142  page_meta_payload->set_allocated_first_tx_time(timestamp_begin);
143  }
144  if (last_tx_time) {
145  auto timestamp_end = new google::protobuf::Timestamp{
146  google::protobuf::util::TimeUtil::MillisecondsToTimestamp(
147  last_tx_time.value())};
148  page_meta_payload->set_allocated_last_tx_time(timestamp_end);
149  }
150  if (first_tx_height) {
151  page_meta_payload->set_first_tx_height(first_tx_height.value());
152  }
153  if (last_tx_height) {
154  page_meta_payload->set_last_tx_height(last_tx_height.value());
155  }
156  if (ordering) {
157  interface::Ordering::OrderingEntry const *ptr = nullptr;
158  size_t count = 0;
159  (*ordering).get(ptr, count);
160 
161  for (size_t ix = 0; ix < count; ++ix) {
162  interface::Ordering::OrderingEntry const &entry = ptr[ix];
163 
164  auto sequence =
165  page_meta_payload->mutable_ordering()->add_sequence();
166  sequence->set_field(from_interface_2_proto_field(entry.field));
167  sequence->set_direction(
168  from_interface_2_proto_direction(entry.direction));
169  }
170  }
171  }
172 
173  TemplateQueryBuilder(const SV &validator)
174  : stateless_validator_(validator) {}
175 
176  public:
177  // we do such default initialization only because it is deprecated and
178  // used only in tests
180  : TemplateQueryBuilder(SV(iroha::test::kTestsValidatorsConfig)) {}
181 
182  auto createdTime(interface::types::TimestampType created_time) const {
183  return transform<CreatedTime>([&](auto &qry) {
184  qry.mutable_payload()->mutable_meta()->set_created_time(created_time);
185  });
186  }
187 
189  const interface::types::AccountIdType &creator_account_id) const {
190  return transform<CreatorAccountId>([&](auto &qry) {
191  qry.mutable_payload()->mutable_meta()->set_creator_account_id(
192  creator_account_id);
193  });
194  }
195 
196  auto queryCounter(interface::types::CounterType query_counter) const {
197  return transform<QueryCounter>([&](auto &qry) {
198  qry.mutable_payload()->mutable_meta()->set_query_counter(
199  query_counter);
200  });
201  }
202 
203  auto getAccount(const interface::types::AccountIdType &account_id) const {
204  return queryField([&](auto proto_query) {
205  auto query = proto_query->mutable_get_account();
206  query->set_account_id(account_id);
207  });
208  }
209 
211  const {
212  return queryField([&](auto proto_query) {
213  auto query = proto_query->mutable_get_signatories();
214  query->set_account_id(account_id);
215  });
216  }
217 
219  const interface::types::AccountIdType &account_id,
221  const std::optional<interface::types::HashType> &first_hash =
222  std::nullopt,
223  const interface::Ordering *ordering = nullptr,
224  const std::optional<interface::types::TimestampType> &first_tx_time =
225  std::nullopt,
226  const std::optional<interface::types::TimestampType> &last_tx_time =
227  std::nullopt,
228  const std::optional<interface::types::HeightType> &first_tx_height =
229  std::nullopt,
230  const std::optional<interface::types::HeightType> &last_tx_height =
231  std::nullopt) const {
232  return queryField([&](auto proto_query) {
233  auto query = proto_query->mutable_get_account_transactions();
234  query->set_account_id(account_id);
235  setTxPaginationMeta(query->mutable_pagination_meta(),
236  page_size,
237  first_hash,
238  ordering,
239  first_tx_time,
240  last_tx_time,
241  first_tx_height,
242  last_tx_height);
243  });
244  }
245 
247  const interface::types::AccountIdType &account_id,
248  const interface::types::AssetIdType &asset_id,
250  const std::optional<interface::types::HashType> &first_hash =
251  std::nullopt,
252  const interface::Ordering *ordering = nullptr,
253  const std::optional<interface::types::TimestampType> &first_tx_time =
254  std::nullopt,
255  const std::optional<interface::types::TimestampType> &last_tx_time =
256  std::nullopt,
257  const std::optional<interface::types::HeightType> &first_tx_height =
258  std::nullopt,
259  const std::optional<interface::types::HeightType> &last_tx_height =
260  std::nullopt) const {
261  return queryField([&](auto proto_query) {
262  auto query = proto_query->mutable_get_account_asset_transactions();
263  query->set_account_id(account_id);
264  query->set_asset_id(asset_id);
265  setTxPaginationMeta(query->mutable_pagination_meta(),
266  page_size,
267  first_hash,
268  ordering,
269  first_tx_time,
270  last_tx_time,
271  first_tx_height,
272  last_tx_height);
273  });
274  }
275 
277  const interface::types::AccountIdType &account_id,
278  size_t page_size,
279  std::optional<shared_model::interface::types::AssetIdType>
280  first_asset_id) const {
281  return queryField([&](auto proto_query) {
282  auto query = proto_query->mutable_get_account_assets();
283  query->set_account_id(account_id);
284  auto pagination_meta = query->mutable_pagination_meta();
285  pagination_meta->set_page_size(page_size);
286  if (first_asset_id) {
287  pagination_meta->set_first_asset_id(*first_asset_id);
288  }
289  });
290  }
291 
293  size_t page_size,
294  const interface::types::AccountIdType &account_id = "",
296  const interface::types::AccountIdType &writer = "",
297  const std::optional<plain::AccountDetailRecordId> &first_record_id =
298  std::nullopt) {
299  return queryField([&](auto proto_query) {
300  auto query = proto_query->mutable_get_account_detail();
301  if (not account_id.empty()) {
302  query->set_account_id(account_id);
303  }
304  if (not key.empty()) {
305  query->set_key(key);
306  }
307  if (not writer.empty()) {
308  query->set_writer(writer);
309  }
310  auto pagination_meta = query->mutable_pagination_meta();
311  pagination_meta->set_page_size(page_size);
312  if (first_record_id) {
313  auto proto_first_record_id =
314  pagination_meta->mutable_first_record_id();
315  proto_first_record_id->set_writer(first_record_id->writer());
316  proto_first_record_id->set_key(first_record_id->key());
317  }
318  });
319  }
320 
322  return queryField([&](auto proto_query) {
323  auto query = proto_query->mutable_get_block();
324  query->set_height(height);
325  });
326  }
327 
328  auto getEngineReceipts(std::string_view tx_hash) {
329  return queryField([&](auto proto_query) {
330  auto query = proto_query->mutable_get_engine_receipts();
331  query->set_tx_hash(tx_hash.data(), tx_hash.size());
332  });
333  }
334 
335  auto getRoles() const {
336  return queryField(
337  [&](auto proto_query) { proto_query->mutable_get_roles(); });
338  }
339 
340  auto getAssetInfo(const interface::types::AssetIdType &asset_id) const {
341  return queryField([&](auto proto_query) {
342  auto query = proto_query->mutable_get_asset_info();
343  query->set_asset_id(asset_id);
344  });
345  }
346 
348  const {
349  return queryField([&](auto proto_query) {
350  auto query = proto_query->mutable_get_role_permissions();
351  query->set_role_id(role_id);
352  });
353  }
354 
355  template <typename Collection>
356  auto getTransactions(const Collection &hashes) const {
357  return queryField([&](auto proto_query) {
358  auto query = proto_query->mutable_get_transactions();
359  boost::for_each(hashes, [&query](const auto &hash) {
360  query->add_tx_hashes(hash.hex());
361  });
362  });
363  }
364 
366  std::initializer_list<interface::types::HashType> hashes) const {
367  return getTransactions(hashes);
368  }
369 
370  template <typename... Hash>
371  auto getTransactions(const Hash &... hashes) const {
372  return getTransactions({hashes...});
373  }
374 
375  auto getPendingTransactions() const {
376  return queryField([&](auto proto_query) {
377  proto_query->mutable_get_pending_transactions();
378  });
379  }
380 
383  const std::optional<interface::types::HashType> &first_hash =
384  std::nullopt) const {
385  return queryField([&](auto proto_query) {
386  auto query = proto_query->mutable_get_pending_transactions();
387  setTxPaginationMeta(
388  query->mutable_pagination_meta(), page_size, first_hash);
389  });
390  }
391 
392  auto getPeers() const {
393  return queryField(
394  [&](auto proto_query) { proto_query->mutable_get_peers(); });
395  }
396 
397  auto build() const {
398  static_assert(S == (1 << TOTAL) - 1, "Required fields are not set");
399  if (not query_.has_payload()) {
400  throw std::invalid_argument("Query missing payload");
401  }
402  if (query_.payload().query_case()
403  == iroha::protocol::Query_Payload::QueryCase::QUERY_NOT_SET) {
404  throw std::invalid_argument("Missing concrete query");
405  }
406  auto result = Query(iroha::protocol::Query(query_));
407  if (auto error = stateless_validator_.validate(result)) {
408  throw std::invalid_argument(error->toString());
409  }
410  return BT(std::move(result));
411  }
412 
413  static const int total = RequiredFields::TOTAL;
414 
415  private:
416  ProtoQuery query_;
417  SV stateless_validator_;
418  };
419  } // namespace proto
420 } // namespace shared_model
421 
422 #endif // IROHA_PROTO_QUERY_BUILDER_TEMPLATE_HPP
auto getBlock(interface::types::HeightType height) const
Definition: query_template.hpp:321
Definition: ordering.hpp:19
auto getTransactions(const Hash &... hashes) const
Definition: query_template.hpp:371
uint64_t HeightType
Type of height (for Block, Proposal etc)
Definition: types.hpp:48
Direction direction
Definition: ordering.hpp:48
auto createdTime(interface::types::TimestampType created_time) const
Definition: query_template.hpp:182
QueryValidator< FieldValidator, QueryValidatorVisitor< FieldValidator > > DefaultUnsignedQueryValidator
Definition: default_validator.hpp:57
auto getAccountAssets(const interface::types::AccountIdType &account_id, size_t page_size, std::optional< shared_model::interface::types::AssetIdType > first_asset_id) const
Definition: query_template.hpp:276
auto creatorAccountId(const interface::types::AccountIdType &creator_account_id) const
Definition: query_template.hpp:188
Definition: query_response_handler.cpp:72
auto getTransactions(const Collection &hashes) const
Definition: query_template.hpp:356
auto getAssetInfo(const interface::types::AssetIdType &asset_id) const
Definition: query_template.hpp:340
auto getPeers() const
Definition: query_template.hpp:392
Field field
Definition: ordering.hpp:47
Field
Definition: ordering.hpp:24
auto getAccount(const interface::types::AccountIdType &account_id) const
Definition: query_template.hpp:203
auto getPendingTransactions(interface::types::TransactionsNumberType page_size, const std::optional< interface::types::HashType > &first_hash=std::nullopt) const
Definition: query_template.hpp:381
TemplateQueryBuilder()
Definition: query_template.hpp:179
auto queryCounter(interface::types::CounterType query_counter) const
Definition: query_template.hpp:196
auto getPendingTransactions() const
Definition: query_template.hpp:375
std::string AccountDetailKeyType
Type of account detail key.
Definition: types.hpp:81
static const int total
Definition: query_template.hpp:413
Definition: block_query.hpp:15
Definition: proto_query.hpp:16
std::string AccountIdType
Type of account id.
Definition: types.hpp:38
hash256_t hash(const T &pb)
Definition: pb_common.hpp:43
auto getSignatories(const interface::types::AccountIdType &account_id) const
Definition: query_template.hpp:210
auto getAccountTransactions(const interface::types::AccountIdType &account_id, interface::types::TransactionsNumberType page_size, const std::optional< interface::types::HashType > &first_hash=std::nullopt, const interface::Ordering *ordering=nullptr, const std::optional< interface::types::TimestampType > &first_tx_time=std::nullopt, const std::optional< interface::types::TimestampType > &last_tx_time=std::nullopt, const std::optional< interface::types::HeightType > &first_tx_height=std::nullopt, const std::optional< interface::types::HeightType > &last_tx_height=std::nullopt) const
Definition: query_template.hpp:218
auto getRoles() const
Definition: query_template.hpp:335
uint16_t TransactionsNumberType
Type of a number of transactions in block and query response page.
Definition: types.hpp:86
auto getTransactions(std::initializer_list< interface::types::HashType > hashes) const
Definition: query_template.hpp:365
uint64_t CounterType
Type of counter.
Definition: types.hpp:71
auto getAccountDetail(size_t page_size, const interface::types::AccountIdType &account_id="", const interface::types::AccountDetailKeyType &key="", const interface::types::AccountIdType &writer="", const std::optional< plain::AccountDetailRecordId > &first_record_id=std::nullopt)
Definition: query_template.hpp:292
Definition: command_executor.hpp:13
auto build() const
Definition: query_template.hpp:397
auto getEngineReceipts(std::string_view tx_hash)
Definition: query_template.hpp:328
Direction
Definition: ordering.hpp:35
Definition: query_template.hpp:39
std::string RoleIdType
Type of role (i.e admin, user)
Definition: types.hpp:56
auto getAccountAssetTransactions(const interface::types::AccountIdType &account_id, const interface::types::AssetIdType &asset_id, interface::types::TransactionsNumberType page_size, const std::optional< interface::types::HashType > &first_hash=std::nullopt, const interface::Ordering *ordering=nullptr, const std::optional< interface::types::TimestampType > &first_tx_time=std::nullopt, const std::optional< interface::types::TimestampType > &last_tx_time=std::nullopt, const std::optional< interface::types::HeightType > &first_tx_height=std::nullopt, const std::optional< interface::types::HeightType > &last_tx_height=std::nullopt) const
Definition: query_template.hpp:246
auto getRolePermissions(const interface::types::RoleIdType &role_id) const
Definition: query_template.hpp:347
uint64_t TimestampType
Type of timestamp.
Definition: types.hpp:69
std::string AssetIdType
Type of asset id.
Definition: types.hpp:60