Scorum
account_by_key_plugin.cpp
Go to the documentation of this file.
4 
8 
9 #include <graphene/schema/schema.hpp>
10 #include <graphene/schema/schema_impl.hpp>
11 
12 namespace scorum {
13 namespace account_by_key {
14 
15 namespace detail {
16 
18 {
19 public:
21  : _self(_plugin)
22  {
23  }
24 
26  {
27  return _self.database();
28  }
29 
30  void pre_operation(const operation_notification& op_obj);
31  void post_operation(const operation_notification& op_obj);
32  void clear_cache();
33  void cache_auths(const account_authority_object& a);
34  void update_key_lookup(const account_authority_object& a);
35 
36  flat_set<public_key_type> cached_keys;
38 };
39 
41 {
43 
45  : _plugin(plugin)
46  {
47  }
48 
49  template <typename T> void operator()(const T&) const
50  {
51  }
52 
53  void operator()(const account_create_operation& op) const
54  {
55  _plugin.my->clear_cache();
56  }
57 
59  {
60  _plugin.my->clear_cache();
61  }
62 
64  {
65  _plugin.my->clear_cache();
66  }
67 
68  void operator()(const account_update_operation& op) const
69  {
70  _plugin.my->clear_cache();
71  auto acct_itr = _plugin.database().find<account_authority_object, by_account>(op.account);
72  if (acct_itr)
73  _plugin.my->cache_auths(*acct_itr);
74  }
75 
76  void operator()(const recover_account_operation& op) const
77  {
78  _plugin.my->clear_cache();
79  auto acct_itr = _plugin.database().find<account_authority_object, by_account>(op.account_to_recover);
80  if (acct_itr)
81  _plugin.my->cache_auths(*acct_itr);
82  }
83 };
84 
86 {
88 
89  template <typename WorkType> result_type operator()(const WorkType& work) const
90  {
91  return &work.input.worker_account;
92  }
93 };
94 
96 {
98 
100  : _plugin(plugin)
101  {
102  }
103 
104  template <typename T> void operator()(const T&) const
105  {
106  }
107 
108  void operator()(const account_create_operation& op) const
109  {
110  auto acct_itr = _plugin.database().find<account_authority_object, by_account>(op.new_account_name);
111  if (acct_itr)
112  _plugin.my->update_key_lookup(*acct_itr);
113  }
114 
116  {
117  auto acct_itr = _plugin.database().find<account_authority_object, by_account>(op.new_account_name);
118  if (acct_itr)
119  _plugin.my->update_key_lookup(*acct_itr);
120  }
121 
123  {
124  auto acct_itr = _plugin.database().find<account_authority_object, by_account>(op.new_account_name);
125  if (acct_itr)
126  _plugin.my->update_key_lookup(*acct_itr);
127  }
128 
129  void operator()(const account_update_operation& op) const
130  {
131  auto acct_itr = _plugin.database().find<account_authority_object, by_account>(op.account);
132  if (acct_itr)
133  _plugin.my->update_key_lookup(*acct_itr);
134  }
135 
136  void operator()(const recover_account_operation& op) const
137  {
138  auto acct_itr = _plugin.database().find<account_authority_object, by_account>(op.account_to_recover);
139  if (acct_itr)
140  _plugin.my->update_key_lookup(*acct_itr);
141  }
142 
143  void operator()(const hardfork_operation& op) const
144  {
145  // removed due to hardfork removal
146  }
147 };
148 
150 {
151  cached_keys.clear();
152 }
153 
154 void account_by_key_plugin_impl::cache_auths(const account_authority_object& a)
155 {
156  for (const auto& item : a.owner.key_auths)
157  cached_keys.insert(item.first);
158  for (const auto& item : a.active.key_auths)
159  cached_keys.insert(item.first);
160  for (const auto& item : a.posting.key_auths)
161  cached_keys.insert(item.first);
162 }
163 
164 void account_by_key_plugin_impl::update_key_lookup(const account_authority_object& a)
165 {
166  auto& db = database();
167  flat_set<public_key_type> new_keys;
168 
169  // Construct the set of keys in the account's authority
170  for (const auto& item : a.owner.key_auths)
171  new_keys.insert(item.first);
172  for (const auto& item : a.active.key_auths)
173  new_keys.insert(item.first);
174  for (const auto& item : a.posting.key_auths)
175  new_keys.insert(item.first);
176 
177  // For each key that needs a lookup
178  for (const auto& key : new_keys)
179  {
180  // If the key was not in the authority, add it to the lookup
181  if (cached_keys.find(key) == cached_keys.end())
182  {
183  auto lookup_itr = db.find<key_lookup_object, by_key>(std::make_tuple(key, a.account));
184 
185  if (lookup_itr == nullptr)
186  {
187  db.create<key_lookup_object>([&](key_lookup_object& o) {
188  o.key = key;
189  o.account = a.account;
190  });
191  }
192  }
193  else
194  {
195  // If the key was already in the auths, remove it from the set so we don't delete it
196  cached_keys.erase(key);
197  }
198  }
199 
200  // Loop over the keys that were in authority but are no longer and remove them from the lookup
201  for (const auto& key : cached_keys)
202  {
203  auto lookup_itr = db.find<key_lookup_object, by_key>(std::make_tuple(key, a.account));
204 
205  if (lookup_itr != nullptr)
206  {
207  db.remove(*lookup_itr);
208  }
209  }
210 
211  cached_keys.clear();
212 }
213 
215 {
216  note.op.visit(pre_operation_visitor(_self));
217 }
218 
220 {
221  note.op.visit(post_operation_visitor(_self));
222 }
223 
224 } // detail
225 
227  : plugin(app)
228  , my(new detail::account_by_key_plugin_impl(*this))
229 {
230 }
231 
232 void account_by_key_plugin::plugin_set_program_options(boost::program_options::options_description& cli,
233  boost::program_options::options_description& cfg)
234 {
235 }
236 
237 void account_by_key_plugin::plugin_initialize(const boost::program_options::variables_map& options)
238 {
239  try
240  {
241  chain::database& db = database();
242 
243  db.pre_apply_operation.connect([&](const operation_notification& o) { my->pre_operation(o); });
244  db.post_apply_operation.connect([&](const operation_notification& o) { my->post_operation(o); });
245 
247  }
248  FC_CAPTURE_AND_RETHROW()
249  print_greeting();
250 }
251 
253 {
254  app().register_api_factory<account_by_key_api>("account_by_key_api");
255 
256  chain::database& db = database();
257 
258  auto it_pair = db.get_index<account_index>().indices().get<by_created_by_genesis>().equal_range(true);
259  auto it = it_pair.first;
260  const auto it_end = it_pair.second;
261  while (it != it_end)
262  {
263  auto it_2_pair = db.get_index<account_authority_index>().indices().get<by_account>().equal_range(it->name);
264  auto it_2 = it_2_pair.first;
265  const auto it_2_end = it_2_pair.second;
266  while (it_2 != it_2_end)
267  {
268  my->update_key_lookup(*it_2);
269  ++it_2;
270  }
271  ++it;
272  }
273 }
274 }
275 } // scorum::account_by_key
276 
std::unique_ptr< detail::account_by_key_plugin_impl > my
virtual void plugin_set_program_options(boost::program_options::options_description &cli, boost::program_options::options_description &cfg) override
Fill in command line parameters used by the plugin.
virtual void plugin_startup() override
Begin normal runtime operations.
virtual void plugin_initialize(const boost::program_options::variables_map &options) override
Perform early startup routines and register plugin indexes, callbacks, etc.
void pre_operation(const operation_notification &op_obj)
void post_operation(const operation_notification &op_obj)
void register_api_factory(const std::string &name, std::function< fc::api_ptr(const api_context &)> factory)
application & app() const
Definition: plugin.hpp:119
void print_greeting()
Definition: plugin.cpp:69
chain::database & database()
Definition: plugin.hpp:115
tracks the blockchain state in an extensible manner
Definition: database.hpp:52
fc::signal< void(const operation_notification &)> post_apply_operation
Definition: database.hpp:210
fc::signal< void(const operation_notification &)> pre_apply_operation
Definition: database.hpp:209
shared_multi_index_container< key_lookup_object, indexed_by< ordered_unique< tag< by_id >, member< key_lookup_object, key_lookup_id_type, &key_lookup_object::id > >, ordered_unique< tag< by_key >, composite_key< key_lookup_object, member< key_lookup_object, public_key_type, &key_lookup_object::key >, member< key_lookup_object, account_name_type, &key_lookup_object::account > > > > > key_lookup_index
fc::fixed_string_16 account_name_type
Definition: types.hpp:62
Definition: asset.cpp:15
#define SCORUM_DEFINE_PLUGIN(plugin_name, plugin_class)
Definition: plugin.hpp:156
void operator()(const account_create_by_committee_operation &op) const
void operator()(const recover_account_operation &op) const
void operator()(const account_create_operation &op) const
void operator()(const account_update_operation &op) const
void operator()(const account_create_with_delegation_operation &op) const
void operator()(const recover_account_operation &op) const
void operator()(const account_create_by_committee_operation &op) const
void operator()(const account_create_with_delegation_operation &op) const
void operator()(const account_update_operation &op) const
void operator()(const account_create_operation &op) const
Creates new account by registration committee.
Updates account keys or/and metadata.
Recovers an account to a new authority using a previous authority.
account_name_type account_to_recover
The account to be recovered.