Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add voting statistics during maintenance time #2247

Merged
merged 5 commits into from
Aug 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docker/default_config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ rpc-endpoint = 0.0.0.0:8090
# For database_api_impl::get_full_accounts to set max items to return in the lists
# api-limit-get-full-accounts-lists = 500

# For database_api_impl::get_top_voters to set max limit value
# api-limit-get-top-voters = 200

# For database_api_impl::get_call_orders and get_call_orders_by_account to set max limit value
# api-limit-get-call-orders = 300

Expand Down
5 changes: 5 additions & 0 deletions libraries/app/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ void application_impl::set_api_limit() {
if(_options->count("api-limit-get-full-accounts-lists")) {
_app_options.api_limit_get_full_accounts_lists = _options->at("api-limit-get-full-accounts-lists").as<uint64_t>();
}
if(_options->count("api-limit-get-top-voters")) {
_app_options.api_limit_get_top_voters = _options->at("api-limit-get-top-voters").as<uint64_t>();
}
if(_options->count("api-limit-get-call-orders")) {
_app_options.api_limit_get_call_orders = _options->at("api-limit-get-call-orders").as<uint64_t>();
}
Expand Down Expand Up @@ -1015,6 +1018,8 @@ void application::set_program_options(boost::program_options::options_descriptio
"For database_api_impl::get_full_accounts to set max accounts to query at once")
("api-limit-get-full-accounts-lists",boost::program_options::value<uint64_t>()->default_value(500),
"For database_api_impl::get_full_accounts to set max items to return in the lists")
("api-limit-get-top-voters",boost::program_options::value<uint64_t>()->default_value(200),
"For database_api_impl::get_top_voters to set max limit value")
("api-limit-get-call-orders",boost::program_options::value<uint64_t>()->default_value(300),
"For database_api_impl::get_call_orders and get_call_orders_by_account to set max limit value")
("api-limit-get-settle-orders",boost::program_options::value<uint64_t>()->default_value(300),
Expand Down
26 changes: 26 additions & 0 deletions libraries/app/database_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,11 @@ std::map<string,full_account> database_api::get_full_accounts( const vector<stri
return my->get_full_accounts( names_or_ids, subscribe );
}

vector<account_statistics_object> database_api::get_top_voters(uint32_t limit)const
{
return my->get_top_voters( limit );
}

std::map<std::string, full_account> database_api_impl::get_full_accounts( const vector<std::string>& names_or_ids,
optional<bool> subscribe )
{
Expand Down Expand Up @@ -640,6 +645,27 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
return results;
}

vector<account_statistics_object> database_api_impl::get_top_voters(uint32_t limit)const
{
abitmore marked this conversation as resolved.
Show resolved Hide resolved
FC_ASSERT( _app_options, "Internal error" );
const auto configured_limit = _app_options->api_limit_get_top_voters;
FC_ASSERT( limit <= configured_limit,
"limit can not be greater than ${configured_limit}",
("configured_limit", configured_limit) );

vector<account_statistics_object> result;

auto last_vote_tally_time = _db.get_dynamic_global_properties().last_vote_tally_time;
const auto& idx = _db.get_index_type<account_stats_index>().indices().get<by_voting_power_active>();

for(auto itr = idx.begin(); result.size() < limit && itr != idx.end() && itr->vote_tally_time >= last_vote_tally_time; ++itr)
{
result.emplace_back(*itr);
}

return result;
}

optional<account_object> database_api::get_account_by_name( string name )const
{
return my->get_account_by_name( name );
Expand Down
1 change: 1 addition & 0 deletions libraries/app/database_api_impl.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
optional<bool> subscribe )const;
std::map<string,full_account> get_full_accounts( const vector<string>& names_or_ids,
optional<bool> subscribe );
vector<account_statistics_object> get_top_voters(uint32_t limit)const;
optional<account_object> get_account_by_name( string name )const;
vector<account_id_type> get_account_references( const std::string account_id_or_name )const;
vector<optional<account_object>> lookup_account_names(const vector<string>& account_names)const;
Expand Down
2 changes: 2 additions & 0 deletions libraries/app/include/graphene/app/api_objects.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,5 @@ FC_REFLECT( graphene::app::market_trade, (sequence)(date)(price)(amount)(value)(

FC_REFLECT_DERIVED( graphene::app::extended_asset_object, (graphene::chain::asset_object),
(total_in_collateral)(total_backing_collateral) );


1 change: 1 addition & 0 deletions libraries/app/include/graphene/app/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ namespace graphene { namespace app {
uint64_t api_limit_get_htlc_by = 100;
uint64_t api_limit_get_full_accounts = 50;
uint64_t api_limit_get_full_accounts_lists = 500;
uint64_t api_limit_get_top_voters = 200;
uint64_t api_limit_get_call_orders = 300;
uint64_t api_limit_get_settle_orders = 300;
uint64_t api_limit_get_assets = 101;
Expand Down
8 changes: 8 additions & 0 deletions libraries/app/include/graphene/app/database_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,13 @@ class database_api
std::map<string,full_account> get_full_accounts( const vector<string>& names_or_ids,
optional<bool> subscribe = optional<bool>() );

/**
* @brief Returns vector of voting power sorted by reverse vp_active
* @param limit Max number of results
* @return Desc Sorted voting power vector
*/
vector<account_statistics_object> get_top_voters(uint32_t limit)const;

/**
* @brief Get info of an account by name
* @param name Name of the account to retrieve
Expand Down Expand Up @@ -948,6 +955,7 @@ FC_API(graphene::app::database_api,
(get_account_id_from_string)
(get_accounts)
(get_full_accounts)
(get_top_voters)
(get_account_by_name)
(get_account_references)
(lookup_account_names)
Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/account_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::account_statistics_object,
(has_cashback_vb)
(is_voting)
(last_vote_time)
(vp_all)(vp_active)(vp_committee)(vp_witness)(vp_worker)
(vote_tally_time)
(lifetime_fees_paid)
(pending_fees)(pending_vested_fees)
)
Expand Down
59 changes: 46 additions & 13 deletions libraries/chain/db_maint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
{
const auto& gpo = get_global_properties();
const auto& dgpo = get_dynamic_global_properties();
auto last_vote_tally_time = head_block_time();

distribute_fba_balances(*this);
create_buyback_orders(*this);
Expand All @@ -1187,7 +1188,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
optional<detail::vote_recalc_times> delegator_recalc_times;

vote_tally_helper( database& db )
: d(db), props( d.get_global_properties() ), dprops( d.get_dynamic_global_properties() ),
: d(db), props( d.get_global_properties() ), dprops( d.get_dynamic_global_properties() ),
now( d.head_block_time() ), hf2103_passed( HARDFORK_CORE_2103_PASSED( now ) ),
pob_activated( dprops.total_pob > 0 || dprops.total_inactive > 0 )
{
Expand Down Expand Up @@ -1226,6 +1227,13 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
+ (stake_account.cashback_vb.valid() ? (*stake_account.cashback_vb)(d).balance.amount.value: 0)
+ stats.core_in_balance.value;

// voting power stats
uint64_t vp_all = 0; ///< all voting power.
uint64_t vp_active = 0; ///< the voting power of the proxy, if there is no attenuation, it is equal to vp_all.
uint64_t vp_committee = 0; ///< the final voting power for the committees.
uint64_t vp_witness = 0; ///< the final voting power for the witnesses.
uint64_t vp_worker = 0; ///< the final voting power for the workers.

//PoB
const uint64_t pol_amount = stats.total_core_pol.value;
const uint64_t pol_value = stats.total_pol_value.value;
Expand Down Expand Up @@ -1275,33 +1283,57 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
if( voting_stake[2] == 0 )
return;

const account_statistics_object& opinion_account_stats = ( directly_voting ? stats : opinion_account.statistics( d ) );

// Recalculate votes
if( !hf2103_passed )
{
voting_stake[0] = voting_stake[2];
voting_stake[1] = voting_stake[2];
num_committee_voting_stake = voting_stake[2];
vp_all = vp_active = vp_committee = vp_witness = vp_worker = voting_stake[2];
}
else
{
vp_all = vp_active = voting_stake[2];
if( !directly_voting )
{
voting_stake[2] = detail::vote_recalc_options::delegator().get_recalced_voting_stake(
voting_stake[2], stats.last_vote_time, *delegator_recalc_times );
vp_active = voting_stake[2] = detail::vote_recalc_options::delegator().get_recalced_voting_stake(
voting_stake[2], stats.last_vote_time, *delegator_recalc_times );
}
const account_statistics_object& opinion_account_stats = ( directly_voting ? stats
: opinion_account.statistics( d ) );
voting_stake[1] = detail::vote_recalc_options::witness().get_recalced_voting_stake(
voting_stake[2], opinion_account_stats.last_vote_time, *witness_recalc_times );
voting_stake[0] = detail::vote_recalc_options::committee().get_recalced_voting_stake(
voting_stake[2], opinion_account_stats.last_vote_time, *committee_recalc_times );
vp_witness = voting_stake[1] = detail::vote_recalc_options::witness().get_recalced_voting_stake(
voting_stake[2], opinion_account_stats.last_vote_time, *witness_recalc_times );
vp_committee = voting_stake[0] = detail::vote_recalc_options::committee().get_recalced_voting_stake(
voting_stake[2], opinion_account_stats.last_vote_time, *committee_recalc_times );
num_committee_voting_stake = voting_stake[0];
if( opinion_account.num_committee_voted > 1 )
voting_stake[0] /= opinion_account.num_committee_voted;
voting_stake[2] = detail::vote_recalc_options::worker().get_recalced_voting_stake(
voting_stake[2], opinion_account_stats.last_vote_time, *worker_recalc_times );
vp_worker = voting_stake[2] = detail::vote_recalc_options::worker().get_recalced_voting_stake(
voting_stake[2], opinion_account_stats.last_vote_time, *worker_recalc_times );
}

// update voting power
d.modify( opinion_account_stats, [=]( account_statistics_object& update_stats ) {
if (update_stats.vote_tally_time != now)
{
update_stats.vp_all = vp_all;
update_stats.vp_active = vp_active;
update_stats.vp_committee = vp_committee;
update_stats.vp_witness = vp_witness;
update_stats.vp_worker = vp_worker;
update_stats.vote_tally_time = now;
}
else
{
update_stats.vp_all += vp_all;
update_stats.vp_active += vp_active;
update_stats.vp_committee += vp_committee;
update_stats.vp_witness += vp_witness;
update_stats.vp_worker += vp_worker;
// update_stats.vote_tally_time = now;
}
});

for( vote_id_type id : opinion_account.options.votes )
{
uint32_t offset = id.instance();
Expand Down Expand Up @@ -1333,7 +1365,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
} tally_helper(*this);

perform_account_maintenance( tally_helper );

struct clear_canary {
clear_canary(vector<uint64_t>& target): target(target){}
~clear_canary() { target.clear(); }
Expand Down Expand Up @@ -1416,8 +1448,9 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
if ( dgpo.next_maintenance_time <= HARDFORK_CORE_2103_TIME && next_maintenance_time > HARDFORK_CORE_2103_TIME )
process_hf_2103(*this);

modify(dgpo, [next_maintenance_time](dynamic_global_property_object& d) {
modify(dgpo, [last_vote_tally_time, next_maintenance_time](dynamic_global_property_object& d) {
d.next_maintenance_time = next_maintenance_time;
d.last_vote_tally_time = last_vote_tally_time;
d.accounts_registered_this_interval = 0;
});

Expand Down
26 changes: 25 additions & 1 deletion libraries/chain/include/graphene/chain/account_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ namespace graphene { namespace chain {

time_point_sec last_vote_time; ///< last time voted

/// Voting Power Stats
abitmore marked this conversation as resolved.
Show resolved Hide resolved
///@{
uint64_t vp_all = 0; ///< all voting power.
uint64_t vp_active = 0; ///< active voting power, if there is no attenuation, it is equal to vp_all.
uint64_t vp_committee = 0; ///< the final voting power for the committees.
uint64_t vp_witness = 0; ///< the final voting power for the witnesses.
uint64_t vp_worker = 0; ///< the final voting power for the workers.
/// timestamp of the last count of votes.
/// if there is no statistics, the date is less than `_db.get_dynamic_global_properties().last_vote_tally_time`.
time_point_sec vote_tally_time;
///@}

/// Whether this account owns some CORE asset and is voting
inline bool has_some_core_voting() const
{
Expand Down Expand Up @@ -419,7 +431,8 @@ namespace graphene { namespace chain {
typedef generic_index<account_object, account_multi_index_type> account_index;

struct by_maintenance_seq;

struct by_voting_power_active;

/**
* @ingroup object_index
*/
Expand All @@ -433,6 +446,17 @@ namespace graphene { namespace chain {
const_mem_fun<account_statistics_object, bool, &account_statistics_object::need_maintenance>,
member<account_statistics_object, string, &account_statistics_object::name>
>
>,
ordered_non_unique< tag<by_voting_power_active>,
composite_key<
account_statistics_object,
member<account_statistics_object, time_point_sec, &account_statistics_object::vote_tally_time>,
member<account_statistics_object, uint64_t, &account_statistics_object::vp_active>
>,
composite_key_compare<
std::greater< time_point_sec >,
std::greater< uint64_t >
>
>
>
> account_stats_multi_index_type;
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/include/graphene/chain/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

#define GRAPHENE_MAX_NESTED_OBJECTS (200)

#define GRAPHENE_CURRENT_DB_VERSION "20200510"
#define GRAPHENE_CURRENT_DB_VERSION "20200825"

#define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4
#define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ namespace graphene { namespace chain {
time_point_sec time;
witness_id_type current_witness;
time_point_sec next_maintenance_time;
time_point_sec last_vote_tally_time;
time_point_sec last_budget_time;
share_type witness_budget;
share_type total_pob;
Expand Down
1 change: 1 addition & 0 deletions libraries/chain/small_objects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::dynamic_global_property_object,
(time)
(current_witness)
(next_maintenance_time)
(last_vote_tally_time)
(last_budget_time)
(witness_budget)
(total_pob)
Expand Down