BitShares-Core  5.0.0
BitShares blockchain implementation and command-line interface software
wallet_voting.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Cryptonomex, Inc., and contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "wallet_api_impl.hpp"
26 
27 /****
28  * Methods to handle voting / workers / committee
29  */
30 
31 namespace graphene { namespace wallet { namespace detail {
32 
33  template<typename WorkerInit>
34  static WorkerInit _create_worker_initializer( const variant& worker_settings )
35  {
36  WorkerInit result;
37  from_variant( worker_settings, result, GRAPHENE_MAX_NESTED_OBJECTS );
38  return result;
39  }
40 
42  string account,
43  worker_vote_delta delta,
44  bool broadcast
45  )
46  {
47  account_object acct = get_account( account );
48 
49  // you could probably use a faster algorithm for this, but flat_set is fast enough :)
50  flat_set< worker_id_type > merged;
51  merged.reserve( delta.vote_for.size() + delta.vote_against.size() + delta.vote_abstain.size() );
52  for( const worker_id_type& wid : delta.vote_for )
53  {
54  bool inserted = merged.insert( wid ).second;
55  FC_ASSERT( inserted, "worker ${wid} specified multiple times", ("wid", wid) );
56  }
57  for( const worker_id_type& wid : delta.vote_against )
58  {
59  bool inserted = merged.insert( wid ).second;
60  FC_ASSERT( inserted, "worker ${wid} specified multiple times", ("wid", wid) );
61  }
62  for( const worker_id_type& wid : delta.vote_abstain )
63  {
64  bool inserted = merged.insert( wid ).second;
65  FC_ASSERT( inserted, "worker ${wid} specified multiple times", ("wid", wid) );
66  }
67 
68  // should be enforced by FC_ASSERT's above
69  assert( merged.size() == delta.vote_for.size() + delta.vote_against.size() + delta.vote_abstain.size() );
70 
71  vector< object_id_type > query_ids;
72  for( const worker_id_type& wid : merged )
73  query_ids.push_back( wid );
74 
75  flat_set<vote_id_type> new_votes( acct.options.votes );
76 
77  fc::variants objects = _remote_db->get_objects( query_ids, {} );
78  for( const variant& obj : objects )
79  {
80  worker_object wo;
82  new_votes.erase( wo.vote_for );
83  new_votes.erase( wo.vote_against );
84  if( delta.vote_for.find( wo.id ) != delta.vote_for.end() )
85  new_votes.insert( wo.vote_for );
86  else if( delta.vote_against.find( wo.id ) != delta.vote_against.end() )
87  new_votes.insert( wo.vote_against );
88  else
89  assert( delta.vote_abstain.find( wo.id ) != delta.vote_abstain.end() );
90  }
91 
92  account_update_operation update_op;
93  update_op.account = acct.id;
94  update_op.new_options = acct.options;
95  update_op.new_options->votes = new_votes;
96 
98  tx.operations.push_back( update_op );
99  set_operation_fees( tx, _remote_db->get_global_properties().parameters.get_current_fees() );
100  tx.validate();
101 
102  return sign_transaction( tx, broadcast );
103  }
104 
106  bool broadcast )
107  { try {
108 
109  committee_member_create_operation committee_member_create_op;
110  committee_member_create_op.committee_member_account = get_account_id(owner_account);
111  committee_member_create_op.url = url;
112  if (_remote_db->get_committee_member_by_account(owner_account))
113  FC_THROW("Account ${owner_account} is already a committee_member", ("owner_account", owner_account));
114 
116  tx.operations.push_back( committee_member_create_op );
117  set_operation_fees( tx, _remote_db->get_global_properties().parameters.get_current_fees());
118  tx.validate();
119 
120  return sign_transaction( tx, broadcast );
121  } FC_CAPTURE_AND_RETHROW( (owner_account)(broadcast) ) }
122 
124  {
125  try
126  {
127  fc::optional<witness_id_type> witness_id = maybe_id<witness_id_type>(owner_account);
128  if (witness_id)
129  {
130  std::vector<witness_id_type> ids_to_get;
131  ids_to_get.push_back(*witness_id);
132  std::vector<fc::optional<witness_object>> witness_objects = _remote_db->get_witnesses(ids_to_get);
133  if (witness_objects.front())
134  return *witness_objects.front();
135  FC_THROW("No witness is registered for id ${id}", ("id", owner_account));
136  }
137  else
138  {
139  // then maybe it's the owner account
140  try
141  {
142  std::string owner_account_id = account_id_to_string(get_account_id(owner_account));
143  fc::optional<witness_object> witness = _remote_db->get_witness_by_account(owner_account_id);
144  if (witness)
145  return *witness;
146  else
147  FC_THROW("No witness is registered for account ${account}", ("account", owner_account));
148  }
149  catch (const fc::exception&)
150  {
151  FC_THROW("No account or witness named ${account}", ("account", owner_account));
152  }
153  }
154  }
155  FC_CAPTURE_AND_RETHROW( (owner_account) )
156  }
157 
159  {
160  try
161  {
162  fc::optional<committee_member_id_type> committee_member_id =
163  maybe_id<committee_member_id_type>(owner_account);
164  if (committee_member_id)
165  {
166  std::vector<committee_member_id_type> ids_to_get;
167  ids_to_get.push_back(*committee_member_id);
168  std::vector<fc::optional<committee_member_object>> committee_member_objects =
169  _remote_db->get_committee_members(ids_to_get);
170  if (committee_member_objects.front())
171  return *committee_member_objects.front();
172  FC_THROW("No committee_member is registered for id ${id}", ("id", owner_account));
173  }
174  else
175  {
176  // then maybe it's the owner account
177  try
178  {
179  fc::optional<committee_member_object> committee_member =
180  _remote_db->get_committee_member_by_account(owner_account);
181  if (committee_member)
182  return *committee_member;
183  else
184  FC_THROW("No committee_member is registered for account ${account}", ("account", owner_account));
185  }
186  catch (const fc::exception&)
187  {
188  FC_THROW("No account or committee_member named ${account}", ("account", owner_account));
189  }
190  }
191  }
192  FC_CAPTURE_AND_RETHROW( (owner_account) )
193  }
194 
196  string url, bool broadcast /* = false */)
197  { try {
198  account_object witness_account = get_account(owner_account);
199  fc::ecc::private_key active_private_key = get_private_key_for_account(witness_account);
200  int witness_key_index = find_first_unused_derived_key_index(active_private_key);
201  fc::ecc::private_key witness_private_key =
202  derive_private_key(key_to_wif(active_private_key), witness_key_index);
203  graphene::chain::public_key_type witness_public_key = witness_private_key.get_public_key();
204 
205  witness_create_operation witness_create_op;
206  witness_create_op.witness_account = witness_account.id;
207  witness_create_op.block_signing_key = witness_public_key;
208  witness_create_op.url = url;
209 
210  if (_remote_db->get_witness_by_account(account_id_to_string(witness_create_op.witness_account)))
211  FC_THROW("Account ${owner_account} is already a witness", ("owner_account", owner_account));
212 
214  tx.operations.push_back( witness_create_op );
215  set_operation_fees( tx, _remote_db->get_global_properties().parameters.get_current_fees());
216  tx.validate();
217 
218  _wallet.pending_witness_registrations[owner_account] = key_to_wif(witness_private_key);
219 
220  return sign_transaction( tx, broadcast );
221  } FC_CAPTURE_AND_RETHROW( (owner_account)(broadcast) ) }
222 
223  signed_transaction wallet_api_impl::update_witness(string witness_name, string url,
224  string block_signing_key, bool broadcast )
225  { try {
226  witness_object witness = get_witness(witness_name);
227  account_object witness_account = get_account( witness.witness_account );
228 
229  witness_update_operation witness_update_op;
230  witness_update_op.witness = witness.id;
231  witness_update_op.witness_account = witness_account.id;
232  if( url != "" )
233  witness_update_op.new_url = url;
234  if( block_signing_key != "" )
235  witness_update_op.new_signing_key = public_key_type( block_signing_key );
236 
238  tx.operations.push_back( witness_update_op );
239  set_operation_fees( tx, _remote_db->get_global_properties().parameters.get_current_fees() );
240  tx.validate();
241 
242  return sign_transaction( tx, broadcast );
243  } FC_CAPTURE_AND_RETHROW( (witness_name)(url)(block_signing_key)(broadcast) ) }
244 
245  signed_transaction wallet_api_impl::create_worker( string owner_account, time_point_sec work_begin_date,
246  time_point_sec work_end_date, share_type daily_pay, string name, string url,
247  variant worker_settings, bool broadcast)
248  {
249  worker_initializer init;
250  std::string wtype = worker_settings["type"].get_string();
251 
252  // TODO: Use introspection to do this dispatch
253  if( wtype == "burn" )
254  init = _create_worker_initializer< burn_worker_initializer >( worker_settings );
255  else if( wtype == "refund" )
256  init = _create_worker_initializer< refund_worker_initializer >( worker_settings );
257  else if( wtype == "vesting" )
258  init = _create_worker_initializer< vesting_balance_worker_initializer >( worker_settings );
259  else
260  {
261  FC_ASSERT( false, "unknown worker[\"type\"] value" );
262  }
263 
265  op.owner = get_account( owner_account ).id;
266  op.work_begin_date = work_begin_date;
267  op.work_end_date = work_end_date;
268  op.daily_pay = daily_pay;
269  op.name = name;
270  op.url = url;
271  op.initializer = init;
272 
274  tx.operations.push_back( op );
275  set_operation_fees( tx, _remote_db->get_global_properties().parameters.get_current_fees() );
276  tx.validate();
277 
278  return sign_transaction( tx, broadcast );
279  }
280 
282  string committee_member, bool approve, bool broadcast )
283  { try {
284  account_object voting_account_object = get_account(voting_account);
285  fc::optional<committee_member_object> committee_member_obj =
286  _remote_db->get_committee_member_by_account(committee_member);
287  if (!committee_member_obj)
288  FC_THROW("Account ${committee_member} is not registered as a committee_member",
289  ("committee_member", committee_member));
290  if (approve)
291  {
292  auto insert_result = voting_account_object.options.votes.insert(committee_member_obj->vote_id);
293  if (!insert_result.second)
294  FC_THROW("Account ${account} was already voting for committee_member ${committee_member}",
295  ("account", voting_account)("committee_member", committee_member));
296  }
297  else
298  {
299  unsigned votes_removed = voting_account_object.options.votes.erase(committee_member_obj->vote_id);
300  if (!votes_removed)
301  FC_THROW("Account ${account} is already not voting for committee_member ${committee_member}",
302  ("account", voting_account)("committee_member", committee_member));
303  }
304  account_update_operation account_update_op;
305  account_update_op.account = voting_account_object.id;
306  account_update_op.new_options = voting_account_object.options;
307 
309  tx.operations.push_back( account_update_op );
310  set_operation_fees( tx, _remote_db->get_global_properties().parameters.get_current_fees());
311  tx.validate();
312 
313  return sign_transaction( tx, broadcast );
314  } FC_CAPTURE_AND_RETHROW( (voting_account)(committee_member)(approve)(broadcast) ) }
315 
316  signed_transaction wallet_api_impl::vote_for_witness(string voting_account, string witness,
317  bool approve, bool broadcast )
318  { try {
319  account_object voting_account_object = get_account(voting_account);
320 
321  fc::optional<witness_object> witness_obj = _remote_db->get_witness_by_account(witness);
322  if (!witness_obj)
323  FC_THROW("Account ${witness} is not registered as a witness", ("witness", witness));
324  if (approve)
325  {
326  auto insert_result = voting_account_object.options.votes.insert(witness_obj->vote_id);
327  if (!insert_result.second)
328  FC_THROW("Account ${account} was already voting for witness ${witness}",
329  ("account", voting_account)("witness", witness));
330  }
331  else
332  {
333  unsigned votes_removed = voting_account_object.options.votes.erase(witness_obj->vote_id);
334  if (!votes_removed)
335  FC_THROW("Account ${account} is already not voting for witness ${witness}",
336  ("account", voting_account)("witness", witness));
337  }
338  account_update_operation account_update_op;
339  account_update_op.account = voting_account_object.id;
340  account_update_op.new_options = voting_account_object.options;
341 
343  tx.operations.push_back( account_update_op );
344  set_operation_fees( tx, _remote_db->get_global_properties().parameters.get_current_fees());
345  tx.validate();
346 
347  return sign_transaction( tx, broadcast );
348  } FC_CAPTURE_AND_RETHROW( (voting_account)(witness)(approve)(broadcast) ) }
349 
351  optional<string> voting_account, bool broadcast )
352  { try {
353  account_object account_object_to_modify = get_account(account_to_modify);
354  if (voting_account)
355  {
356  account_id_type new_voting_account_id = get_account_id(*voting_account);
357  if (account_object_to_modify.options.voting_account == new_voting_account_id)
358  FC_THROW("Voting proxy for ${account} is already set to ${voter}",
359  ("account", account_to_modify)("voter", *voting_account));
360  account_object_to_modify.options.voting_account = new_voting_account_id;
361  }
362  else
363  {
364  if (account_object_to_modify.options.voting_account == GRAPHENE_PROXY_TO_SELF_ACCOUNT)
365  FC_THROW("Account ${account} is already voting for itself", ("account", account_to_modify));
366  account_object_to_modify.options.voting_account = GRAPHENE_PROXY_TO_SELF_ACCOUNT;
367  }
368 
369  account_update_operation account_update_op;
370  account_update_op.account = account_object_to_modify.id;
371  account_update_op.new_options = account_object_to_modify.options;
372 
374  tx.operations.push_back( account_update_op );
375  set_operation_fees( tx, _remote_db->get_global_properties().parameters.get_current_fees());
376  tx.validate();
377 
378  return sign_transaction( tx, broadcast );
379  } FC_CAPTURE_AND_RETHROW( (account_to_modify)(voting_account)(broadcast) ) }
380 
382  string account_to_modify, uint16_t desired_number_of_witnesses, uint16_t desired_number_of_committee_members,
383  bool broadcast )
384  { try {
385  account_object account_object_to_modify = get_account(account_to_modify);
386 
387  if (account_object_to_modify.options.num_witness == desired_number_of_witnesses &&
388  account_object_to_modify.options.num_committee == desired_number_of_committee_members)
389  FC_THROW("Account ${account} is already voting for ${witnesses} witnesses"
390  " and ${committee_members} committee_members",
391  ("account", account_to_modify)("witnesses", desired_number_of_witnesses)
392  ("committee_members",desired_number_of_witnesses));
393  account_object_to_modify.options.num_witness = desired_number_of_witnesses;
394  account_object_to_modify.options.num_committee = desired_number_of_committee_members;
395 
396  account_update_operation account_update_op;
397  account_update_op.account = account_object_to_modify.id;
398  account_update_op.new_options = account_object_to_modify.options;
399 
401  tx.operations.push_back( account_update_op );
402  set_operation_fees( tx, _remote_db->get_global_properties().parameters.get_current_fees());
403  tx.validate();
404 
405  return sign_transaction( tx, broadcast );
406  } FC_CAPTURE_AND_RETHROW( (account_to_modify)(desired_number_of_witnesses)
407  (desired_number_of_committee_members)(broadcast) ) }
408 
410  fc::time_point_sec expiration_time, const variant_object& changed_values, bool broadcast )
411  {
412  FC_ASSERT( !changed_values.contains("current_fees") );
413 
414  const chain_parameters& current_params = get_global_properties().parameters;
415  chain_parameters new_params = current_params;
418  );
419 
421  update_op.new_parameters = new_params;
422 
424 
425  prop_op.expiration_time = expiration_time;
426  prop_op.review_period_seconds = current_params.committee_proposal_review_period;
427  prop_op.fee_paying_account = get_account(proposing_account).id;
428 
429  prop_op.proposed_ops.emplace_back( update_op );
430  current_params.get_current_fees().set_fee( prop_op.proposed_ops.back().op );
431 
433  tx.operations.push_back(prop_op);
434  set_operation_fees(tx, current_params.get_current_fees());
435  tx.validate();
436 
437  return sign_transaction(tx, broadcast);
438  }
439 
440  signed_transaction wallet_api_impl::propose_fee_change( const string& proposing_account,
441  fc::time_point_sec expiration_time, const variant_object& changed_fees, bool broadcast )
442  {
443  const chain_parameters& current_params = get_global_properties().parameters;
444  const fee_schedule_type& current_fees = current_params.get_current_fees();
445 
446  flat_map< int, fee_parameters > fee_map;
447  fee_map.reserve( current_fees.parameters.size() );
448  for( const fee_parameters& op_fee : current_fees.parameters )
449  fee_map[ op_fee.which() ] = op_fee;
450  uint32_t scale = current_fees.scale;
451 
452  for( const auto& item : changed_fees )
453  {
454  const string& key = item.key();
455  if( key == "scale" )
456  {
457  int64_t _scale = item.value().as_int64();
458  FC_ASSERT( _scale >= 0 );
459  FC_ASSERT( _scale <= std::numeric_limits<uint32_t>::max() );
460  scale = uint32_t( _scale );
461  continue;
462  }
463  // is key a number?
464  auto is_numeric = [&key]() -> bool
465  {
466  size_t n = key.size();
467  for( size_t i=0; i<n; i++ )
468  {
469  if( !isdigit( key[i] ) )
470  return false;
471  }
472  return true;
473  };
474 
475  int which;
476  if( is_numeric() )
477  which = std::stoi( key );
478  else
479  {
480  const auto& n2w = _operation_which_map.name_to_which;
481  auto it = n2w.find( key );
482  FC_ASSERT( it != n2w.end(), "unknown operation" );
483  which = it->second;
484  }
485 
486  fee_parameters fp = from_which_variant< fee_parameters >( which, item.value(), GRAPHENE_MAX_NESTED_OBJECTS );
487  fee_map[ which ] = fp;
488  }
489 
490  fee_schedule_type new_fees;
491 
492  for( const std::pair< int, fee_parameters >& item : fee_map )
493  new_fees.parameters.insert( item.second );
494  new_fees.scale = scale;
495 
496  chain_parameters new_params = current_params;
497  new_params.get_mutable_fees() = new_fees;
498 
500  update_op.new_parameters = new_params;
501 
503 
504  prop_op.expiration_time = expiration_time;
506  prop_op.fee_paying_account = get_account(proposing_account).id;
507 
508  prop_op.proposed_ops.emplace_back( update_op );
509  current_params.get_current_fees().set_fee( prop_op.proposed_ops.back().op );
510 
512  tx.operations.push_back(prop_op);
513  set_operation_fees(tx, current_params.get_current_fees());
514  tx.validate();
515 
516  return sign_transaction(tx, broadcast);
517  }
518 
519 }}} // namespace graphene::wallet::detail
flat_set< worker_id_type > vote_for
Create a committee_member object, as a bid to hold a committee_member seat on the network...
const std::string & get_string() const
Definition: variant.cpp:575
signed_transaction update_witness(string witness_name, string url, string block_signing_key, bool broadcast)
account_id_type get_account_id(string account_name_or_id) const
witness_id_type witness
The witness object to update.
Definition: witness.hpp:64
signed_transaction propose_parameter_change(const string &proposing_account, fc::time_point_sec expiration_time, const variant_object &changed_values, bool broadcast=false)
vector< operation > operations
Definition: transaction.hpp:89
#define GRAPHENE_MAX_NESTED_OBJECTS
Definition: config.hpp:31
virtual void validate() const
Definition: transaction.cpp:58
contains all of the parameters necessary to calculate the fee for any operation
This class represents an account on the object graphAccounts are the primary unit of authority on the...
global_property_object get_global_properties() const
Definition: api.cpp:56
signed_transaction set_voting_proxy(string account_to_modify, optional< string > voting_account, bool broadcast)
Create a witness object, as a bid to hold a witness position on the network.Accounts which wish to be...
Definition: witness.hpp:37
Update an existing account.
Definition: account.hpp:135
#define GRAPHENE_PROXY_TO_SELF_ACCOUNT
Represents the canonical account for specifying you will vote directly (as opposed to a proxy) ...
Definition: config.hpp:135
Used to generate a useful error report when an exception is thrown.At each level in the stack where t...
Definition: exception.hpp:56
std::vector< variant > variants
Definition: variant.hpp:170
signed_transaction create_committee_member(string owner_account, string url, bool broadcast)
transform_to_fee_parameters< operation >::type fee_parameters
#define FC_THROW(...)
Definition: exception.hpp:366
optional< account_options > new_options
New account options.
Definition: account.hpp:160
account_object get_account(account_id_type id) const
uint32_t committee_proposal_review_period
minimum time in seconds that a proposed transaction requiring committee authority may not be signed...
signed_transaction create_worker(string owner_account, time_point_sec work_begin_date, time_point_sec work_end_date, share_type daily_pay, string name, string url, variant worker_settings, bool broadcast)
fc::ecc::private_key get_private_key_for_account(const account_object &account) const
map< string, string > pending_witness_registrations
optional< public_key_type > new_signing_key
The new block signing key.
Definition: witness.hpp:70
public_key get_public_key() const
The proposal_create_operation creates a transaction proposal, for use in multi-sig scenariosCreates a...
Definition: proposal.hpp:70
const fee_schedule & get_current_fees() const
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
std::string key_to_wif(const fc::sha256 &private_secret)
flat_set< worker_id_type > vote_abstain
account_id_type committee_member_account
The account which owns the committee_member. This account pays the fee for this operation.
fc::ecc::private_key derive_private_key(const std::string &prefix_string, int sequence_number)
Definition: wallet_sign.cpp:54
object_id_type id
Definition: object.hpp:69
optional< string > new_url
The new URL.
Definition: witness.hpp:68
flat_set< vote_id_type > votes
Definition: account.hpp:58
defines visit functions for T Unless this is specialized, visit() will not be defined for T...
Definition: reflect.hpp:25
signed_transaction sign_transaction(signed_transaction tx, bool broadcast=false)
signed_transaction propose_fee_change(const string &proposing_account, fc::time_point_sec expiration_time, const variant_object &changed_fees, bool broadcast=false)
flat_set< worker_id_type > vote_against
Update a witness object&#39;s URL and block signing key.
Definition: witness.hpp:55
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:478
worker_initializer initializer
This should be set to the initializer appropriate for the type of worker to be created.
Definition: worker.hpp:90
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
adds a signature to a transaction
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object&#39;s.
Definition: variant.hpp:198
account_id_type witness_account
The account which owns the witness. This account pays the fee for this operation. ...
Definition: witness.hpp:43
signed_transaction update_worker_votes(string account, worker_vote_delta delta, bool broadcast)
witness_object get_witness(string owner_account)
signed_transaction set_desired_witness_and_committee_member_count(string account_to_modify, uint16_t desired_number_of_witnesses, uint16_t desired_number_of_committee_members, bool broadcast)
account_id_type account
The account to update.
Definition: account.hpp:152
signed_transaction vote_for_witness(string voting_account, string witness, bool approve, bool broadcast)
void from_variant(const variant &var, flat_set< T, A... > &vo, uint32_t _max_depth)
Definition: flat.hpp:116
flat_map< string, int > name_to_which
vote_id_type vote_against
Voting ID which represents disapproval of this worker.
Worker object contains the details of a blockchain worker. See The Blockchain Worker System for detai...
vote_id_type vote_for
Voting ID which represents approval of this worker.
account_id_type witness_account
The account which owns the witness. This account pays the fee for this operation. ...
Definition: witness.hpp:66
committee_member_object get_committee_member(string owner_account)
asset set_fee(operation &op, const price &core_exchange_rate=price::unit_price()) const
Used by committee_members to update the global parameters of the blockchain.This operation allows the...
an elliptic curve private key.
Definition: elliptic.hpp:89
signed_transaction vote_for_committee_member(string voting_account, string committee_member, bool approve, bool broadcast)
tracks information about a committee_member account.A committee_member is responsible for setting blo...
void set_operation_fees(signed_transaction &tx, const fee_schedule &s)
signed_transaction create_witness(string owner_account, string url, bool broadcast)
uint32_t scale
fee * scale / GRAPHENE_100_PERCENT
Create a new worker object.
Definition: worker.hpp:78
fee_parameters::flat_set_type parameters