From 49564af60ad4ade409eb660af5ce99c8b966cba0 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Thu, 3 Oct 2019 01:17:29 +0200 Subject: [PATCH] WIP, SON related operations, cli_wallet commands and RPC - Updating global_property_object --- libraries/chain/db_init.cpp | 3 +- libraries/chain/db_maint.cpp | 105 ++++++++++++++++++ .../chain/include/graphene/chain/config.hpp | 4 + .../chain/include/graphene/chain/database.hpp | 2 + .../graphene/chain/global_property_object.hpp | 1 + .../chain/immutable_chain_parameters.hpp | 2 + .../chain/protocol/chain_parameters.hpp | 2 + 7 files changed, 117 insertions(+), 2 deletions(-) diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 5e7ab107..3f95b44b 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -256,6 +256,7 @@ void database::initialize_indexes() acnt_index->add_secondary_index(); add_index< primary_index >(); + add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); @@ -304,8 +305,6 @@ void database::initialize_indexes() //add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); - - add_index< primary_index >(); } void database::init_genesis(const genesis_state_type& genesis_state) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 06e15a19..c6ea58f7 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -326,6 +326,96 @@ void database::update_active_committee_members() }); } FC_CAPTURE_AND_RETHROW() } +void database::update_active_sons() +{ try { + assert( _son_count_histogram_buffer.size() > 0 ); + share_type stake_target = (_total_voting_stake-_witness_count_histogram_buffer[0]) / 2; + + /// accounts that vote for 0 or 1 son do not get to express an opinion on + /// the number of sons to have (they abstain and are non-voting accounts) + + share_type stake_tally = 0; + + size_t son_count = 0; + if( stake_target > 0 ) + { + while( (son_count < _son_count_histogram_buffer.size() - 1) + && (stake_tally <= stake_target) ) + { + stake_tally += _son_count_histogram_buffer[++son_count]; + } + } + + const chain_property_object& cpo = get_chain_properties(); + auto sons = sort_votable_objects(std::max(son_count*2+1, (size_t)cpo.immutable_parameters.min_son_count)); + + const global_property_object& gpo = get_global_properties(); + + const auto& all_sons = get_index_type().indices(); + + for( const son_object& son : all_sons ) + { + modify( son, [&]( son_object& obj ){ + obj.total_votes = _vote_tally_buffer[son.vote_id]; + }); + } + + // Update SON authority + modify( get(GRAPHENE_SON_ACCOUNT_ID), [&]( account_object& a ) + { + if( head_block_time() < HARDFORK_533_TIME ) + { + uint64_t total_votes = 0; + map weights; + a.active.weight_threshold = 0; + a.active.clear(); + + for( const son_object& son : sons ) + { + weights.emplace(son.son_member_account, _vote_tally_buffer[son.vote_id]); + total_votes += _vote_tally_buffer[son.vote_id]; + } + + // total_votes is 64 bits. Subtract the number of leading low bits from 64 to get the number of useful bits, + // then I want to keep the most significant 16 bits of what's left. + int8_t bits_to_drop = std::max(int(boost::multiprecision::detail::find_msb(total_votes)) - 15, 0); + for( const auto& weight : weights ) + { + // Ensure that everyone has at least one vote. Zero weights aren't allowed. + uint16_t votes = std::max((weight.second >> bits_to_drop), uint64_t(1) ); + a.active.account_auths[weight.first] += votes; + a.active.weight_threshold += votes; + } + + a.active.weight_threshold /= 2; + a.active.weight_threshold += 1; + } + else + { + vote_counter vc; + for( const son_object& son : sons ) + vc.add( son.son_member_account, std::max(_vote_tally_buffer[son.vote_id], UINT64_C(1)) ); + vc.finish( a.active ); + } + } ); + + modify(gpo, [&]( global_property_object& gp ){ + gp.active_sons.clear(); + gp.active_sons.reserve(sons.size()); + std::transform(sons.begin(), sons.end(), + std::inserter(gp.active_sons, gp.active_sons.end()), + [](const son_object& s) { + return s.id; + }); + }); + + //const witness_schedule_object& wso = witness_schedule_id_type()(*this); + //modify(wso, [&](witness_schedule_object& _wso) + //{ + // _wso.scheduler.update(gpo.active_witnesses); + //}); +} FC_CAPTURE_AND_RETHROW() } + void database::initialize_budget_record( fc::time_point_sec now, budget_record& rec )const { const dynamic_global_property_object& dpo = get_dynamic_global_properties(); @@ -1401,6 +1491,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g d._vote_tally_buffer.resize(props.next_available_vote_id); d._witness_count_histogram_buffer.resize(props.parameters.maximum_witness_count / 2 + 1); d._committee_count_histogram_buffer.resize(props.parameters.maximum_committee_count / 2 + 1); + d._son_count_histogram_buffer.resize(props.parameters.maximum_son s committee_count / 2 + 1); d._total_voting_stake = 0; auto balance_type = vesting_balance_type::unspecified; @@ -1503,6 +1594,18 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g // same rationale as for witnesses d._committee_count_histogram_buffer[offset] += voting_stake; } + if( opinion_account.options.num_son <= props.parameters.maximum_son_count ) + { + uint16_t offset = std::min(size_t(opinion_account.options.num_son/2), + d._son_count_histogram_buffer.size() - 1); + // votes for a number greater than maximum_son_count + // are turned into votes for maximum_son_count. + // + // in particular, this takes care of the case where a + // member was voting for a high number, then the + // parameter was lowered. + d._son_count_histogram_buffer[offset] += voting_stake; + } d._total_voting_stake += voting_stake; } @@ -1533,11 +1636,13 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g }; clear_canary a(_witness_count_histogram_buffer), b(_committee_count_histogram_buffer), + d(_son_count_histogram_buffer), c(_vote_tally_buffer); update_top_n_authorities(*this); update_active_witnesses(); update_active_committee_members(); + update_active_sons(); update_worker_votes(); modify(gpo, [this](global_property_object& p) { diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 7b3e8743..62ad468f 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -90,8 +90,10 @@ #define GRAPHENE_DEFAULT_MIN_WITNESS_COUNT (11) #define GRAPHENE_DEFAULT_MIN_COMMITTEE_MEMBER_COUNT (11) +#define GRAPHENE_DEFAULT_MIN_SON_COUNT (5) #define GRAPHENE_DEFAULT_MAX_WITNESSES (1001) // SHOULD BE ODD #define GRAPHENE_DEFAULT_MAX_COMMITTEE (1001) // SHOULD BE ODD +#define GRAPHENE_DEFAULT_MAX_SONS (15) #define GRAPHENE_DEFAULT_MAX_PROPOSAL_LIFETIME_SEC (60*60*24*7*4) // Four weeks #define GRAPHENE_DEFAULT_COMMITTEE_PROPOSAL_REVIEW_PERIOD_SEC (60*60*24*7*2) // Two weeks #define GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE (20*GRAPHENE_1_PERCENT) @@ -173,6 +175,8 @@ #define GRAPHENE_PROXY_TO_SELF_ACCOUNT (graphene::chain::account_id_type(5)) /// #define GRAPHENE_RAKE_FEE_ACCOUNT_ID (graphene::chain::account_id_type(6)) +/// +#define GRAPHENE_SON_ACCOUNT_ID (graphene::chain::account_id_type(7)) /// Sentinel value used in the scheduler. #define GRAPHENE_NULL_WITNESS (graphene::chain::witness_id_type(0)) ///@} diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 179fb2df..5a2530f6 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -497,6 +497,7 @@ namespace graphene { namespace chain { void perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props); void update_active_witnesses(); void update_active_committee_members(); + void update_active_sons(); void update_worker_votes(); public: double calculate_vesting_factor(const account_object& stake_account); @@ -537,6 +538,7 @@ namespace graphene { namespace chain { vector _vote_tally_buffer; vector _witness_count_histogram_buffer; vector _committee_count_histogram_buffer; + vector _son_count_histogram_buffer; uint64_t _total_voting_stake; flat_map _checkpoints; diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index b976eea0..788ccdaf 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -150,4 +150,5 @@ FC_REFLECT_DERIVED( graphene::chain::global_property_object, (graphene::db::obje (next_available_vote_id) (active_committee_members) (active_witnesses) + (active_sons) ) diff --git a/libraries/chain/include/graphene/chain/immutable_chain_parameters.hpp b/libraries/chain/include/graphene/chain/immutable_chain_parameters.hpp index 0082383c..ade1a459 100644 --- a/libraries/chain/include/graphene/chain/immutable_chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/immutable_chain_parameters.hpp @@ -35,6 +35,7 @@ struct immutable_chain_parameters { uint16_t min_committee_member_count = GRAPHENE_DEFAULT_MIN_COMMITTEE_MEMBER_COUNT; uint16_t min_witness_count = GRAPHENE_DEFAULT_MIN_WITNESS_COUNT; + uint16_t min_son_count = GRAPHENE_DEFAULT_MIN_SON_COUNT; uint32_t num_special_accounts = 0; uint32_t num_special_assets = 0; }; @@ -44,6 +45,7 @@ struct immutable_chain_parameters FC_REFLECT( graphene::chain::immutable_chain_parameters, (min_committee_member_count) (min_witness_count) + (min_son_count) (num_special_accounts) (num_special_assets) ) diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index 87c2e3fe..2d97857e 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -61,6 +61,7 @@ namespace graphene { namespace chain { uint8_t maximum_asset_feed_publishers = GRAPHENE_DEFAULT_MAX_ASSET_FEED_PUBLISHERS; ///< the maximum number of feed publishers for a given asset uint16_t maximum_witness_count = GRAPHENE_DEFAULT_MAX_WITNESSES; ///< maximum number of active witnesses uint16_t maximum_committee_count = GRAPHENE_DEFAULT_MAX_COMMITTEE; ///< maximum number of active committee_members + uint16_t maximum_son_count = GRAPHENE_DEFAULT_MAX_SONS; ///< maximum number of active SONS uint16_t maximum_authority_membership = GRAPHENE_DEFAULT_MAX_AUTHORITY_MEMBERSHIP; ///< largest number of keys/accounts an authority can have uint16_t reserve_percent_of_fee = GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE; ///< the percentage of the network's allocation of a fee that is taken out of circulation uint16_t network_percent_of_fee = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; ///< percent of transaction fees paid to network @@ -150,6 +151,7 @@ FC_REFLECT( graphene::chain::chain_parameters, (maximum_asset_feed_publishers) (maximum_witness_count) (maximum_committee_count) + (maximum_son_count) (maximum_authority_membership) (reserve_percent_of_fee) (network_percent_of_fee)