BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
db_balance.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  */
24 
26 
31 #include <boost/range/algorithm.hpp>
32 
33 namespace graphene { namespace chain {
34 
35 asset database::get_balance(account_id_type owner, asset_id_type asset_id) const
36 {
37  auto& index = get_index_type< primary_index< account_balance_index > >().get_secondary_index<balances_by_account_index>();
38  auto abo = index.get_account_balance( owner, asset_id );
39  if( !abo )
40  return asset(0, asset_id);
41  return abo->get_balance();
42 }
43 
44 asset database::get_balance(const account_object& owner, const asset_object& asset_obj) const
45 {
46  return get_balance(owner.get_id(), asset_obj.get_id());
47 }
48 
49 string database::to_pretty_string( const asset& a )const
50 {
51  return a.asset_id(*this).amount_to_pretty_string(a.amount);
52 }
53 
54 void database::adjust_balance(account_id_type account, asset delta )
55 { try {
56  if( delta.amount == 0 )
57  return;
58 
59  auto& index = get_index_type< primary_index< account_balance_index > >().get_secondary_index<balances_by_account_index>();
60  auto abo = index.get_account_balance( account, delta.asset_id );
61  if( !abo )
62  {
63  FC_ASSERT( delta.amount > 0, "Insufficient Balance: ${a}'s balance of ${b} is less than required ${r}",
64  ("a",account(*this).name)
65  ("b",to_pretty_string(asset(0,delta.asset_id)))
66  ("r",to_pretty_string(-delta)));
67  create<account_balance_object>([account,&delta](account_balance_object& b) {
68  b.owner = account;
69  b.asset_type = delta.asset_id;
70  b.balance = delta.amount.value;
71  if( b.asset_type == asset_id_type() ) // CORE asset
72  b.maintenance_flag = true;
73  });
74  } else {
75  if( delta.amount < 0 )
76  FC_ASSERT( abo->get_balance() >= -delta, "Insufficient Balance: ${a}'s balance of ${b} is less than required ${r}",
77  ("a",account(*this).name)("b",to_pretty_string(abo->get_balance()))("r",to_pretty_string(-delta)));
78  modify(*abo, [delta](account_balance_object& b) {
79  b.adjust_balance(delta);
80  });
81  }
82 
83 } FC_CAPTURE_AND_RETHROW( (account)(delta) ) }
84 
85 namespace detail {
86 
90  struct vbo_mfs_key
91  {
92  account_id_type account_id;
93  asset_id_type asset_id;
94 
95  vbo_mfs_key(const account_id_type& account, const asset_id_type& asset):
96  account_id(account),
98  {}
99 
100  bool operator()(const vbo_mfs_key& k, const vesting_balance_object& vbo)const
101  {
103  ( k.asset_id == vbo.balance.asset_id ) &&
104  ( k.account_id == vbo.owner );
105  }
106 
107  uint64_t operator()(const vbo_mfs_key& k)const
108  {
109  return vbo_mfs_hash(k.account_id, k.asset_id);
110  }
111  };
112 } //detail
113 
114 asset database::get_market_fee_vesting_balance(const account_id_type &account_id, const asset_id_type &asset_id)
115 {
116  auto& vesting_balances = get_index_type<vesting_balance_index>().indices().get<by_vesting_type>();
117  const auto& key = detail::vbo_mfs_key{account_id, asset_id};
118  auto vbo_it = vesting_balances.find(key, key, key);
119 
120  if( vbo_it == vesting_balances.end() )
121  {
122  return asset(0, asset_id);
123  }
124  return vbo_it->balance;
125 }
126 
127 void database::deposit_market_fee_vesting_balance(const account_id_type &account_id, const asset &delta)
128 { try {
129  FC_ASSERT( delta.amount >= 0, "Invalid negative value for balance");
130 
131  if( delta.amount == 0 )
132  return;
133 
134  auto& vesting_balances = get_index_type<vesting_balance_index>().indices().get<by_vesting_type>();
135  const auto& key = detail::vbo_mfs_key{account_id, delta.asset_id};
136  auto vbo_it = vesting_balances.find(key, key, key);
137 
138  auto block_time = head_block_time();
139 
140  if( vbo_it == vesting_balances.end() )
141  {
142  create<vesting_balance_object>([&account_id, &delta](vesting_balance_object &vbo) {
143  vbo.owner = account_id;
144  vbo.balance = delta;
147  });
148  } else {
149  modify( *vbo_it, [&block_time, &delta]( vesting_balance_object& vbo )
150  {
151  vbo.deposit_vested(block_time, delta);
152  });
153  }
154 } FC_CAPTURE_AND_RETHROW( (account_id)(delta) ) }
155 
158  share_type amount, uint32_t req_vesting_seconds,
159  vesting_balance_type balance_type,
160  account_id_type req_owner,
161  bool require_vesting )
162 {
163  if( amount == 0 )
165 
167 
168  if( ovbid.valid() )
169  {
170  const vesting_balance_object& vbo = (*ovbid)(*this);
171  if( vbo.owner == req_owner && vbo.policy.is_type< cdd_vesting_policy >()
172  && vbo.policy.get< cdd_vesting_policy >().vesting_seconds == req_vesting_seconds )
173  {
174  modify( vbo, [require_vesting, &now, &amount]( vesting_balance_object& _vbo )
175  {
176  if( require_vesting )
177  _vbo.deposit(now, amount);
178  else
179  _vbo.deposit_vested(now, amount);
180  } );
182  }
183  }
184 
185  cdd_vesting_policy policy;
186  policy.vesting_seconds = req_vesting_seconds;
187  policy.coin_seconds_earned = require_vesting ? 0 : amount.value * policy.vesting_seconds;
188  policy.coin_seconds_earned_last_update = now;
189 
190  const vesting_balance_object& vbo = create< vesting_balance_object >(
191  [&req_owner, &amount, &balance_type, &policy ]( vesting_balance_object& _vbo )
192  {
193  _vbo.owner = req_owner;
194  _vbo.balance = amount;
195  _vbo.balance_type = balance_type;
196  _vbo.policy = policy;
197  } );
198 
199  return vbo.id;
200 }
201 
202 void database::deposit_cashback(const account_object& acct, share_type amount, bool require_vesting)
203 {
204  // If we don't have a VBO, or if it has the wrong maturity
205  // due to a policy change, cut it loose.
206 
207  if( amount == 0 )
208  return;
209 
210  account_id_type acct_id = acct.get_id();
211 
212  // Note: missing 'PROXY_TO_SELF' here
213  bool is_reserved_account = ( acct_id == GRAPHENE_COMMITTEE_ACCOUNT || acct_id == GRAPHENE_WITNESS_ACCOUNT ||
215  is_reserved_account = ( is_reserved_account || acct_id == GRAPHENE_NULL_ACCOUNT ||
216  acct_id == GRAPHENE_TEMP_ACCOUNT );
217  if( is_reserved_account )
218  {
219  // The blockchain's accounts do not get cashback; it simply goes to the reserve pool.
221  d.current_supply -= amount;
222  });
223  return;
224  }
225 
227  acct.cashback_vb,
228  amount,
229  get_global_properties().parameters.cashback_vesting_period_seconds,
231  acct_id,
232  require_vesting );
233 
234  if( new_vbid.valid() )
235  {
236  modify( acct, [&new_vbid]( account_object& _acct )
237  {
238  _acct.cashback_vb = *new_vbid;
239  } );
240  modify( acct.statistics( *this ), []( account_statistics_object& aso )
241  {
242  aso.has_cashback_vb = true;
243  } );
244  }
245 
246  return;
247 }
248 
250 {
251  if( amount == 0 )
252  return;
253 
255  wit.pay_vb,
256  amount,
257  get_global_properties().parameters.witness_pay_vesting_seconds,
259  wit.witness_account,
260  true );
261 
262  if( new_vbid.valid() )
263  {
264  modify( wit, [&]( witness_object& _wit )
265  {
266  _wit.pay_vb = *new_vbid;
267  } );
268  }
269 
270  return;
271 }
272 
273 } }
graphene::chain::cdd_vesting_policy
defines vesting in terms of coin-days accrued which allows for dynamic deposit/withdraw
Definition: vesting_balance_object.hpp:89
FC_CAPTURE_AND_RETHROW
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:479
graphene::chain::cdd_vesting_policy::coin_seconds_earned
fc::uint128_t coin_seconds_earned
Definition: vesting_balance_object.hpp:92
graphene::chain::detail::vbo_mfs_key
Definition: db_balance.cpp:90
graphene::db::object::id
object_id_type id
Definition: object.hpp:69
graphene::chain::account_balance_object::owner
account_id_type owner
Definition: account_object.hpp:161
GRAPHENE_RELAXED_COMMITTEE_ACCOUNT
#define GRAPHENE_RELAXED_COMMITTEE_ACCOUNT
Represents the current committee members.
Definition: config.hpp:144
graphene::chain::detail::vbo_mfs_key::asset_id
asset_id_type asset_id
Definition: db_balance.cpp:93
graphene::chain::database::head_block_time
time_point_sec head_block_time() const
Definition: db_getter.cpp:67
asset_object.hpp
graphene::chain::database::get_balance
asset get_balance(account_id_type owner, asset_id_type asset_id) const
Retrieve a particular account's balance in a given asset.
Definition: db_balance.cpp:35
database.hpp
graphene::chain::instant_vesting_policy
instant vesting policy
Definition: vesting_balance_object.hpp:126
graphene::chain::account_balance_object::adjust_balance
void adjust_balance(const asset &delta)
Definition: account_object.cpp:45
graphene::chain::asset_dynamic_data_object::current_supply
share_type current_supply
The number of shares currently in existence.
Definition: asset_object.hpp:61
graphene::chain::vesting_balance_type
vesting_balance_type
Definition: vesting_balance_object.hpp:143
GRAPHENE_TEMP_ACCOUNT
#define GRAPHENE_TEMP_ACCOUNT
Represents the canonical account with WILDCARD authority (anybody can access funds in temp account)
Definition: config.hpp:148
graphene::chain::witness_object::witness_account
account_id_type witness_account
Definition: witness_object.hpp:35
graphene::chain::asset_object
tracks the parameters of an asset
Definition: asset_object.hpp:75
graphene::chain::database::adjust_balance
void adjust_balance(account_id_type account, asset delta)
Adjust a particular account's balance in a given asset by a delta.
Definition: db_balance.cpp:54
graphene::chain::account_balance_object
Tracks the balance of a single account/asset pair.
Definition: account_object.hpp:157
graphene::chain::witness_object::pay_vb
optional< vesting_balance_id_type > pay_vb
Definition: witness_object.hpp:38
graphene::chain::database::deposit_witness_pay
void deposit_witness_pay(const witness_object &wit, share_type amount)
helper to handle witness pay
Definition: db_balance.cpp:249
graphene::chain::vesting_balance_object::deposit
void deposit(const fc::time_point_sec &now, const asset &amount)
Deposit amount into vesting balance, requiring it to vest before withdrawal.
Definition: vesting_balance_object.cpp:240
graphene::chain::vesting_balance_object::policy
vesting_policy policy
The vesting policy stores details on when funds vest, and controls when they may be withdrawn.
Definition: vesting_balance_object.hpp:161
graphene::chain::vesting_balance_object
Definition: vesting_balance_object.hpp:151
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::detail::vbo_mfs_key::operator()
bool operator()(const vbo_mfs_key &k, const vesting_balance_object &vbo) const
Definition: db_balance.cpp:100
graphene::chain::cdd_vesting_policy::coin_seconds_earned_last_update
fc::time_point_sec coin_seconds_earned_last_update
Definition: vesting_balance_object.hpp:95
fc::optional::valid
bool valid() const
Definition: optional.hpp:186
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
fc::time_point_sec
Definition: time.hpp:74
graphene::protocol::asset::asset_id
asset_id_type asset_id
Definition: asset.hpp:37
account_object.hpp
graphene::chain::detail::vbo_mfs_key::account_id
account_id_type account_id
Definition: db_balance.cpp:92
graphene::chain::detail::vbo_mfs_key::vbo_mfs_key
vbo_mfs_key(const account_id_type &account, const asset_id_type &asset)
Definition: db_balance.cpp:95
graphene::chain::account_object::cashback_vb
optional< vesting_balance_id_type > cashback_vb
Definition: account_object.hpp:265
vesting_balance_object.hpp
graphene::chain::database::to_pretty_string
string to_pretty_string(const asset &a) const
Definition: db_balance.cpp:49
graphene::chain::vesting_balance_object::balance
asset balance
Definition: vesting_balance_object.hpp:159
graphene::chain::vesting_balance_object::balance_type
vesting_balance_type balance_type
type of the vesting balance
Definition: vesting_balance_object.hpp:163
graphene::chain::database::deposit_market_fee_vesting_balance
void deposit_market_fee_vesting_balance(const account_id_type &account_id, const asset &delta)
Definition: db_balance.cpp:127
GRAPHENE_COMMITTEE_ACCOUNT
#define GRAPHENE_COMMITTEE_ACCOUNT
Definition: config.hpp:140
graphene::chain::vesting_balance_type::market_fee_sharing
@ market_fee_sharing
graphene::chain::database::deposit_lazy_vesting
optional< vesting_balance_id_type > deposit_lazy_vesting(const optional< vesting_balance_id_type > &ovbid, share_type amount, uint32_t req_vesting_seconds, vesting_balance_type balance_type, account_id_type req_owner, bool require_vesting)
Helper to make lazy deposit to CDD VBO.
Definition: db_balance.cpp:156
FC_ASSERT
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
fc::static_variant::is_type
bool is_type() const
Definition: static_variant.hpp:332
graphene::chain::database::get_market_fee_vesting_balance
asset get_market_fee_vesting_balance(const account_id_type &account_id, const asset_id_type &asset_id)
Retrieve a particular account's market fee vesting balance in a given asset.
Definition: db_balance.cpp:114
graphene::chain::detail::vbo_mfs_key::operator()
uint64_t operator()(const vbo_mfs_key &k) const
Definition: db_balance.cpp:107
GRAPHENE_WITNESS_ACCOUNT
#define GRAPHENE_WITNESS_ACCOUNT
Represents the current witnesses.
Definition: config.hpp:142
graphene::protocol::asset::amount
share_type amount
Definition: asset.hpp:36
fc::static_variant::get
X & get()
Definition: static_variant.hpp:236
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::vesting_balance_object::deposit_vested
void deposit_vested(const fc::time_point_sec &now, const asset &amount)
Deposit amount into vesting balance, making the new funds vest immediately.
Definition: vesting_balance_object.cpp:247
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::vesting_balance_type::cashback
@ cashback
graphene::chain::witness_object
Definition: witness_object.hpp:32
graphene::chain::account_object::statistics
account_statistics_id_type statistics
Definition: account_object.hpp:229
graphene::chain::detail::vbo_mfs_hash
uint64_t vbo_mfs_hash(const account_id_type &account_id, const asset_id_type &asset_id)
Definition: vesting_balance_object.hpp:204
GRAPHENE_NULL_ACCOUNT
#define GRAPHENE_NULL_ACCOUNT
Represents the canonical account with NO authority (nobody can access funds in null account)
Definition: config.hpp:146
graphene::db::abstract_object::get_id
object_id< SpaceID, TypeID > get_id() const
Definition: object.hpp:113
graphene::chain::database::get_global_properties
const global_property_object & get_global_properties() const
Definition: db_getter.cpp:47
graphene::chain::vesting_balance_object::owner
account_id_type owner
Account which owns and may withdraw from this vesting balance.
Definition: vesting_balance_object.hpp:156
fc::optional< vesting_balance_id_type >
graphene::protocol::asset
Definition: asset.hpp:31
witness_object.hpp
graphene::chain::cdd_vesting_policy::vesting_seconds
uint32_t vesting_seconds
Definition: vesting_balance_object.hpp:91
fc::safe::value
T value
Definition: safe.hpp:28
graphene::db::index
abstract base class for accessing objects indexed in various ways.
Definition: index.hpp:70
graphene::chain::vesting_balance_type::witness
@ witness
graphene
Definition: api.cpp:48
graphene::db::object_database::modify
void modify(const T &obj, const Lambda &m)
Definition: object_database.hpp:99
graphene::chain::account_balance_object::asset_type
asset_id_type asset_type
Definition: account_object.hpp:162
fc::safe
Definition: safe.hpp:26