add get_gpos_info database api call

This commit is contained in:
Alfredo 2019-03-05 17:48:47 -03:00
parent 0e3d87eaad
commit a58eb6fae8
6 changed files with 201 additions and 15 deletions

View file

@ -161,6 +161,8 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
vector<tournament_object> get_tournaments_by_state(tournament_id_type stop, unsigned limit, tournament_id_type start, tournament_state state); vector<tournament_object> get_tournaments_by_state(tournament_id_type stop, unsigned limit, tournament_id_type start, tournament_state state);
vector<tournament_id_type> get_registered_tournaments(account_id_type account_filter, uint32_t limit) const; vector<tournament_id_type> get_registered_tournaments(account_id_type account_filter, uint32_t limit) const;
// gpos
gpos_info get_gpos_info(const account_id_type account) const;
//private: //private:
template<typename T> template<typename T>
@ -2021,6 +2023,55 @@ vector<tournament_id_type> database_api_impl::get_registered_tournaments(account
return tournament_ids; return tournament_ids;
} }
//////////////////////////////////////////////////////////////////////
// //
// GPOS methods //
// //
//////////////////////////////////////////////////////////////////////
graphene::app::gpos_info database_api::get_gpos_info(const account_id_type account) const
{
return my->get_gpos_info(account);
}
graphene::app::gpos_info database_api_impl::get_gpos_info(const account_id_type account) const
{
gpos_info result;
result.vesting_factor = _db.calculate_vesting_factor(account(_db));
const auto& dividend_data = asset_id_type()(_db).dividend_data(_db);
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(_db);
result.award = _db.get_balance(dividend_distribution_account, asset_id_type()(_db));
share_type total_amount;
auto balance_type = vesting_balance_type::gpos;
#ifdef USE_VESTING_OBJECT_BY_ASSET_BALANCE_INDEX
// get only once a collection of accounts that hold nonzero vesting balances of the dividend asset
auto vesting_balances_begin =
vesting_index.indices().get<by_asset_balance>().lower_bound(boost::make_tuple(asset_id_type(), balance_type));
auto vesting_balances_end =
vesting_index.indices().get<by_asset_balance>().upper_bound(boost::make_tuple(asset_id_type(), balance_type, share_type()));
for (const vesting_balance_object& vesting_balance_obj : boost::make_iterator_range(vesting_balances_begin, vesting_balances_end))
{
total_amount += vesting_balance_obj.balance.amount;
}
#else
const vesting_balance_index& vesting_index = _db.get_index_type<vesting_balance_index>();
const auto& vesting_balances = vesting_index.indices().get<by_id>();
for (const vesting_balance_object& vesting_balance_obj : vesting_balances)
{
if (vesting_balance_obj.balance.asset_id == asset_id_type() && vesting_balance_obj.balance_type == balance_type)
{
total_amount += vesting_balance_obj.balance.amount;
}
}
#endif
result.total_amount = total_amount;
return result;
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// // // //
// Private methods // // Private methods //

View file

@ -114,6 +114,12 @@ struct market_trade
double value; double value;
}; };
struct gpos_info {
double vesting_factor;
asset award;
share_type total_amount;
};
/** /**
* @brief The database_api class implements the RPC API for the chain database. * @brief The database_api class implements the RPC API for the chain database.
* *
@ -645,7 +651,17 @@ class database_api
*/ */
vector<tournament_id_type> get_registered_tournaments(account_id_type account_filter, uint32_t limit) const; vector<tournament_id_type> get_registered_tournaments(account_id_type account_filter, uint32_t limit) const;
private: //////////
// GPOS //
//////////
/**
* @return account and network GPOS information
*/
gpos_info get_gpos_info(const account_id_type account) const;
private:
std::shared_ptr< database_api_impl > my; std::shared_ptr< database_api_impl > my;
}; };
@ -656,6 +672,8 @@ FC_REFLECT( graphene::app::order_book, (base)(quote)(bids)(asks) );
FC_REFLECT( graphene::app::market_ticker, (base)(quote)(latest)(lowest_ask)(highest_bid)(percent_change)(base_volume)(quote_volume) ); FC_REFLECT( graphene::app::market_ticker, (base)(quote)(latest)(lowest_ask)(highest_bid)(percent_change)(base_volume)(quote_volume) );
FC_REFLECT( graphene::app::market_volume, (base)(quote)(base_volume)(quote_volume) ); FC_REFLECT( graphene::app::market_volume, (base)(quote)(base_volume)(quote_volume) );
FC_REFLECT( graphene::app::market_trade, (date)(price)(amount)(value) ); FC_REFLECT( graphene::app::market_trade, (date)(price)(amount)(value) );
FC_REFLECT( graphene::app::gpos_info, (vesting_factor)(award)(total_amount) );
FC_API(graphene::app::database_api, FC_API(graphene::app::database_api,
// Objects // Objects
@ -765,4 +783,7 @@ FC_API(graphene::app::database_api,
(get_tournaments_by_state) (get_tournaments_by_state)
(get_tournaments ) (get_tournaments )
(get_registered_tournaments) (get_registered_tournaments)
// gpos
(get_gpos_info)
) )

View file

@ -725,14 +725,14 @@ void deprecate_annual_members( database& db )
return; return;
} }
double calculate_vesting_factor(const database& d, const account_object& stake_account) double database::calculate_vesting_factor(const account_object& stake_account)
{ {
// get last time voted form stats // get last time voted form stats
const auto &stats = stake_account.statistics(d); const auto &stats = stake_account.statistics(*this);
fc::time_point_sec last_date_voted = stats.last_vote_time; fc::time_point_sec last_date_voted = stats.last_vote_time;
// get global data related to gpos // get global data related to gpos
const auto &gpo = d.get_global_properties(); const auto &gpo = this->get_global_properties();
const auto vesting_period = gpo.parameters.gpos_period(); const auto vesting_period = gpo.parameters.gpos_period();
const auto vesting_subperiod = gpo.parameters.gpos_subperiod(); const auto vesting_subperiod = gpo.parameters.gpos_subperiod();
const auto period_start = fc::time_point_sec(gpo.parameters.gpos_period_start()); const auto period_start = fc::time_point_sec(gpo.parameters.gpos_period_start());
@ -740,7 +740,7 @@ double calculate_vesting_factor(const database& d, const account_object& stake_a
// variables needed // variables needed
const fc::time_point_sec period_end = period_start + vesting_period; const fc::time_point_sec period_end = period_start + vesting_period;
const auto number_of_subperiods = vesting_period / vesting_subperiod; const auto number_of_subperiods = vesting_period / vesting_subperiod;
const auto now = d.head_block_time(); const auto now = this->head_block_time();
double vesting_factor; double vesting_factor;
auto seconds_since_period_start = now.sec_since_epoch() - period_start.sec_since_epoch(); auto seconds_since_period_start = now.sec_since_epoch() - period_start.sec_since_epoch();
@ -1071,7 +1071,7 @@ void schedule_pending_dividend_balances(database& db,
vesting_balances_begin, vesting_balances_end)) { vesting_balances_begin, vesting_balances_end)) {
if (holder_balance_object.owner == dividend_data.dividend_distribution_account) continue; if (holder_balance_object.owner == dividend_data.dividend_distribution_account) continue;
auto vesting_factor = calculate_vesting_factor(db, holder_balance_object.owner(db)); auto vesting_factor = db.calculate_vesting_factor(holder_balance_object.owner(db));
auto holder_balance = holder_balance_object.balance; auto holder_balance = holder_balance_object.balance;
@ -1463,7 +1463,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
if (itr == vesting_amounts.end()) if (itr == vesting_amounts.end())
return; return;
auto vesting_factor = calculate_vesting_factor(d, stake_account); auto vesting_factor = d.calculate_vesting_factor(stake_account);
voting_stake = (uint64_t)floor(voting_stake * vesting_factor); voting_stake = (uint64_t)floor(voting_stake * vesting_factor);
} }
else else

View file

@ -1,4 +1,4 @@
// GPOS HARDFORK Friday, February 15, 2019 5:08:21 PM // GPOS HARDFORK Friday, March 15, 2019 11:57:28 PM
#ifndef HARDFORK_GPOS_TIME #ifndef HARDFORK_GPOS_TIME
#define HARDFORK_GPOS_TIME (fc::time_point_sec( 1550250501 )) #define HARDFORK_GPOS_TIME (fc::time_point_sec( 1552694248 ))
#endif #endif

View file

@ -498,8 +498,11 @@ namespace graphene { namespace chain {
void update_active_witnesses(); void update_active_witnesses();
void update_active_committee_members(); void update_active_committee_members();
void update_worker_votes(); void update_worker_votes();
public:
double calculate_vesting_factor(const account_object& stake_account);
template<class... Types>
template<class... Types>
void perform_account_maintenance(std::tuple<Types...> helpers); void perform_account_maintenance(std::tuple<Types...> helpers);
///@} ///@}
///@} ///@}

View file

@ -32,6 +32,8 @@
#include "../common/database_fixture.hpp" #include "../common/database_fixture.hpp"
#include <graphene/app/database_api.hpp>
using namespace graphene::chain; using namespace graphene::chain;
using namespace graphene::chain::test; using namespace graphene::chain::test;
@ -340,6 +342,7 @@ BOOST_AUTO_TEST_CASE( voting )
{ {
ACTORS((alice)(bob)); ACTORS((alice)(bob));
try { try {
// move to hardfork // move to hardfork
generate_blocks( HARDFORK_GPOS_TIME ); generate_blocks( HARDFORK_GPOS_TIME );
generate_block(); generate_block();
@ -638,16 +641,15 @@ BOOST_AUTO_TEST_CASE( worker_dividends_voting )
BOOST_AUTO_TEST_CASE( account_multiple_vesting ) BOOST_AUTO_TEST_CASE( account_multiple_vesting )
{ {
try { try {
// update default gpos global parameters to 4 days
auto now = db.head_block_time();
update_gpos_global(345600, 86400, now);
// advance to HF // advance to HF
generate_blocks(HARDFORK_GPOS_TIME); generate_blocks(HARDFORK_GPOS_TIME);
generate_block(); generate_block();
set_expiration(db, trx); set_expiration(db, trx);
// update default gpos global parameters to 4 days
auto now = db.head_block_time();
update_gpos_global(345600, 86400, now);
ACTORS((sam)(patty)); ACTORS((sam)(patty));
const auto& core = asset_id_type()(db); const auto& core = asset_id_type()(db);
@ -839,4 +841,113 @@ BOOST_AUTO_TEST_CASE( proxy_voting )
} }
} }
BOOST_AUTO_TEST_CASE( no_proposal )
{
try {
}
catch (fc::exception &e) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_CASE( database_api )
{
ACTORS((alice)(bob));
try {
// move to hardfork
generate_blocks( HARDFORK_GPOS_TIME );
generate_block();
// database api
graphene::app::database_api db_api(db);
const auto& core = asset_id_type()(db);
// send some asset to alice and bob
transfer( committee_account, alice_id, core.amount( 1000 ) );
transfer( committee_account, bob_id, core.amount( 1000 ) );
generate_block();
// add some vesting to alice and bob
create_vesting(alice_id, core.amount(100), vesting_balance_type::gpos);
generate_block();
// total balance is 100 rest of data at 0
auto gpos_info = db_api.get_gpos_info(alice_id);
BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0);
BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0);
BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 100);
create_vesting(bob_id, core.amount(100), vesting_balance_type::gpos);
generate_block();
// total gpos balance is now 200
gpos_info = db_api.get_gpos_info(alice_id);
BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200);
// update default gpos and dividend interval to 10 days
auto now = db.head_block_time();
update_gpos_global(5184000, 864000, now); // 10 days subperiods
update_payout_interval(core.symbol, fc::time_point::now() + fc::minutes(1), 60 * 60 * 24 * 10); // 10 days
generate_block();
// no votes for witness 1
auto witness1 = witness_id_type(1)(db);
BOOST_CHECK_EQUAL(witness1.total_votes, 0);
// no votes for witness 2
auto witness2 = witness_id_type(2)(db);
BOOST_CHECK_EQUAL(witness2.total_votes, 0);
// transfering some coins to distribution account.
const auto& dividend_holder_asset_object = get_asset(GRAPHENE_SYMBOL);
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db);
transfer( committee_account, dividend_distribution_account.id, core.amount( 100 ) );
generate_block();
// award balance is now 100
gpos_info = db_api.get_gpos_info(alice_id);
BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0);
BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 100);
BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200);
// vote for witness1
vote_for(alice_id, witness1.vote_id, alice_private_key);
vote_for(bob_id, witness1.vote_id, bob_private_key);
// go to maint
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
// payment for alice and bob is done, distribution account is back in 0
gpos_info = db_api.get_gpos_info(alice_id);
BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 1);
BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0);
BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200);
advance_x_maint(10);
// alice vesting coeffcient decay
gpos_info = db_api.get_gpos_info(alice_id);
BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0.83333333333333337);
BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0);
BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200);
advance_x_maint(10);
// vesting factor for alice decaying more
gpos_info = db_api.get_gpos_info(alice_id);
BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0.66666666666666663);
BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0);
BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200);
}
catch (fc::exception &e) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()