2017-05-25 09:13:59 +00:00
/*
* Copyright ( c ) 2015 Cryptonomex , Inc . , and contributors .
*
* The MIT License
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
# include <graphene/chain/database.hpp>
# include <graphene/chain/account_object.hpp>
# include <graphene/chain/asset_object.hpp>
2017-12-06 07:40:52 +00:00
# include <graphene/chain/balance_object.hpp>
2017-05-25 09:13:59 +00:00
# include <graphene/chain/vesting_balance_object.hpp>
# include <graphene/chain/witness_object.hpp>
namespace graphene { namespace chain {
asset database : : get_balance ( account_id_type owner , asset_id_type asset_id ) const
{
2019-09-10 13:26:27 +00:00
auto & index = get_index_type < primary_index < account_balance_index > > ( ) . get_secondary_index < balances_by_account_index > ( ) ;
auto abo = index . get_account_balance ( owner , asset_id ) ;
if ( ! abo )
2017-05-25 09:13:59 +00:00
return asset ( 0 , asset_id ) ;
2019-09-10 13:26:27 +00:00
return abo - > get_balance ( ) ;
2017-05-25 09:13:59 +00:00
}
asset database : : get_balance ( const account_object & owner , const asset_object & asset_obj ) const
{
return get_balance ( owner . get_id ( ) , asset_obj . get_id ( ) ) ;
}
2017-12-06 07:40:52 +00:00
asset database : : get_balance ( asset_id_type lottery_id ) const
{
auto & index = get_index_type < lottery_balance_index > ( ) . indices ( ) . get < by_owner > ( ) ;
auto itr = index . find ( lottery_id ) ;
if ( itr = = index . end ( ) )
return asset ( 0 , asset_id_type ( ) ) ;
return itr - > get_balance ( ) ;
}
2017-05-25 09:13:59 +00:00
string database : : to_pretty_string ( const asset & a ) const
{
return a . asset_id ( * this ) . amount_to_pretty_string ( a . amount ) ;
}
void database : : adjust_balance ( account_id_type account , asset delta )
{ try {
if ( delta . amount = = 0 )
return ;
2019-09-10 13:26:27 +00:00
auto & index = get_index_type < primary_index < account_balance_index > > ( ) . get_secondary_index < balances_by_account_index > ( ) ;
auto abo = index . get_account_balance ( account , delta . asset_id ) ;
if ( ! abo )
2017-05-25 09:13:59 +00:00
{
FC_ASSERT ( delta . amount > 0 , " Insufficient Balance: ${a}'s balance of ${b} is less than required ${r} " ,
( " a " , account ( * this ) . name )
( " b " , to_pretty_string ( asset ( 0 , delta . asset_id ) ) )
( " r " , to_pretty_string ( - delta ) ) ) ;
create < account_balance_object > ( [ account , & delta ] ( account_balance_object & b ) {
b . owner = account ;
b . asset_type = delta . asset_id ;
b . balance = delta . amount . value ;
2019-11-07 05:55:02 +00:00
if ( b . asset_type = = asset_id_type ( ) ) // CORE asset
b . maintenance_flag = true ;
2017-05-25 09:13:59 +00:00
} ) ;
} else {
if ( delta . amount < 0 )
2019-09-10 13:26:27 +00:00
FC_ASSERT ( abo - > get_balance ( ) > = - delta , " Insufficient Balance: ${a}'s balance of ${b} is less than required ${r} " ,
( " a " , account ( * this ) . name ) ( " b " , to_pretty_string ( abo - > get_balance ( ) ) ) ( " r " , to_pretty_string ( - delta ) ) ) ;
modify ( * abo , [ delta ] ( account_balance_object & b ) {
2017-05-25 09:13:59 +00:00
b . adjust_balance ( delta ) ;
} ) ;
}
} FC_CAPTURE_AND_RETHROW ( ( account ) ( delta ) ) }
2017-12-06 07:40:52 +00:00
void database : : adjust_balance ( asset_id_type lottery_id , asset delta )
{
if ( delta . amount = = 0 )
return ;
auto & index = get_index_type < lottery_balance_index > ( ) . indices ( ) . get < by_owner > ( ) ;
auto itr = index . find ( lottery_id ) ;
if ( itr = = index . end ( ) )
{
FC_ASSERT ( delta . amount > 0 , " Insufficient Balance: ${a}'s balance is less than required ${r} " ,
( " a " , lottery_id )
( " b " , " test " )
( " r " , to_pretty_string ( - delta ) ) ) ;
create < lottery_balance_object > ( [ lottery_id , & delta ] ( lottery_balance_object & b ) {
b . lottery_id = lottery_id ;
b . balance = asset ( delta . amount , delta . asset_id ) ;
} ) ;
} else {
if ( delta . amount < 0 )
FC_ASSERT ( itr - > get_balance ( ) > = - delta , " Insufficient Balance: ${a}'s balance of ${b} is less than required ${r} " , ( " a " , lottery_id ) ( " b " , to_pretty_string ( itr - > get_balance ( ) ) ) ( " r " , to_pretty_string ( - delta ) ) ) ;
modify ( * itr , [ delta ] ( lottery_balance_object & b ) {
b . adjust_balance ( delta ) ;
} ) ;
}
}
void database : : adjust_sweeps_vesting_balance ( account_id_type account , int64_t delta )
{
if ( delta = = 0 )
return ;
2019-08-02 13:47:32 +00:00
asset_id_type asset_id = get_global_properties ( ) . parameters . sweeps_distribution_asset ( ) ;
2017-12-06 07:40:52 +00:00
auto & index = get_index_type < sweeps_vesting_balance_index > ( ) . indices ( ) . get < by_owner > ( ) ;
auto itr = index . find ( account ) ;
if ( itr = = index . end ( ) )
{
FC_ASSERT ( delta > 0 , " Insufficient Balance: ${a}'s balance of ${b} is less than required ${r} " ,
( " a " , account )
( " b " , " test " )
( " r " , - delta ) ) ;
create < sweeps_vesting_balance_object > ( [ account , & delta , & asset_id ] ( sweeps_vesting_balance_object & b ) {
b . owner = account ;
b . asset_id = asset_id ;
b . balance = delta ;
} ) ;
} else {
if ( delta < 0 )
FC_ASSERT ( itr - > get_balance ( ) > = - delta , " Insufficient Balance: ${a}'s balance of ${b} is less than required ${r} " , ( " a " , account ) ( " b " , itr - > get_balance ( ) ) ( " r " , - delta ) ) ;
2017-12-12 12:37:58 +00:00
modify ( * itr , [ & delta , & asset_id , this ] ( sweeps_vesting_balance_object & b ) {
2017-12-06 07:40:52 +00:00
b . adjust_balance ( asset ( delta , asset_id ) ) ;
2017-12-12 12:37:58 +00:00
b . last_claim_date = head_block_time ( ) ;
2017-12-06 07:40:52 +00:00
} ) ;
}
}
2017-05-25 09:13:59 +00:00
optional < vesting_balance_id_type > database : : deposit_lazy_vesting (
const optional < vesting_balance_id_type > & ovbid ,
share_type amount , uint32_t req_vesting_seconds ,
account_id_type req_owner ,
bool require_vesting )
{
if ( amount = = 0 )
return optional < vesting_balance_id_type > ( ) ;
fc : : time_point_sec now = head_block_time ( ) ;
while ( true )
{
if ( ! ovbid . valid ( ) )
break ;
const vesting_balance_object & vbo = ( * ovbid ) ( * this ) ;
if ( vbo . owner ! = req_owner )
break ;
if ( vbo . policy . which ( ) ! = vesting_policy : : tag < cdd_vesting_policy > : : value )
break ;
if ( vbo . policy . get < cdd_vesting_policy > ( ) . vesting_seconds ! = req_vesting_seconds )
break ;
modify ( vbo , [ & ] ( vesting_balance_object & _vbo )
{
if ( require_vesting )
_vbo . deposit ( now , amount ) ;
else
_vbo . deposit_vested ( now , amount ) ;
} ) ;
return optional < vesting_balance_id_type > ( ) ;
}
const vesting_balance_object & vbo = create < vesting_balance_object > ( [ & ] ( vesting_balance_object & _vbo )
{
_vbo . owner = req_owner ;
_vbo . balance = amount ;
cdd_vesting_policy policy ;
policy . vesting_seconds = req_vesting_seconds ;
policy . coin_seconds_earned = require_vesting ? 0 : amount . value * policy . vesting_seconds ;
policy . coin_seconds_earned_last_update = now ;
_vbo . policy = policy ;
} ) ;
return vbo . id ;
}
void database : : deposit_cashback ( const account_object & acct , share_type amount , bool require_vesting )
{
// If we don't have a VBO, or if it has the wrong maturity
// due to a policy change, cut it loose.
if ( amount = = 0 )
return ;
if ( acct . get_id ( ) = = GRAPHENE_COMMITTEE_ACCOUNT | | acct . get_id ( ) = = GRAPHENE_WITNESS_ACCOUNT | |
acct . get_id ( ) = = GRAPHENE_RELAXED_COMMITTEE_ACCOUNT | | acct . get_id ( ) = = GRAPHENE_NULL_ACCOUNT | |
acct . get_id ( ) = = GRAPHENE_TEMP_ACCOUNT )
{
// The blockchain's accounts do not get cashback; it simply goes to the reserve pool.
2018-07-05 17:52:55 +00:00
modify ( get_core_dynamic_data ( ) , [ amount ] ( asset_dynamic_data_object & d ) {
2017-05-25 09:13:59 +00:00
d . current_supply - = amount ;
} ) ;
return ;
}
optional < vesting_balance_id_type > new_vbid = deposit_lazy_vesting (
acct . cashback_vb ,
amount ,
get_global_properties ( ) . parameters . cashback_vesting_period_seconds ,
acct . id ,
require_vesting ) ;
if ( new_vbid . valid ( ) )
{
2019-11-07 05:55:02 +00:00
modify ( acct , [ & new_vbid ] ( account_object & _acct )
2017-05-25 09:13:59 +00:00
{
_acct . cashback_vb = * new_vbid ;
} ) ;
2019-11-07 05:55:02 +00:00
modify ( acct . statistics ( * this ) , [ ] ( account_statistics_object & aso )
{
aso . has_cashback_vb = true ;
} ) ;
2017-05-25 09:13:59 +00:00
}
return ;
}
void database : : deposit_witness_pay ( const witness_object & wit , share_type amount )
{
if ( amount = = 0 )
return ;
optional < vesting_balance_id_type > new_vbid = deposit_lazy_vesting (
wit . pay_vb ,
amount ,
get_global_properties ( ) . parameters . witness_pay_vesting_seconds ,
wit . witness_account ,
true ) ;
if ( new_vbid . valid ( ) )
{
modify ( wit , [ & ] ( witness_object & _wit )
{
_wit . pay_vb = * new_vbid ;
} ) ;
}
return ;
}
} }