BitShares-Core  4.0.0
BitShares blockchain implementation and command-line interface 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),
97  asset_id(asset)
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;
145  vbo.balance_type = vesting_balance_type::market_fee_sharing;
146  vbo.policy = instant_vesting_policy{};
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  while( true )
169  {
170  if( !ovbid.valid() )
171  break;
172  const vesting_balance_object& vbo = (*ovbid)(*this);
173  if( vbo.owner != req_owner )
174  break;
175  if( !vbo.policy.is_type< cdd_vesting_policy >() )
176  break;
177  if( vbo.policy.get< cdd_vesting_policy >().vesting_seconds != req_vesting_seconds )
178  break;
179  modify( vbo, [&]( vesting_balance_object& _vbo )
180  {
181  if( require_vesting )
182  _vbo.deposit(now, amount);
183  else
184  _vbo.deposit_vested(now, amount);
185  } );
187  }
188 
189  const vesting_balance_object& vbo = create< vesting_balance_object >( [&]( vesting_balance_object& _vbo )
190  {
191  _vbo.owner = req_owner;
192  _vbo.balance = amount;
193  _vbo.balance_type = balance_type;
194 
195  cdd_vesting_policy policy;
196  policy.vesting_seconds = req_vesting_seconds;
197  policy.coin_seconds_earned = require_vesting ? 0 : amount.value * policy.vesting_seconds;
198  policy.coin_seconds_earned_last_update = now;
199 
200  _vbo.policy = policy;
201  } );
202 
203  return vbo.id;
204 }
205 
206 void database::deposit_cashback(const account_object& acct, share_type amount, bool require_vesting)
207 {
208  // If we don't have a VBO, or if it has the wrong maturity
209  // due to a policy change, cut it loose.
210 
211  if( amount == 0 )
212  return;
213 
216  acct.get_id() == GRAPHENE_TEMP_ACCOUNT )
217  {
218  // The blockchain's accounts do not get cashback; it simply goes to the reserve pool.
220  d.current_supply -= amount;
221  });
222  return;
223  }
224 
226  acct.cashback_vb,
227  amount,
228  get_global_properties().parameters.cashback_vesting_period_seconds,
230  acct.id,
231  require_vesting );
232 
233  if( new_vbid.valid() )
234  {
235  modify( acct, [&new_vbid]( account_object& _acct )
236  {
237  _acct.cashback_vb = *new_vbid;
238  } );
239  modify( acct.statistics( *this ), []( account_statistics_object& aso )
240  {
241  aso.has_cashback_vb = true;
242  } );
243  }
244 
245  return;
246 }
247 
249 {
250  if( amount == 0 )
251  return;
252 
254  wit.pay_vb,
255  amount,
256  get_global_properties().parameters.witness_pay_vesting_seconds,
258  wit.witness_account,
259  true );
260 
261  if( new_vbid.valid() )
262  {
263  modify( wit, [&]( witness_object& _wit )
264  {
265  _wit.pay_vb = *new_vbid;
266  } );
267  }
268 
269  return;
270 }
271 
272 } }
bool is_type() const
Tracks the balance of a single account/asset pairThis object is indexed on owner and asset_type so th...
#define GRAPHENE_TEMP_ACCOUNT
Represents the canonical account with WILDCARD authority (anybody can access funds in temp account) ...
Definition: config.hpp:133
vesting_balance_type balance_type
type of the vesting balance
void modify(const T &obj, const Lambda &m)
void adjust_balance(account_id_type account, asset delta)
Adjust a particular account&#39;s balance in a given asset by a delta.
Definition: db_balance.cpp:54
This class represents an account on the object graphAccounts are the primary unit of authority on the...
string to_pretty_string(const asset &a) const
Definition: db_balance.cpp:49
Definition: api.cpp:56
vbo_mfs_key(const account_id_type &account, const asset_id_type &asset)
Definition: db_balance.cpp:95
asset get_balance(account_id_type owner, asset_id_type asset_id) const
Retrieve a particular account&#39;s balance in a given asset.
Definition: db_balance.cpp:35
bool valid() const
Definition: optional.hpp:186
void deposit(const fc::time_point_sec &now, const asset &amount)
Deposit amount into vesting balance, requiring it to vest before withdrawal.
optional< vesting_balance_id_type > pay_vb
vesting_policy policy
The vesting policy stores details on when funds vest, and controls when they may be withdrawn...
const global_property_object & get_global_properties() const
Definition: db_getter.cpp:44
object_id_type id
Definition: object.hpp:73
void deposit_witness_pay(const witness_object &wit, share_type amount)
Definition: db_balance.cpp:248
account_id_type get_id() const
optional< vesting_balance_id_type > cashback_vb
time_point_sec head_block_time() const
Definition: db_getter.cpp:64
#define GRAPHENE_COMMITTEE_ACCOUNT
Definition: config.hpp:125
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:478
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
tracks the asset information that changes frequentlyBecause the asset_object is very large it doesn&#39;t...
#define GRAPHENE_NULL_ACCOUNT
Represents the canonical account with NO authority (nobody can access funds in null account) ...
Definition: config.hpp:131
bool operator()(const vbo_mfs_key &k, const vesting_balance_object &vbo) const
Definition: db_balance.cpp:100
void deposit_vested(const fc::time_point_sec &now, const asset &amount)
Deposit amount into vesting balance, making the new funds vest immediately.
void deposit_market_fee_vesting_balance(const account_id_type &account_id, const asset &delta)
Definition: db_balance.cpp:127
asset get_market_fee_vesting_balance(const account_id_type &account_id, const asset_id_type &asset_id)
Retrieve a particular account&#39;s market fee vesting balance in a given asset.
Definition: db_balance.cpp:114
uint64_t vbo_mfs_hash(const account_id_type &account_id, const asset_id_type &asset_id)
#define GRAPHENE_RELAXED_COMMITTEE_ACCOUNT
Represents the current committee members.
Definition: config.hpp:129
const asset_dynamic_data_object & get_core_dynamic_data() const
Definition: db_getter.cpp:39
tracks the parameters of an assetAll assets have a globally unique symbol name that controls how they...
asset_id_type asset_id
Definition: asset.hpp:39
account_statistics_id_type statistics
asset_id_type get_id() const
abstract base class for accessing objects indexed in various ways.
Definition: index.hpp:71
defines vesting in terms of coin-days accrued which allows for dynamic deposit/withdraw ...
void deposit_cashback(const account_object &acct, share_type amount, bool require_vesting=true)
Definition: db_balance.cpp:206
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
share_type current_supply
The number of shares currently in existence.
account_id_type owner
Account which owns and may withdraw from this vesting balance.
T value
Definition: safe.hpp:22
uint64_t operator()(const vbo_mfs_key &k) const
Definition: db_balance.cpp:107
void adjust_balance(const asset &delta)
#define GRAPHENE_WITNESS_ACCOUNT
Represents the current witnesses.
Definition: config.hpp:127