BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
account_object.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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  */
26 
27 #include <fc/io/raw.hpp>
28 #include <fc/uint128.hpp>
29 
30 namespace graphene { namespace chain {
31 
33 {
34  if( a == 0 || p == 0 )
35  return 0;
36  if( p == GRAPHENE_100_PERCENT )
37  return a;
38 
39  fc::uint128_t r = a.value;
40  r *= p;
42  return static_cast<uint64_t>(r);
43 }
44 
46 {
47  assert(delta.asset_id == asset_type);
48  balance += delta.amount;
49  if( asset_type == asset_id_type() ) // CORE asset
50  maintenance_flag = true;
51 }
52 
54 {
55  if( pending_fees > 0 || pending_vested_fees > 0 )
56  {
57  auto pay_out_fees = [&](const account_object& account, share_type core_fee_total, bool require_vesting)
58  {
59  // Check the referrer -- if he's no longer a member, pay to the lifetime referrer instead.
60  // No need to check the registrar; registrars are required to be lifetime members.
61  if( account.referrer(d).is_basic_account(d.head_block_time()) )
62  d.modify( account, [](account_object& acc) {
63  acc.referrer = acc.lifetime_referrer;
64  });
65 
66  share_type network_cut = cut_fee(core_fee_total, account.network_fee_percentage);
67  assert( network_cut <= core_fee_total );
68 
69  share_type lifetime_cut = cut_fee(core_fee_total, account.lifetime_referrer_fee_percentage);
70  share_type referral = core_fee_total - network_cut - lifetime_cut;
71 
72  d.modify( d.get_core_dynamic_data(), [network_cut](asset_dynamic_data_object& addo) {
73  addo.accumulated_fees += network_cut;
74  });
75 
76  // Potential optimization: Skip some of this math and object lookups by special casing on the account type.
77  // For example, if the account is a lifetime member, we can skip all this and just deposit the referral to
78  // it directly.
79  share_type referrer_cut = cut_fee(referral, account.referrer_rewards_percentage);
80  share_type registrar_cut = referral - referrer_cut;
81 
82  d.deposit_cashback(d.get(account.lifetime_referrer), lifetime_cut, require_vesting);
83  d.deposit_cashback(d.get(account.referrer), referrer_cut, require_vesting);
84  d.deposit_cashback(d.get(account.registrar), registrar_cut, require_vesting);
85 
86  assert( referrer_cut + registrar_cut + network_cut + lifetime_cut == core_fee_total );
87  };
88 
89  pay_out_fees(a, pending_fees, true);
90  pay_out_fees(a, pending_vested_fees, false);
91 
92  d.modify(*this, [&](account_statistics_object& s) {
94  s.pending_fees = 0;
95  s.pending_vested_fees = 0;
96  });
97  }
98 }
99 
100 void account_statistics_object::pay_fee( share_type core_fee, share_type cashback_vesting_threshold )
101 {
102  if( core_fee > cashback_vesting_threshold )
103  pending_fees += core_fee;
104  else
105  pending_vested_fees += core_fee;
106 }
107 
109 {
110  set<account_id_type> result;
111  for( auto auth : a.owner.account_auths )
112  result.insert(auth.first);
113  for( auto auth : a.active.account_auths )
114  result.insert(auth.first);
115  return result;
116 }
117 set<public_key_type, pubkey_comparator> account_member_index::get_key_members(const account_object& a)const
118 {
119  set<public_key_type, pubkey_comparator> result;
120  for( auto auth : a.owner.key_auths )
121  result.insert(auth.first);
122  for( auto auth : a.active.key_auths )
123  result.insert(auth.first);
124  result.insert( a.options.memo_key );
125  return result;
126 }
128 {
129  set<address> result;
130  for( auto auth : a.owner.address_auths )
131  result.insert(auth.first);
132  for( auto auth : a.active.address_auths )
133  result.insert(auth.first);
134  return result;
135 }
136 
138 {
139  assert( dynamic_cast<const account_object*>(&obj) ); // for debug only
140  const account_object& a = static_cast<const account_object&>(obj);
141  const account_id_type account_id = a.get_id();
142 
143  auto account_members = get_account_members(a);
144  for( auto item : account_members )
145  account_to_account_memberships[item].insert(account_id);
146 
147  auto key_members = get_key_members(a);
148  for( auto item : key_members )
149  account_to_key_memberships[item].insert(account_id);
150 
151  auto address_members = get_address_members(a);
152  for( auto item : address_members )
153  account_to_address_memberships[item].insert(account_id);
154 }
155 
157 {
158  assert( dynamic_cast<const account_object*>(&obj) ); // for debug only
159  const account_object& a = static_cast<const account_object&>(obj);
160  const account_id_type account_id = a.get_id();
161 
162  auto key_members = get_key_members(a);
163  for( auto item : key_members )
164  account_to_key_memberships[item].erase( account_id );
165 
166  auto address_members = get_address_members(a);
167  for( auto item : address_members )
168  account_to_address_memberships[item].erase( account_id );
169 
170  auto account_members = get_account_members(a);
171  for( auto item : account_members )
172  account_to_account_memberships[item].erase( account_id );
173 }
174 
175 void account_member_index::about_to_modify(const object& before)
176 {
177  before_key_members.clear();
178  before_account_members.clear();
179  assert( dynamic_cast<const account_object*>(&before) ); // for debug only
180  const account_object& a = static_cast<const account_object&>(before);
184 }
185 
186 void account_member_index::object_modified(const object& after)
187 {
188  assert( dynamic_cast<const account_object*>(&after) ); // for debug only
189  const account_object& a = static_cast<const account_object&>(after);
190  const account_id_type account_id = a.get_id();
191 
192  {
193  set<account_id_type> after_account_members = get_account_members(a);
194  vector<account_id_type> removed;
195  removed.reserve(before_account_members.size());
196  std::set_difference(before_account_members.begin(), before_account_members.end(),
197  after_account_members.begin(), after_account_members.end(),
198  std::inserter(removed, removed.end()));
199 
200  for( auto itr = removed.begin(); itr != removed.end(); ++itr )
201  account_to_account_memberships[*itr].erase(account_id);
202 
203  vector<account_id_type> added;
204  added.reserve(after_account_members.size());
205  std::set_difference(after_account_members.begin(), after_account_members.end(),
207  std::inserter(added, added.end()));
208 
209  for( auto itr = added.begin(); itr != added.end(); ++itr )
210  account_to_account_memberships[*itr].insert(account_id);
211  }
212 
213 
214  {
215  set<public_key_type, pubkey_comparator> after_key_members = get_key_members(a);
216 
217  vector<public_key_type> removed;
218  removed.reserve(before_key_members.size());
219  std::set_difference(before_key_members.begin(), before_key_members.end(),
220  after_key_members.begin(), after_key_members.end(),
221  std::inserter(removed, removed.end()));
222 
223  for( auto itr = removed.begin(); itr != removed.end(); ++itr )
224  account_to_key_memberships[*itr].erase(account_id);
225 
226  vector<public_key_type> added;
227  added.reserve(after_key_members.size());
228  std::set_difference(after_key_members.begin(), after_key_members.end(),
229  before_key_members.begin(), before_key_members.end(),
230  std::inserter(added, added.end()));
231 
232  for( auto itr = added.begin(); itr != added.end(); ++itr )
233  account_to_key_memberships[*itr].insert(account_id);
234  }
235 
236  {
237  set<address> after_address_members = get_address_members(a);
238 
239  vector<address> removed;
240  removed.reserve(before_address_members.size());
241  std::set_difference(before_address_members.begin(), before_address_members.end(),
242  after_address_members.begin(), after_address_members.end(),
243  std::inserter(removed, removed.end()));
244 
245  for( auto itr = removed.begin(); itr != removed.end(); ++itr )
246  account_to_address_memberships[*itr].erase(account_id);
247 
248  vector<address> added;
249  added.reserve(after_address_members.size());
250  std::set_difference(after_address_members.begin(), after_address_members.end(),
252  std::inserter(added, added.end()));
253 
254  for( auto itr = added.begin(); itr != added.end(); ++itr )
255  account_to_address_memberships[*itr].insert(account_id);
256  }
257 
258 }
259 
260 const uint8_t balances_by_account_index::bits = 20;
261 const uint64_t balances_by_account_index::mask = (1ULL << balances_by_account_index::bits) - 1;
262 
264 {
265  const auto& abo = dynamic_cast< const account_balance_object& >( obj );
266  while( balances.size() < (abo.owner.instance.value >> bits) + 1 )
267  {
268  balances.reserve( (abo.owner.instance.value >> bits) + 1 );
269  balances.resize( balances.size() + 1 );
270  balances.back().resize( 1ULL << bits );
271  }
272  balances[abo.owner.instance.value >> bits][abo.owner.instance.value & mask][abo.asset_type] = &abo;
273 }
274 
276 {
277  const auto& abo = dynamic_cast< const account_balance_object& >( obj );
278  if( balances.size() < (abo.owner.instance.value >> bits) + 1 ) return;
279  balances[abo.owner.instance.value >> bits][abo.owner.instance.value & mask].erase( abo.asset_type );
280 }
281 
282 void balances_by_account_index::about_to_modify( const object& before )
283 {
284  ids_being_modified.emplace( before.id );
285 }
286 
288 {
289  FC_ASSERT( ids_being_modified.top() == after.id, "Modification of ID is not supported!");
290  ids_being_modified.pop();
291 }
292 
293 const map< asset_id_type, const account_balance_object* >& balances_by_account_index::get_account_balances( const account_id_type& acct )const
294 {
295  static const map< asset_id_type, const account_balance_object* > _empty;
296 
297  if( balances.size() < (acct.instance.value >> bits) + 1 ) return _empty;
298  return balances[acct.instance.value >> bits][acct.instance.value & mask];
299 }
300 
301 const account_balance_object* balances_by_account_index::get_account_balance( const account_id_type& acct, const asset_id_type& asset )const
302 {
303  if( balances.size() < (acct.instance.value >> bits) + 1 ) return nullptr;
304  const auto& mine = balances[acct.instance.value >> bits][acct.instance.value & mask];
305  const auto itr = mine.find( asset );
306  if( mine.end() == itr ) return nullptr;
307  return itr->second;
308 }
309 
310 } } // graphene::chain
311 
314  (membership_expiration_date)(registrar)(referrer)(lifetime_referrer)
315  (network_fee_percentage)(lifetime_referrer_fee_percentage)(referrer_rewards_percentage)
316  (name)(owner)(active)(options)(num_committee_voted)(statistics)
317  (whitelisting_accounts)(blacklisting_accounts)
318  (whitelisted_accounts)(blacklisted_accounts)
319  (cashback_vb)
320  (owner_special_authority)(active_special_authority)
321  (top_n_control_flags)
322  (allowed_assets)
323  (creation_block_num)(creation_time)
324  )
325 
328  (owner)(asset_type)(balance)(maintenance_flag) )
329 
332  (owner)(name)
333  (most_recent_op)
334  (total_ops)(removed_ops)
335  (total_core_in_orders)
336  (total_core_inactive)(total_core_pob)(total_core_pol)
337  (total_pob_value)(total_pol_value)
338  (core_in_balance)
339  (has_cashback_vb)
340  (is_voting)
341  (last_vote_time)
342  (vp_all)(vp_active)(vp_committee)(vp_witness)(vp_worker)
343  (vote_tally_time)
344  (lifetime_fees_paid)
345  (pending_fees)(pending_vested_fees)
346  )
347 
uint128.hpp
graphene::db::object::id
object_id_type id
Definition: object.hpp:69
graphene::chain::database
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
graphene::chain::account_statistics_object::process_fees
void process_fees(const account_object &a, database &d) const
Split up and pay out pending_fees and pending_vested_fees.
Definition: account_object.cpp:53
graphene::chain::database::head_block_time
time_point_sec head_block_time() const
Definition: db_getter.cpp:67
graphene::chain::balances_by_account_index::get_account_balance
const account_balance_object * get_account_balance(const account_id_type &acct, const asset_id_type &asset) const
Definition: account_object.cpp:301
graphene::chain::account_member_index::get_account_members
set< account_id_type > get_account_members(const account_object &a) const
Definition: account_object.cpp:108
graphene::chain::account_object::lifetime_referrer
account_id_type lifetime_referrer
The lifetime member at the top of the referral tree. Receives a percentage of referral rewards.
Definition: account_object.hpp:198
graphene::db::object_database::get
const T & get(const object_id_type &id) const
Definition: object_database.hpp:119
database.hpp
graphene::protocol::authority::address_auths
flat_map< address, weight_type > address_auths
Definition: authority.hpp:123
graphene::chain::account_member_index::object_inserted
virtual void object_inserted(const object &obj) override
Definition: account_object.cpp:137
graphene::chain::account_object::active
authority active
Definition: account_object.hpp:220
graphene::chain::account_balance_object::adjust_balance
void adjust_balance(const asset &delta)
Definition: account_object.cpp:45
graphene::chain::account_member_index::get_address_members
set< address > get_address_members(const account_object &a) const
Definition: account_object.cpp:127
graphene::protocol::authority::key_auths
flat_map< public_key_type, weight_type > key_auths
Definition: authority.hpp:121
graphene::chain::balances_by_account_index::get_account_balances
const map< asset_id_type, const account_balance_object * > & get_account_balances(const account_id_type &acct) const
Definition: account_object.cpp:293
graphene::chain::balances_by_account_index::object_inserted
virtual void object_inserted(const object &obj) override
Definition: account_object.cpp:263
graphene::chain::balances_by_account_index::object_modified
virtual void object_modified(const object &after) override
Definition: account_object.cpp:287
graphene::chain::account_object::registrar
account_id_type registrar
The account that paid the fee to register this account. Receives a percentage of referral rewards.
Definition: account_object.hpp:194
graphene::chain::account_balance_object
Tracks the balance of a single account/asset pair.
Definition: account_object.hpp:157
graphene::chain::account_object::network_fee_percentage
uint16_t network_fee_percentage
Percentage of fee which should go to network.
Definition: account_object.hpp:201
GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION
#define GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION(type)
Definition: types.hpp:86
graphene::chain::account_statistics_object::lifetime_fees_paid
share_type lifetime_fees_paid
Definition: account_object.hpp:118
graphene::protocol::authority::account_auths
flat_map< account_id_type, weight_type > account_auths
Definition: authority.hpp:120
graphene::chain::account_statistics_object
Definition: account_object.hpp:46
graphene::chain::account_balance_object::balance
share_type balance
Definition: account_object.hpp:163
graphene::chain::account_object::options
account_options options
Definition: account_object.hpp:222
graphene::chain::asset_dynamic_data_object
tracks the asset information that changes frequently
Definition: asset_object.hpp:56
graphene::chain::database::get_core_dynamic_data
const asset_dynamic_data_object & get_core_dynamic_data() const
Definition: db_getter.cpp:42
graphene::chain::account_object
This class represents an account on the object graph.
Definition: account_object.hpp:180
graphene::chain::account_member_index::object_modified
virtual void object_modified(const object &after) override
Definition: account_object.cpp:186
graphene::protocol::asset::asset_id
asset_id_type asset_id
Definition: asset.hpp:37
account_object.hpp
graphene::protocol::account_options::memo_key
public_key_type memo_key
Definition: account.hpp:44
graphene::chain::account_statistics_object::pending_fees
share_type pending_fees
Definition: account_object.hpp:128
graphene::chain::account_member_index::account_to_address_memberships
map< address, set< account_id_type > > account_to_address_memberships
Definition: account_object.hpp:343
graphene::chain::account_member_index::about_to_modify
virtual void about_to_modify(const object &before) override
Definition: account_object.cpp:175
FC_REFLECT_DERIVED_NO_TYPENAME
#define FC_REFLECT_DERIVED_NO_TYPENAME(TYPE, INHERITS, MEMBERS)
Definition: reflect.hpp:357
graphene::chain::account_object::owner
authority owner
Definition: account_object.hpp:217
graphene::chain::balances_by_account_index::object_removed
virtual void object_removed(const object &obj) override
Definition: account_object.cpp:275
graphene::chain::account_object::lifetime_referrer_fee_percentage
uint16_t lifetime_referrer_fee_percentage
Percentage of fee which should go to lifetime referrer.
Definition: account_object.hpp:203
graphene::chain::account_member_index::before_key_members
set< public_key_type, pubkey_comparator > before_key_members
Definition: account_object.hpp:352
graphene::chain::account_object::referrer_rewards_percentage
uint16_t referrer_rewards_percentage
Definition: account_object.hpp:206
graphene::chain::account_member_index::get_key_members
set< public_key_type, pubkey_comparator > get_key_members(const account_object &a) const
Definition: account_object.cpp:117
graphene::chain::cut_fee
share_type cut_fee(share_type a, uint16_t p)
Definition: account_object.cpp:32
FC_ASSERT
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
graphene::protocol::asset::amount
share_type amount
Definition: asset.hpp:36
graphene::chain::account_balance_object::maintenance_flag
bool maintenance_flag
Whether need to process this balance object in maintenance interval.
Definition: account_object.hpp:165
graphene::chain::database::deposit_cashback
void deposit_cashback(const account_object &acct, share_type amount, bool require_vesting=true)
helper to handle cashback rewards
Definition: db_balance.cpp:202
graphene::chain::account_member_index::account_to_key_memberships
map< public_key_type, set< account_id_type >, pubkey_comparator > account_to_key_memberships
Definition: account_object.hpp:341
graphene::db::abstract_object::get_id
object_id< SpaceID, TypeID > get_id() const
Definition: object.hpp:113
graphene::chain::account_member_index::account_to_account_memberships
map< account_id_type, set< account_id_type > > account_to_account_memberships
Definition: account_object.hpp:340
graphene::chain::account_statistics_object::pending_vested_fees
share_type pending_vested_fees
Definition: account_object.hpp:133
graphene::chain::account_member_index::object_removed
virtual void object_removed(const object &obj) override
Definition: account_object.cpp:156
graphene::chain::account_object::referrer
account_id_type referrer
The account credited as referring this account. Receives a percentage of referral rewards.
Definition: account_object.hpp:196
graphene::chain::balances_by_account_index::about_to_modify
virtual void about_to_modify(const object &before) override
Definition: account_object.cpp:282
graphene::protocol::asset
Definition: asset.hpp:31
graphene::chain::account_member_index::before_account_members
set< account_id_type > before_account_members
Definition: account_object.hpp:351
fc::safe::value
T value
Definition: safe.hpp:28
graphene::chain::account_member_index::before_address_members
set< address > before_address_members
Definition: account_object.hpp:353
graphene::chain::account_statistics_object::pay_fee
void pay_fee(share_type core_fee, share_type cashback_vesting_threshold)
Definition: account_object.cpp:100
GRAPHENE_100_PERCENT
#define GRAPHENE_100_PERCENT
Definition: config.hpp:102
graphene
Definition: api.cpp:48
graphene::db::object_database::modify
void modify(const T &obj, const Lambda &m)
Definition: object_database.hpp:99
graphene::db::object
base for all database objects
Definition: object.hpp:61
graphene::chain::account_balance_object::asset_type
asset_id_type asset_type
Definition: account_object.hpp:162
raw.hpp
fc::safe
Definition: safe.hpp:26