Scorum
database_api.cpp
Go to the documentation of this file.
2 
4 
7 
9 
10 #include <scorum/rewards_math/formulas.hpp>
11 
27 
37 
39 
40 #include <fc/bloom_filter.hpp>
41 #include <fc/smart_ref_impl.hpp>
42 #include <fc/crypto/hex.hpp>
43 #include <fc/container/utils.hpp>
44 
45 #include <boost/range/iterator_range.hpp>
46 #include <boost/algorithm/string.hpp>
47 
48 #include <cctype>
49 
50 #include <cfenv>
51 #include <iostream>
52 
53 namespace scorum {
54 namespace app {
55 
56 class database_api_impl;
57 
58 class database_api_impl : public std::enable_shared_from_this<database_api_impl>
59 {
60 public:
63 
64  // Subscriptions
65  void set_block_applied_callback(std::function<void(const variant& block_id)> cb);
66 
67  // Globals
68  fc::variant_object get_config() const;
71 
72  // Keys
73  std::vector<std::set<std::string>> get_key_references(std::vector<public_key_type> key) const;
74 
75  // Accounts
76  std::vector<extended_account> get_accounts(const std::vector<std::string>& names) const;
77  std::vector<account_id_type> get_account_references(account_id_type account_id) const;
78  std::vector<optional<account_api_obj>> lookup_account_names(const std::vector<std::string>& account_names) const;
79  std::set<std::string> lookup_accounts(const std::string& lower_bound_name, uint32_t limit) const;
80  uint64_t get_account_count() const;
81 
82  // Budgets
83  template <typename BudgetService>
84  std::vector<budget_api_obj> get_budgets(BudgetService& budget_service, const std::set<std::string>& names) const
85  {
86  FC_ASSERT(names.size() <= get_api_config(API_DATABASE).max_budgets_list_size,
87  "names size must be less or equal than ${1}",
88  ("1", get_api_config(API_DATABASE).max_budgets_list_size));
89 
90  std::vector<budget_api_obj> results;
91 
92  for (const auto& name : names)
93  {
94  auto budgets = budget_service.get_budgets(name);
95  if (results.size() + budgets.size() > get_api_config(API_DATABASE).max_budgets_list_size)
96  {
97  break;
98  }
99 
100  for (const auto& budget : budgets)
101  {
102  results.emplace_back(budget);
103  }
104  }
105 
106  return results;
107  }
108  template <typename BudgetService>
109  std::set<std::string>
110  lookup_budget_owners(BudgetService& budget_service, const std::string& lower_bound_name, uint32_t limit) const
111  {
112  FC_ASSERT(limit <= get_api_config(API_DATABASE).max_budgets_list_size, "limit must be less or equal than ${1}",
113  ("1", get_api_config(API_DATABASE).max_budgets_list_size));
114 
115  return budget_service.lookup_budget_owners(lower_bound_name, limit);
116  }
117 
118  // Atomic Swap
119  std::vector<atomicswap_contract_api_obj> get_atomicswap_contracts(const std::string& owner) const;
121  get_atomicswap_contract(const std::string& from, const std::string& to, const std::string& secret_hash) const;
122 
123  // Witnesses
124  std::vector<optional<witness_api_obj>> get_witnesses(const std::vector<witness_id_type>& witness_ids) const;
125  fc::optional<witness_api_obj> get_witness_by_account(const std::string& account_name) const;
126  std::set<account_name_type> lookup_witness_accounts(const std::string& lower_bound_name, uint32_t limit) const;
127  uint64_t get_witness_count() const;
128 
129  // Committee
130  std::set<account_name_type> lookup_registration_committee_members(const std::string& lower_bound_name,
131  uint32_t limit) const;
132 
133  std::set<account_name_type> lookup_development_committee_members(const std::string& lower_bound_name,
134  uint32_t limit) const;
135 
136  std::vector<proposal_api_obj> lookup_proposals() const;
137 
138  // Authority / validation
139  std::string get_transaction_hex(const signed_transaction& trx) const;
140  std::set<public_key_type> get_required_signatures(const signed_transaction& trx,
141  const flat_set<public_key_type>& available_keys) const;
142  std::set<public_key_type> get_potential_signatures(const signed_transaction& trx) const;
143  bool verify_authority(const signed_transaction& trx) const;
144  bool verify_account_authority(const std::string& name_or_id, const flat_set<public_key_type>& signers) const;
145 
146  // signal handlers
147  void on_applied_block(const chain::signed_block& b);
148 
149  std::function<void(const fc::variant&)> _block_applied_callback;
150 
152 
153  boost::signals2::scoped_connection _block_applied_connection;
154 
158 };
159 
161 // //
162 // Subscriptions //
163 // //
165 
166 void database_api::set_block_applied_callback(std::function<void(const variant& block_id)> cb)
167 {
168  my->_db.with_read_lock([&]() { my->set_block_applied_callback(cb); });
169 }
170 
172 {
173  try
174  {
176  }
177  catch (...)
178  {
179  _block_applied_connection.release();
180  }
181 }
182 
183 void database_api_impl::set_block_applied_callback(std::function<void(const variant& block_header)> cb)
184 {
187 }
188 
190 // //
191 // Constructors //
192 // //
194 
196  : my(new database_api_impl(ctx))
197 {
198 }
199 
201 {
202 }
203 
205  : _db(*ctx.app.chain_database())
206 {
207  wlog("creating database api ${x}", ("x", int64_t(this)));
208 }
209 
211 {
212  elog("freeing database api ${x}", ("x", int64_t(this)));
213 }
214 
216 {
217 }
218 
220 // //
221 // Globals //
222 // //
224 
225 fc::variant_object database_api::get_config() const
226 {
227  return my->_db.with_read_lock([&]() { return my->get_config(); });
228 }
229 
230 fc::variant_object database_api_impl::get_config() const
231 {
233 }
234 
236 {
237  return my->_db.with_read_lock([&]() { return my->get_dynamic_global_properties(); });
238 }
239 
241 {
244 
245  if (_db.has_index<witness::reserve_ratio_index>())
246  {
247  const auto& r = _db.find(witness::reserve_ratio_id_type());
248 
249  if (BOOST_LIKELY(r != nullptr))
250  {
251  gpao = *r;
252  }
253  }
254 
256  {
258  }
259 
261  {
262  gpao.fund_budget_balance = _db.obtain_service<dbs_fund_budget>().get().balance;
263  }
264 
266  {
268  }
269 
271  {
273  = _db.obtain_service<dbs_content_reward_fund_scr>().get().activity_reward_balance;
274  }
275 
277  {
278  gpao.content_reward_sp_balance = _db.obtain_service<dbs_content_reward_fund_sp>().get().activity_reward_balance;
279  }
280 
281  return gpao;
282 }
283 
285 {
286  return my->_db.with_read_lock([&]() { return my->get_chain_id(); });
287 }
288 
290 {
291  return _db.get_chain_id();
292 }
293 
295 {
296  return my->_db.with_read_lock([&]() { return my->_db.get(witness_schedule_id_type()); });
297 }
298 
300 // //
301 // Keys //
302 // //
304 
305 std::vector<std::set<std::string>> database_api::get_key_references(std::vector<public_key_type> key) const
306 {
307  return my->_db.with_read_lock([&]() { return my->get_key_references(key); });
308 }
309 
313 std::vector<std::set<std::string>> database_api_impl::get_key_references(std::vector<public_key_type> keys) const
314 {
315  FC_ASSERT(false,
316  "database_api::get_key_references has been deprecated. Please use "
317  "account_by_key_api::get_key_references instead.");
318  std::vector<std::set<std::string>> final_result;
319  return final_result;
320 }
321 
323 // //
324 // Accounts //
325 // //
327 
328 std::vector<extended_account> database_api::get_accounts(const std::vector<std::string>& names) const
329 {
330  return my->_db.with_read_lock([&]() { return my->get_accounts(names); });
331 }
332 
333 std::vector<extended_account> database_api_impl::get_accounts(const std::vector<std::string>& names) const
334 {
335  const auto& idx = _db.get_index<account_index>().indices().get<by_name>();
336  const auto& vidx = _db.get_index<witness_vote_index>().indices().get<by_account_witness>();
337  std::vector<extended_account> results;
338 
339  auto& dprop = _db.obtain_service<dbs_dynamic_global_property>().get();
340 
341  for (auto& name : names)
342  {
343  auto itr = idx.find(name);
344  if (itr != idx.end())
345  {
347  api_obj.voting_power = rewards_math::calculate_restoring_power(
348  api_obj.voting_power, _db.head_block_time(), api_obj.last_vote_time, SCORUM_VOTE_REGENERATION_SECONDS);
349 
350  api_obj.head_block_number = dprop.head_block_number;
351  api_obj.last_irreversible_block_num = dprop.last_irreversible_block_num;
352  api_obj.head_block_id = dprop.head_block_id;
353  api_obj.time = dprop.time;
354 
355  results.push_back(std::move(api_obj));
356 
357  auto vitr = vidx.lower_bound(boost::make_tuple(itr->id, witness_id_type()));
358  while (vitr != vidx.end() && vitr->account == itr->id)
359  {
360  results.back().witness_votes.insert(_db.get(vitr->witness).owner);
361  ++vitr;
362  }
363  }
364  }
365 
366  return results;
367 }
368 
369 std::vector<account_id_type> database_api::get_account_references(account_id_type account_id) const
370 {
371  return my->_db.with_read_lock([&]() { return my->get_account_references(account_id); });
372 }
373 
374 std::vector<account_id_type> database_api_impl::get_account_references(account_id_type account_id) const
375 {
376  /*const auto& idx = _db.get_index<account_index>();
377  const auto& aidx = dynamic_cast<const primary_index<account_index>&>(idx);
378  const auto& refs = aidx.get_secondary_index<scorum::chain::account_member_index>();
379  auto itr = refs.account_to_account_memberships.find(account_id);
380  std::vector<account_id_type> result;
381 
382  if( itr != refs.account_to_account_memberships.end() )
383  {
384  result.reserve( itr->second.size() );
385  for( auto item : itr->second ) result.push_back(item);
386  }
387  return result;*/
388  FC_ASSERT(false, "database_api::get_account_references --- Needs to be refactored for scorum.");
389 }
390 
391 std::vector<optional<account_api_obj>>
392 database_api::lookup_account_names(const std::vector<std::string>& account_names) const
393 {
394  return my->_db.with_read_lock([&]() { return my->lookup_account_names(account_names); });
395 }
396 
397 std::vector<optional<account_api_obj>>
398 database_api_impl::lookup_account_names(const std::vector<std::string>& account_names) const
399 {
400  std::vector<optional<account_api_obj>> result;
401  result.reserve(account_names.size());
402  for (auto& name : account_names)
403  {
404  auto itr = _db.find<account_object, by_name>(name);
405 
406  if (itr)
407  {
408  result.push_back(account_api_obj(*itr, _db));
409  }
410  else
411  {
412  result.push_back(optional<account_api_obj>());
413  }
414  }
415 
416  return result;
417 }
418 
419 std::set<std::string> database_api::lookup_accounts(const std::string& lower_bound_name, uint32_t limit) const
420 {
421  return my->_db.with_read_lock([&]() { return my->lookup_accounts(lower_bound_name, limit); });
422 }
423 
424 std::set<std::string> database_api_impl::lookup_accounts(const std::string& lower_bound_name, uint32_t limit) const
425 {
426  FC_ASSERT(limit <= get_api_config(API_DATABASE).lookup_limit);
427  const auto& accounts_by_name = _db.get_index<account_index>().indices().get<by_name>();
428  std::set<std::string> result;
429 
430  for (auto itr = accounts_by_name.lower_bound(lower_bound_name); limit-- && itr != accounts_by_name.end(); ++itr)
431  {
432  result.insert(itr->name);
433  }
434 
435  return result;
436 }
437 
439 {
440  return my->_db.with_read_lock([&]() { return my->get_account_count(); });
441 }
442 
444 {
445  return _db.get_index<account_index>().indices().size();
446 }
447 
448 std::vector<owner_authority_history_api_obj> database_api::get_owner_history(const std::string& account) const
449 {
450  return my->_db.with_read_lock([&]() {
451  std::vector<owner_authority_history_api_obj> results;
452 
453  const auto& hist_idx = my->_db.get_index<owner_authority_history_index>().indices().get<by_account>();
454  auto itr = hist_idx.lower_bound(account);
455 
456  while (itr != hist_idx.end() && itr->account == account)
457  {
458  results.push_back(owner_authority_history_api_obj(*itr));
459  ++itr;
460  }
461 
462  return results;
463  });
464 }
465 
466 optional<account_recovery_request_api_obj> database_api::get_recovery_request(const std::string& account) const
467 {
468  return my->_db.with_read_lock([&]() {
469  optional<account_recovery_request_api_obj> result;
470 
471  const auto& rec_idx = my->_db.get_index<account_recovery_request_index>().indices().get<by_account>();
472  auto req = rec_idx.find(account);
473 
474  if (req != rec_idx.end())
476 
477  return result;
478  });
479 }
480 
481 optional<escrow_api_obj> database_api::get_escrow(const std::string& from, uint32_t escrow_id) const
482 {
483  return my->_db.with_read_lock([&]() {
484  optional<escrow_api_obj> result;
485 
486  try
487  {
488  result = my->_db.obtain_service<dbs_escrow>().get(from, escrow_id);
489  }
490  catch (...)
491  {
492  }
493 
494  return result;
495  });
496 }
497 
498 std::vector<withdraw_route> database_api::get_withdraw_routes(const std::string& account,
499  withdraw_route_type type) const
500 {
501  return my->_db.with_read_lock([&]() {
502  std::vector<withdraw_route> result;
503 
504  const auto& acc = my->_db.account_service().get_account(account);
505 
506  if (type == outgoing || type == all)
507  {
508  const auto& by_route
509  = my->_db.get_index<withdraw_scorumpower_route_index>().indices().get<by_withdraw_route>();
510  auto route = by_route.lower_bound(acc.id); // TODO: test get_withdraw_routes
511 
512  while (route != by_route.end() && is_equal_withdrawable_id(route->from_id, acc.id))
513  {
514  withdraw_route r;
515  r.from_account = account;
516  r.to_account = my->_db.get(route->to_id.get<account_id_type>()).name;
517  r.percent = route->percent;
518  r.auto_vest = route->auto_vest;
519 
520  result.push_back(r);
521 
522  ++route;
523  }
524  }
525 
526  if (type == incoming || type == all)
527  {
528  const auto& by_dest = my->_db.get_index<withdraw_scorumpower_route_index>().indices().get<by_destination>();
529  auto route = by_dest.lower_bound(acc.id); // TODO: test get_withdraw_routes
530 
531  while (route != by_dest.end() && is_equal_withdrawable_id(route->to_id, acc.id))
532  {
533  withdraw_route r;
534  r.from_account = my->_db.get(route->from_id.get<account_id_type>()).name;
535  r.to_account = account;
536  r.percent = route->percent;
537  r.auto_vest = route->auto_vest;
538 
539  result.push_back(r);
540 
541  ++route;
542  }
543  }
544 
545  return result;
546  });
547 }
548 
549 optional<account_bandwidth_api_obj> database_api::get_account_bandwidth(const std::string& account,
550  witness::bandwidth_type type) const
551 {
552  optional<account_bandwidth_api_obj> result;
553 
554  if (my->_db.has_index<witness::account_bandwidth_index>())
555  {
556  auto band = my->_db.find<witness::account_bandwidth_object, witness::by_account_bandwidth_type>(
557  boost::make_tuple(account, type));
558  if (band != nullptr)
559  result = *band;
560  }
561 
562  return result;
563 }
564 
566 // //
567 // Witnesses //
568 // //
570 
571 std::vector<optional<witness_api_obj>>
572 database_api::get_witnesses(const std::vector<witness_id_type>& witness_ids) const
573 {
574  return my->_db.with_read_lock([&]() { return my->get_witnesses(witness_ids); });
575 }
576 
577 std::vector<optional<witness_api_obj>>
578 database_api_impl::get_witnesses(const std::vector<witness_id_type>& witness_ids) const
579 {
580  std::vector<optional<witness_api_obj>> result;
581  result.reserve(witness_ids.size());
582  std::transform(witness_ids.begin(), witness_ids.end(), std::back_inserter(result),
583  [this](witness_id_type id) -> optional<witness_api_obj> {
584  if (auto o = _db.find(id))
585  return *o;
586  return {};
587  });
588  return result;
589 }
590 
591 fc::optional<witness_api_obj> database_api::get_witness_by_account(const std::string& account_name) const
592 {
593  return my->_db.with_read_lock([&]() { return my->get_witness_by_account(account_name); });
594 }
595 
596 std::vector<witness_api_obj> database_api::get_witnesses_by_vote(const std::string& from, uint32_t limit) const
597 {
598  return my->_db.with_read_lock([&]() {
599  // idump((from)(limit));
600  FC_ASSERT(limit <= get_api_config(API_DATABASE).lookup_limit);
601 
602  std::vector<witness_api_obj> result;
603  result.reserve(limit);
604 
605  const auto& name_idx = my->_db.get_index<witness_index>().indices().get<by_name>();
606  const auto& vote_idx = my->_db.get_index<witness_index>().indices().get<by_vote_name>();
607 
608  auto itr = vote_idx.begin();
609  if (from.size())
610  {
611  auto nameitr = name_idx.find(from);
612  FC_ASSERT(nameitr != name_idx.end(), "invalid witness name ${n}", ("n", from));
613  itr = vote_idx.iterator_to(*nameitr);
614  }
615 
616  while (itr != vote_idx.end() && result.size() < limit && itr->votes > 0)
617  {
618  result.push_back(witness_api_obj(*itr));
619  ++itr;
620  }
621  return result;
622  });
623 }
624 
625 fc::optional<witness_api_obj> database_api_impl::get_witness_by_account(const std::string& account_name) const
626 {
627  const auto& idx = _db.get_index<witness_index>().indices().get<by_name>();
628  auto itr = idx.find(account_name);
629  if (itr != idx.end())
630  return witness_api_obj(*itr);
631  return {};
632 }
633 
634 std::set<account_name_type> database_api::lookup_witness_accounts(const std::string& lower_bound_name,
635  uint32_t limit) const
636 {
637  return my->_db.with_read_lock([&]() { return my->lookup_witness_accounts(lower_bound_name, limit); });
638 }
639 
640 std::set<account_name_type> database_api_impl::lookup_witness_accounts(const std::string& lower_bound_name,
641  uint32_t limit) const
642 {
643  FC_ASSERT(limit <= get_api_config(API_DATABASE).lookup_limit);
644  const auto& witnesses_by_id = _db.get_index<witness_index>().indices().get<by_id>();
645 
646  // get all the names and look them all up, sort them, then figure out what
647  // records to return. This could be optimized, but we expect the
648  // number of witnesses to be few and the frequency of calls to be rare
649  std::set<account_name_type> witnesses_by_account_name;
650  for (const witness_api_obj& witness : witnesses_by_id)
651  if (witness.owner >= lower_bound_name) // we can ignore anything below lower_bound_name
652  witnesses_by_account_name.insert(witness.owner);
653 
654  auto end_iter = witnesses_by_account_name.begin();
655  while (end_iter != witnesses_by_account_name.end() && limit--)
656  ++end_iter;
657  witnesses_by_account_name.erase(end_iter, witnesses_by_account_name.end());
658  return witnesses_by_account_name;
659 }
660 
661 uint64_t database_api::get_witness_count() const
662 {
663  return my->_db.with_read_lock([&]() { return my->get_witness_count(); });
664 }
665 
666 uint64_t database_api_impl::get_witness_count() const
667 {
668  return _db.get_index<witness_index>().indices().size();
669 }
670 
671 advertising_property_api_obj database_api::get_advertising_property() const
672 {
673  return my->_db.with_read_lock([&]() { return my->get_advertising_property(); });
674 }
675 
676 advertising_property_api_obj database_api_impl::get_advertising_property() const
677 {
678  return advertising_property_api_obj(_db.advertising_property_service().get());
679 }
680 
681 std::set<account_name_type> database_api::lookup_registration_committee_members(const std::string& lower_bound_name,
682  uint32_t limit) const
683 {
684 
685  return my->_db.with_read_lock([&]() { return my->lookup_registration_committee_members(lower_bound_name, limit); });
686 }
687 
688 std::set<account_name_type> database_api::lookup_development_committee_members(const std::string& lower_bound_name,
689  uint32_t limit) const
690 {
691  return my->_db.with_read_lock([&]() { return my->lookup_development_committee_members(lower_bound_name, limit); });
692 }
693 
694 std::set<account_name_type>
695 database_api_impl::lookup_registration_committee_members(const std::string& lower_bound_name, uint32_t limit) const
696 {
697  FC_ASSERT(limit <= get_api_config(API_DATABASE).lookup_limit);
698 
699  return chain::committee::lookup_members<registration_committee_member_index>(_db, lower_bound_name, limit);
700 }
701 
702 std::set<account_name_type> database_api_impl::lookup_development_committee_members(const std::string& lower_bound_name,
703  uint32_t limit) const
704 {
705  FC_ASSERT(limit <= get_api_config(API_DATABASE).lookup_limit);
706 
707  return chain::committee::lookup_members<dev_committee_member_index>(_db, lower_bound_name, limit);
708 }
709 
710 std::vector<proposal_api_obj> database_api::lookup_proposals() const
711 {
712  return my->_db.with_read_lock([&]() { return my->lookup_proposals(); });
713 }
714 
715 std::vector<proposal_api_obj> database_api_impl::lookup_proposals() const
716 {
717  const auto& proposals_by_id = _db.get_index<proposal_object_index>().indices().get<by_id>();
718 
719  std::vector<proposal_api_obj> proposals;
720  for (const proposal_api_obj& obj : proposals_by_id)
721  {
722  proposals.push_back(obj);
723  }
724 
725  return proposals;
726 }
727 
728 registration_committee_api_obj database_api::get_registration_committee() const
729 {
730  return my->_db.with_read_lock([&]() { return my->get_registration_committee(); });
731 }
732 
733 registration_committee_api_obj database_api_impl::get_registration_committee() const
734 {
736 
737  return committee;
738 }
739 
740 development_committee_api_obj database_api::get_development_committee() const
741 {
742  return my->_db.with_read_lock([&]() { return my->get_development_committee(); });
743 }
744 
745 development_committee_api_obj database_api_impl::get_development_committee() const
746 {
748  committee = _db.get(dev_committee_id_type());
749 
750  return committee;
751 }
752 
754 // //
755 // Authority / validation //
756 // //
758 
759 std::string database_api::get_transaction_hex(const signed_transaction& trx) const
760 {
761  return my->_db.with_read_lock([&]() { return my->get_transaction_hex(trx); });
762 }
763 
764 std::string database_api_impl::get_transaction_hex(const signed_transaction& trx) const
765 {
766  return fc::to_hex(fc::raw::pack(trx));
767 }
768 
769 std::set<public_key_type> database_api::get_required_signatures(const signed_transaction& trx,
770  const flat_set<public_key_type>& available_keys) const
771 {
772  return my->_db.with_read_lock([&]() { return my->get_required_signatures(trx, available_keys); });
773 }
774 
775 std::set<public_key_type>
776 database_api_impl::get_required_signatures(const signed_transaction& trx,
777  const flat_set<public_key_type>& available_keys) const
778 {
779  // wdump((trx)(available_keys));
780  auto result = trx.get_required_signatures(
781  get_chain_id(), available_keys,
782  [&](const std::string& account_name) {
783  return authority(_db.get<account_authority_object, by_account>(account_name).active);
784  },
785  [&](const std::string& account_name) {
786  return authority(_db.get<account_authority_object, by_account>(account_name).owner);
787  },
788  [&](const std::string& account_name) {
789  return authority(_db.get<account_authority_object, by_account>(account_name).posting);
790  },
791  SCORUM_MAX_SIG_CHECK_DEPTH);
792  // wdump((result));
793  return result;
794 }
795 
796 std::set<public_key_type> database_api::get_potential_signatures(const signed_transaction& trx) const
797 {
798  return my->_db.with_read_lock([&]() { return my->get_potential_signatures(trx); });
799 }
800 
801 std::set<public_key_type> database_api_impl::get_potential_signatures(const signed_transaction& trx) const
802 {
803  // wdump((trx));
804  std::set<public_key_type> result;
806  get_chain_id(), flat_set<public_key_type>(),
807  [&](account_name_type account_name) {
808  const auto& auth = _db.get<account_authority_object, by_account>(account_name).active;
809  for (const auto& k : auth.get_keys())
810  result.insert(k);
811  return authority(auth);
812  },
813  [&](account_name_type account_name) {
814  const auto& auth = _db.get<account_authority_object, by_account>(account_name).owner;
815  for (const auto& k : auth.get_keys())
816  result.insert(k);
817  return authority(auth);
818  },
819  [&](account_name_type account_name) {
820  const auto& auth = _db.get<account_authority_object, by_account>(account_name).posting;
821  for (const auto& k : auth.get_keys())
822  result.insert(k);
823  return authority(auth);
824  },
825  SCORUM_MAX_SIG_CHECK_DEPTH);
826 
827  // wdump((result));
828  return result;
829 }
830 
832 {
833  return my->_db.with_read_lock([&]() { return my->verify_authority(trx); });
834 }
835 
837 {
838  trx.verify_authority(
839  get_chain_id(),
840  [&](const std::string& account_name) {
841  return authority(_db.get<account_authority_object, by_account>(account_name).active);
842  },
843  [&](const std::string& account_name) {
844  return authority(_db.get<account_authority_object, by_account>(account_name).owner);
845  },
846  [&](const std::string& account_name) {
847  return authority(_db.get<account_authority_object, by_account>(account_name).posting);
848  },
849  SCORUM_MAX_SIG_CHECK_DEPTH);
850  return true;
851 }
852 
853 bool database_api::verify_account_authority(const std::string& name_or_id,
854  const flat_set<public_key_type>& signers) const
855 {
856  return my->_db.with_read_lock([&]() { return my->verify_account_authority(name_or_id, signers); });
857 }
858 
859 bool database_api_impl::verify_account_authority(const std::string& name, const flat_set<public_key_type>& keys) const
860 {
861  FC_ASSERT(name.size() > 0);
862  auto account = _db.find<account_object, by_name>(name);
863  FC_ASSERT(account, "no such account");
864 
866  signed_transaction trx;
868  op.from = account->name;
869  trx.operations.emplace_back(op);
870 
871  return verify_authority(trx);
872 }
873 
874 std::vector<vote_state> database_api::get_active_votes(const std::string& author, const std::string& permlink) const
875 {
876  return my->_db.with_read_lock([&]() {
877  std::vector<vote_state> result;
878  const auto& comment = my->_db.obtain_service<dbs_comment>().get(author, permlink);
879  const auto& idx = my->_db.get_index<comment_vote_index>().indices().get<by_comment_voter>();
880  comment_id_type cid(comment.id);
881  auto itr = idx.lower_bound(cid);
882  while (itr != idx.end() && itr->comment == cid)
883  {
884  const auto& vo = my->_db.get(itr->voter);
885  vote_state vstate;
886  vstate.voter = vo.name;
887  vstate.weight = itr->weight;
888  vstate.rshares = itr->rshares.value;
889  vstate.percent = itr->vote_percent;
890  vstate.time = itr->last_update;
891 
892  result.push_back(vstate);
893  ++itr;
894  }
895  return result;
896  });
897 }
898 
899 std::vector<account_vote> database_api::get_account_votes(const std::string& voter) const
900 {
901  return my->_db.with_read_lock([&]() {
902  std::vector<account_vote> result;
903 
904  const auto& voter_acnt = my->_db.account_service().get_account(voter);
905  const auto& idx = my->_db.get_index<comment_vote_index>().indices().get<by_voter_comment>();
906 
907  account_id_type aid(voter_acnt.id);
908  auto itr = idx.lower_bound(aid);
909  auto end = idx.upper_bound(aid);
910  while (itr != end)
911  {
912  const auto& vo = my->_db.get(itr->comment);
913  account_vote avote;
914  avote.authorperm = vo.author + "/" + fc::to_string(vo.permlink);
915  avote.weight = itr->weight;
916  avote.rshares = itr->rshares.value;
917  avote.percent = itr->vote_percent;
918  avote.time = itr->last_update;
919  result.push_back(avote);
920  ++itr;
921  }
922  return result;
923  });
924 }
925 
927 // //
928 // Budgets //
929 // //
931 std::vector<budget_api_obj> database_api::get_budgets(const budget_type type, const std::set<std::string>& names) const
932 {
933  return my->_db.with_read_lock([&]() {
934  switch (type)
935  {
936  case budget_type::post:
937  return my->get_budgets(my->_db.post_budget_service(), names);
938  case budget_type::banner:
939  return my->get_budgets(my->_db.banner_budget_service(), names);
940  default:
941  return std::vector<budget_api_obj>();
942  }
943  });
944 }
945 
946 std::set<std::string>
947 database_api::lookup_budget_owners(const budget_type type, const std::string& lower_bound_name, uint32_t limit) const
948 {
949  return my->_db.with_read_lock([&]() {
950  switch (type)
951  {
952  case budget_type::post:
953  return my->lookup_budget_owners(my->_db.post_budget_service(), lower_bound_name, limit);
954  case budget_type::banner:
955  return my->lookup_budget_owners(my->_db.banner_budget_service(), lower_bound_name, limit);
956  default:
957  return std::set<std::string>();
958  }
959  });
960 }
961 
963 // //
964 // Atomic Swap //
965 // //
967 std::vector<atomicswap_contract_api_obj> database_api::get_atomicswap_contracts(const std::string& owner) const
968 {
969  return my->_db.with_read_lock([&]() { return my->get_atomicswap_contracts(owner); });
970 }
971 
972 std::vector<atomicswap_contract_api_obj> database_api_impl::get_atomicswap_contracts(const std::string& owner) const
973 {
974  std::vector<atomicswap_contract_api_obj> results;
975 
976  auto& account_svc = _db.account_service();
977  const chain::account_object& owner_obj = account_svc.get_account(owner);
978 
979  chain::dbs_atomicswap& atomicswap_service = _db.obtain_service<chain::dbs_atomicswap>();
980 
981  auto contracts = atomicswap_service.get_contracts(owner_obj);
982  for (const chain::atomicswap_contract_object& contract : contracts)
983  {
984  results.push_back(atomicswap_contract_api_obj(contract));
985  }
986 
987  return results;
988 }
989 
990 atomicswap_contract_info_api_obj database_api::get_atomicswap_contract(const std::string& from,
991  const std::string& to,
992  const std::string& secret_hash) const
993 {
994  return my->_db.with_read_lock([&]() { return my->get_atomicswap_contract(from, to, secret_hash); });
995 }
996 
997 atomicswap_contract_info_api_obj database_api_impl::get_atomicswap_contract(const std::string& from,
998  const std::string& to,
999  const std::string& secret_hash) const
1000 {
1002 
1003  auto& account_svc = _db.account_service();
1004  const chain::account_object& from_obj = account_svc.get_account(from);
1005  const chain::account_object& to_obj = account_svc.get_account(to);
1006 
1007  chain::dbs_atomicswap& atomicswap_service = _db.obtain_service<chain::dbs_atomicswap>();
1008 
1009  const chain::atomicswap_contract_object& contract = atomicswap_service.get_contract(from_obj, to_obj, secret_hash);
1010 
1011  return atomicswap_contract_info_api_obj(contract);
1012 }
1013 
1014 std::vector<account_name_type> database_api::get_active_witnesses() const
1015 {
1016  return my->_db.with_read_lock([&]() {
1017  const auto& wso = my->_db.obtain_service<chain::dbs_witness_schedule>().get();
1018  size_t n = wso.current_shuffled_witnesses.size();
1019  std::vector<account_name_type> result;
1020  result.reserve(n);
1021  for (size_t i = 0; i < n; i++)
1022  result.push_back(wso.current_shuffled_witnesses[i]);
1023  return result;
1024  });
1025 }
1026 
1027 std::vector<scorumpower_delegation_api_obj>
1028 database_api::get_scorumpower_delegations(const std::string& account, const std::string& from, uint32_t limit) const
1029 {
1030  FC_ASSERT(limit <= get_api_config(API_DATABASE).lookup_limit);
1031 
1032  return my->_db.with_read_lock([&]() {
1033  std::vector<scorumpower_delegation_api_obj> result;
1034  result.reserve(limit);
1035 
1036  const auto& delegation_idx = my->_db.get_index<scorumpower_delegation_index, by_delegation>();
1037  auto itr = delegation_idx.lower_bound(boost::make_tuple(account, from));
1038  while (result.size() < limit && itr != delegation_idx.end() && itr->delegator == account)
1039  {
1040  result.push_back(*itr);
1041  ++itr;
1042  }
1043 
1044  return result;
1045  });
1046 }
1047 
1048 std::vector<scorumpower_delegation_expiration_api_obj> database_api::get_expiring_scorumpower_delegations(
1049  const std::string& account, time_point_sec from, uint32_t limit) const
1050 {
1051  FC_ASSERT(limit <= get_api_config(API_DATABASE).lookup_limit);
1052 
1053  return my->_db.with_read_lock([&]() {
1054  std::vector<scorumpower_delegation_expiration_api_obj> result;
1055  result.reserve(limit);
1056 
1057  const auto& exp_idx = my->_db.get_index<scorumpower_delegation_expiration_index, by_account_expiration>();
1058  auto itr = exp_idx.lower_bound(boost::make_tuple(account, from));
1059  while (result.size() < limit && itr != exp_idx.end() && itr->delegator == account)
1060  {
1061  result.push_back(*itr);
1062  ++itr;
1063  }
1064 
1065  return result;
1066  });
1067 }
1068 
1069 nft_api_obj database_api::get_nft_by_id(int64_t id) const
1070 {
1071  return my->_db.with_read_lock([&]() { return my->_db.get_dba<nft_object>().get_by<by_id>(id); });
1072 }
1073 
1074 nft_api_obj database_api::get_nft_by_name(const account_name_type& name) const
1075 {
1076  return my->_db.with_read_lock([&]() { return my->_db.get_dba<nft_object>().get_by<by_name>(name); });
1077 }
1078 
1079 nft_api_obj database_api::get_nft_by_uuid(const uuid_type& uuid) const
1080 {
1081  return my->_db.with_read_lock([&]() { return my->_db.get_dba<nft_object>().get_by<by_uuid>(uuid); });
1082 }
1083 
1084 std::vector<nft_api_obj> database_api::lookup_nft(int64_t id, uint32_t limit) const
1085 {
1086  return my->_db.with_read_lock([&]() {
1087  FC_ASSERT(limit <= get_api_config(API_DATABASE).lookup_limit);
1088 
1089  const auto& index = my->_db.get_index<nft_index>().indices().get<by_id>();
1090  std::vector<nft_api_obj> result;
1091 
1092  for (auto itr = index.lower_bound(id); limit-- && itr != index.end(); ++itr)
1093  {
1094  result.emplace_back(*itr);
1095  }
1096 
1097  return result;
1098  });
1099 }
1100 
1101 game_round_api_obj database_api::get_game_round_by_uuid(const uuid_type& uuid) const
1102 {
1103  return my->_db.with_read_lock([&]() { return my->_db.get_dba<game_round_object>().get_by<by_uuid>(uuid); });
1104 }
1105 
1106 std::vector<game_round_api_obj> database_api::lookup_game_round(int64_t id, uint32_t limit) const
1107 {
1108  return my->_db.with_read_lock([&]() {
1109  FC_ASSERT(limit <= get_api_config(API_DATABASE).lookup_limit);
1110 
1111  const auto& index = my->_db.get_index<game_round_index>().indices().get<by_id>();
1112  std::vector<game_round_api_obj> result;
1113 
1114  for (auto itr = index.lower_bound(id); limit-- && itr != index.end(); ++itr)
1115  {
1116  result.emplace_back(*itr);
1117  }
1118 
1119  return result;
1120  });
1121 }
1122 
1123 
1124 } // namespace app
1125 } // namespace scorum
std::vector< account_id_type > get_account_references(account_id_type account_id) const
dynamic_global_property_api_obj get_dynamic_global_properties() const
boost::signals2::scoped_connection _block_applied_connection
fc::optional< witness_api_obj > get_witness_by_account(const std::string &account_name) const
std::vector< extended_account > get_accounts(const std::vector< std::string > &names) const
database_api_impl(const scorum::app::api_context &ctx)
advertising_property_api_obj get_advertising_property() const
std::string get_transaction_hex(const signed_transaction &trx) const
std::set< std::string > lookup_budget_owners(BudgetService &budget_service, const std::string &lower_bound_name, uint32_t limit) const
development_committee_api_obj get_development_committee() const
std::set< public_key_type > get_potential_signatures(const signed_transaction &trx) const
std::set< account_name_type > lookup_registration_committee_members(const std::string &lower_bound_name, uint32_t limit) const
atomicswap_contract_info_api_obj get_atomicswap_contract(const std::string &from, const std::string &to, const std::string &secret_hash) const
uint64_t get_account_count() const
std::vector< optional< witness_api_obj > > get_witnesses(const std::vector< witness_id_type > &witness_ids) const
chain_id_type get_chain_id() const
std::set< account_name_type > lookup_witness_accounts(const std::string &lower_bound_name, uint32_t limit) const
std::vector< std::set< std::string > > get_key_references(std::vector< public_key_type > key) const
std::function< void(const fc::variant &)> _block_applied_callback
uint64_t get_witness_count() const
bool verify_authority(const signed_transaction &trx) const
void on_applied_block(const chain::signed_block &b)
bool verify_account_authority(const std::string &name_or_id, const flat_set< public_key_type > &signers) const
registration_committee_api_obj get_registration_committee() const
void set_block_applied_callback(std::function< void(const variant &block_id)> cb)
std::vector< atomicswap_contract_api_obj > get_atomicswap_contracts(const std::string &owner) const
std::set< account_name_type > lookup_development_committee_members(const std::string &lower_bound_name, uint32_t limit) const
std::vector< optional< account_api_obj > > lookup_account_names(const std::vector< std::string > &account_names) const
std::vector< proposal_api_obj > lookup_proposals() const
fc::variant_object get_config() const
std::set< public_key_type > get_required_signatures(const signed_transaction &trx, const flat_set< public_key_type > &available_keys) const
std::set< std::string > lookup_accounts(const std::string &lower_bound_name, uint32_t limit) const
std::vector< budget_api_obj > get_budgets(BudgetService &budget_service, const std::set< std::string > &names) const
scorum::chain::database & _db
database_api(const scorum::app::api_context &ctx)
tracks the blockchain state in an extensible manner
Definition: database.hpp:52
time_point_sec head_block_time() const
Definition: database.cpp:1222
chain_id_type get_chain_id() const
Definition: database.cpp:533
fc::signal< void(const signed_block &)> applied_block
Definition: database.hpp:221
virtual const atomicswap_contract_object & get_contract(const account_object &from, const account_object &to, const std::string &secret_hash) const override
Definition: atomicswap.cpp:48
virtual atomicswap_contracts_refs_type get_contracts() const override
Definition: atomicswap.cpp:22
virtual bool is_exists() const override
#define SCORUM_VOTE_REGENERATION_SECONDS
Definition: config.hpp:191
#define API_DATABASE
Definition: database_api.hpp:3
std::vector< optional< account_api_obj > > lookup_account_names(const std::vector< std::string > &account_names) const
Get a list of accounts by name.
optional< account_bandwidth_api_obj > get_account_bandwidth(const std::string &account, witness::bandwidth_type type) const
optional< account_recovery_request_api_obj > get_recovery_request(const std::string &account) const
std::vector< extended_account > get_accounts(const std::vector< std::string > &names) const
std::set< std::string > lookup_accounts(const std::string &lower_bound_name, uint32_t limit) const
Get names and IDs for registered accounts.
std::vector< std::set< std::string > > get_key_references(std::vector< public_key_type > key) const
std::vector< account_id_type > get_account_references(account_id_type account_id) const
optional< escrow_api_obj > get_escrow(const std::string &from, uint32_t escrow_id) const
uint64_t get_account_count() const
Get the total number of accounts registered with the blockchain.
std::vector< owner_authority_history_api_obj > get_owner_history(const std::string &account) const
std::vector< withdraw_route > get_withdraw_routes(const std::string &account, withdraw_route_type type=outgoing) const
chain_id_type get_chain_id() const
Get the chain ID.
dynamic_global_property_api_obj get_dynamic_global_properties() const
Retrieve the current chain properties.
witness_schedule_api_obj get_witness_schedule() const
Get witness schedule.
fc::variant_object get_config() const
Retrieve compile-time constants.
void set_block_applied_callback(std::function< void(const variant &block_header)> cb)
std::vector< optional< witness_api_obj > > get_witnesses(const std::vector< witness_id_type > &witness_ids) const
Get a list of witnesses by ID.
boost::signals2::scoped_connection connect_signal(boost::signals2::signal< void(Args...)> &sig, C &c, void(C::*f)(Args...))
shared_multi_index_container< proposal_object, indexed_by< ordered_unique< tag< by_id >, member< proposal_object, proposal_id_type, &proposal_object::id > >, ordered_non_unique< tag< by_expiration >, member< proposal_object, fc::time_point_sec, &proposal_object::expiration > >, ordered_non_unique< tag< by_created >, member< proposal_object, fc::time_point_sec, &proposal_object::created > > > > proposal_object_index
bool is_equal_withdrawable_id(const withdrawable_id_type &a, const withdrawable_id_type &b)
shared_multi_index_container< nft_object, indexed_by< ordered_unique< tag< by_id >, member< nft_object, nft_id_type, &nft_object::id > >, hashed_unique< tag< by_uuid >, member< nft_object, uuid_type, &nft_object::uuid > >, hashed_unique< tag< by_name >, member< nft_object, account_name_type, &nft_object::name > > > > nft_index
Definition: nft_object.hpp:59
oid< witness_schedule_object > witness_schedule_id_type
shared_multi_index_container< game_round_object, indexed_by< ordered_unique< tag< by_id >, member< game_round_object, game_round_id_type, &game_round_object::id > >, hashed_unique< tag< by_uuid >, member< game_round_object, uuid_type, &game_round_object::uuid > > > > game_round_index
Definition: nft_object.hpp:65
oid< dev_committee_object > dev_committee_id_type
shared_multi_index_container< withdraw_scorumpower_route_object, indexed_by< ordered_unique< tag< by_id >, member< withdraw_scorumpower_route_object, withdraw_scorumpower_route_id_type, &withdraw_scorumpower_route_object::id > >, ordered_unique< tag< by_withdraw_route >, composite_key< withdraw_scorumpower_route_object, member< withdraw_scorumpower_route_object, withdrawable_id_type, &withdraw_scorumpower_route_object::from_id >, member< withdraw_scorumpower_route_object, withdrawable_id_type, &withdraw_scorumpower_route_object::to_id > >, composite_key_compare< less_for_withdrawable_id, less_for_withdrawable_id > >, ordered_unique< tag< by_destination >, composite_key< withdraw_scorumpower_route_object, member< withdraw_scorumpower_route_object, withdrawable_id_type, &withdraw_scorumpower_route_object::to_id >, member< withdraw_scorumpower_route_object, withdraw_scorumpower_route_id_type, &withdraw_scorumpower_route_object::id > >, composite_key_compare< less_for_withdrawable_id, std::less< withdraw_scorumpower_route_id_type > > > > > withdraw_scorumpower_route_index
shared_multi_index_container< witness_vote_object, indexed_by< ordered_unique< tag< by_id >, member< witness_vote_object, witness_vote_id_type, &witness_vote_object::id > >, ordered_unique< tag< by_account_witness >, composite_key< witness_vote_object, member< witness_vote_object, account_id_type, &witness_vote_object::account >, member< witness_vote_object, witness_id_type, &witness_vote_object::witness > >, composite_key_compare< std::less< account_id_type >, std::less< witness_id_type > > >, ordered_unique< tag< by_witness_account >, composite_key< witness_vote_object, member< witness_vote_object, witness_id_type, &witness_vote_object::witness >, member< witness_vote_object, account_id_type, &witness_vote_object::account > >, composite_key_compare< std::less< witness_id_type >, std::less< account_id_type > > > > > witness_vote_index
shared_multi_index_container< witness_object, indexed_by< ordered_unique< tag< by_id >, member< witness_object, witness_id_type, &witness_object::id > >, ordered_unique< tag< by_name >, member< witness_object, account_name_type, &witness_object::owner > >, ordered_unique< tag< by_vote_name >, composite_key< witness_object, member< witness_object, share_type, &witness_object::votes >, member< witness_object, account_name_type, &witness_object::owner > >, composite_key_compare< std::greater< share_type >, std::less< account_name_type > > >, ordered_unique< tag< by_schedule_time >, composite_key< witness_object, member< witness_object, fc::uint128, &witness_object::virtual_scheduled_time >, member< witness_object, witness_id_type, &witness_object::id > > > > > witness_index
@ post
Rate limiting posting reward eligibility over time.
fc::variant_object get_config()
Definition: get_config.cpp:12
fc::fixed_string_16 account_name_type
Definition: types.hpp:62
fc::sha256 chain_id_type
Definition: types.hpp:61
void verify_authority(const std::vector< operation > &ops, const flat_set< public_key_type > &sigs, const authority_getter &get_active, const authority_getter &get_owner, const authority_getter &get_posting, uint32_t max_recursion=SCORUM_MAX_SIG_CHECK_DEPTH, bool allow_committe=false, const flat_set< account_name_type > &active_aprovals=flat_set< account_name_type >(), const flat_set< account_name_type > &owner_aprovals=flat_set< account_name_type >(), const flat_set< account_name_type > &posting_approvals=flat_set< account_name_type >())
Definition: transaction.cpp:88
shared_multi_index_container< account_bandwidth_object, indexed_by< ordered_unique< tag< by_id >, member< account_bandwidth_object, account_bandwidth_id_type, &account_bandwidth_object::id > >, ordered_unique< tag< by_account_bandwidth_type >, composite_key< account_bandwidth_object, member< account_bandwidth_object, account_name_type, &account_bandwidth_object::account >, member< account_bandwidth_object, bandwidth_type, &account_bandwidth_object::type > > > > > account_bandwidth_index
shared_multi_index_container< reserve_ratio_object, indexed_by< ordered_unique< tag< by_id >, member< reserve_ratio_object, reserve_ratio_id_type, &reserve_ratio_object::id > > > > reserve_ratio_index
Definition: asset.cpp:15
boost::uuids::uuid uuid_type
Definition: types.hpp:53
config_api & get_api_config(std::string api_name)
Definition: config_api.cpp:114
vote_weight_type percent
Definition: state.hpp:27
std::string authorperm
Definition: state.hpp:24
time_point_sec time
Definition: state.hpp:28
std::string voter
Definition: state.hpp:15
vote_weight_type percent
Definition: state.hpp:18
time_point_sec time
Definition: state.hpp:19
void verify_authority(const chain_id_type &chain_id, const authority_getter &get_active, const authority_getter &get_owner, const authority_getter &get_posting, uint32_t max_recursion=SCORUM_MAX_SIG_CHECK_DEPTH) const
std::set< public_key_type > get_required_signatures(const chain_id_type &chain_id, const flat_set< public_key_type > &available_keys, const authority_getter &get_active, const authority_getter &get_owner, const authority_getter &get_posting, uint32_t max_recursion=SCORUM_MAX_SIG_CHECK_DEPTH) const
std::vector< operation > operations
Definition: transaction.hpp:18
Transfers SCR from one account to another.