Skip to content

Commit

Permalink
Added voting mechanism for SON
Browse files Browse the repository at this point in the history
  • Loading branch information
pixelplex-dev committed Jul 29, 2019
1 parent 988a177 commit b3786b3
Show file tree
Hide file tree
Showing 12 changed files with 409 additions and 21 deletions.
46 changes: 45 additions & 1 deletion libraries/chain/db_maint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ void database::update_active_witnesses()
void database::update_active_committee_members()
{ try {
assert( _committee_count_histogram_buffer.size() > 0 );
share_type stake_target = (_total_voting_stake-_witness_count_histogram_buffer[0]) / 2;
share_type stake_target = (_total_voting_stake - _committee_count_histogram_buffer[0]) / 2;

/// accounts that vote for 0 or 1 witness do not get to express an opinion on
/// the number of witnesses to have (they abstain and are non-voting accounts)
Expand Down Expand Up @@ -326,6 +326,37 @@ void database::update_active_committee_members()
});
} FC_CAPTURE_AND_RETHROW() }

void database::update_active_son_members()
{ try {
share_type stake_target = (_total_voting_stake-_son_count_histogram_buffer[0]) / 2;

/// accounts that vote for 0 or 1 sons do not get to express an opinion on
/// the number of sons to have (they abstain and are non-voting accounts)
uint64_t stake_tally = 0; // _son_count_histogram_buffer[0];
size_t son_member_count = 0;

if( stake_target > 0 )
while( (son_member_count < _son_count_histogram_buffer.size() - 1)
&& (stake_tally <= stake_target) )
stake_tally += _son_count_histogram_buffer[++son_member_count];

const chain_property_object& cpo = get_chain_properties();
auto son_members = sort_votable_objects<son_member_index>(std::max(son_member_count*2+1, (size_t)cpo.immutable_parameters.min_son_member_count));

for( const son_member_object& son : son_members )
{
modify( son, [&]( son_member_object& obj ) {
obj.total_votes = _vote_tally_buffer[son.vote_id];
});
}
modify(get_global_properties(), [&](global_property_object& gp) {
gp.active_son_members.clear();
std::transform(son_members.begin(), son_members.end(),
std::inserter(gp.active_son_members, gp.active_son_members.begin()),
[](const son_member_object& s) { return s.id; });
});
} 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();
Expand Down Expand Up @@ -1401,6 +1432,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_count / 2 + 1);
d._total_voting_stake = 0;

auto balance_type = vesting_balance_type::unspecified;
Expand Down Expand Up @@ -1503,6 +1535,16 @@ 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.
//
// same rationale as for witnesses
d._son_count_histogram_buffer[offset] += voting_stake;
}

d._total_voting_stake += voting_stake;
}
Expand Down Expand Up @@ -1533,11 +1575,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_son_members();
update_worker_votes();

modify(gpo, [this](global_property_object& p) {
Expand Down
3 changes: 3 additions & 0 deletions libraries/chain/include/graphene/chain/btc-sidechain/son.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ namespace graphene { namespace chain {
vote_id_type vote_id;
uint64_t total_votes = 0;
string url;

son_member_id_type get_id()const { return id; }

};

struct by_account;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ namespace graphene { namespace chain {

account_id_type fee_payer()const { return owner_account; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }

void validate()const {
FC_ASSERT( fee.amount >= 0 );
FC_ASSERT( url.size() < GRAPHENE_MAX_URL_LENGTH );
}
};

struct son_member_delete_operation : public base_operation
Expand All @@ -24,6 +29,10 @@ namespace graphene { namespace chain {

account_id_type fee_payer()const { return owner_account; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }

void validate()const {
FC_ASSERT( fee.amount >= 0 );
}
};

} } // namespace graphene::chain
Expand Down
3 changes: 3 additions & 0 deletions libraries/chain/include/graphene/chain/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,6 @@
#define TOURNAMENT_MAX_START_DELAY (60*60*24*7) // 1 week
#define GPOS_PERIOD (60*60*24*30*6) // 6 months
#define GPOS_SUBPERIOD (60*60*24*30) // 1 month

#define PEERPLAYS_DEFAULT_MAX_SON_MEMBER_COUNT (1001) // should be odd
#define PEERPLAYS_DEFAULT_MIN_SON_MEMBER_COUNT (11) // should be odd
4 changes: 4 additions & 0 deletions libraries/chain/include/graphene/chain/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,9 @@ 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();
public: // TODO: TEMP public method
void update_active_son_members();
private:
void update_worker_votes();
public:
double calculate_vesting_factor(const account_object& stake_account);
Expand Down Expand Up @@ -537,6 +540,7 @@ namespace graphene { namespace chain {
vector<uint64_t> _vote_tally_buffer;
vector<uint64_t> _witness_count_histogram_buffer;
vector<uint64_t> _committee_count_histogram_buffer;
vector<uint64_t> _son_count_histogram_buffer;
uint64_t _total_voting_stake;

flat_map<uint32_t,block_id_type> _checkpoints;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ struct immutable_chain_parameters
uint16_t min_witness_count = GRAPHENE_DEFAULT_MIN_WITNESS_COUNT;
uint32_t num_special_accounts = 0;
uint32_t num_special_assets = 0;

uint16_t min_son_member_count = PEERPLAYS_DEFAULT_MIN_SON_MEMBER_COUNT;
};

} } // graphene::chain
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ namespace graphene { namespace chain {
uint32_t maximum_tournament_start_time_in_future = TOURNAMENT_MAX_START_TIME_IN_FUTURE;
uint32_t maximum_tournament_start_delay = TOURNAMENT_MAX_START_DELAY;
uint16_t maximum_tournament_number_of_wins = TOURNAMENT_MAX_NUMBER_OF_WINS;

uint16_t maximum_son_count = PEERPLAYS_DEFAULT_MAX_SON_MEMBER_COUNT;

extension<parameter_extension> extensions;

/** defined in fee_schedule.cpp */
Expand Down
7 changes: 5 additions & 2 deletions libraries/chain/protocol/account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,15 +171,18 @@ void account_options::validate() const
{
auto needed_witnesses = num_witness;
auto needed_committee = num_committee;
auto needed_son = num_son;

for( vote_id_type id : votes )
if( id.type() == vote_id_type::witness && needed_witnesses )
--needed_witnesses;
else if ( id.type() == vote_id_type::committee && needed_committee )
--needed_committee;
else if ( id.type() == vote_id_type::son && needed_son )
--needed_son;

FC_ASSERT( needed_witnesses == 0 && needed_committee == 0,
"May not specify fewer witnesses or committee members than the number voted for.");
FC_ASSERT( needed_witnesses == 0 && needed_committee == 0 && needed_son == 0,
"May not specify fewer witnesses or committee members or son than the number voted for.");
}

void affiliate_reward_distribution::validate() const
Expand Down
45 changes: 45 additions & 0 deletions libraries/chain/son_operations_evaluator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <graphene/chain/btc-sidechain/son_operations_evaluator.hpp>

#include <graphene/chain/database.hpp>
#include <graphene/chain/btc-sidechain/son.hpp>

namespace graphene { namespace chain {

void_result create_son_evaluator::do_evaluate(const create_son_operation& op)
{ try{
FC_ASSERT(db().get(op.owner_account).is_lifetime_member(), "Only Lifetime members may register a SON.");
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }

object_id_type create_son_evaluator::do_apply(const create_son_operation& op)
{ try {
vote_id_type vote_id;
db().modify(db().get_global_properties(), [&vote_id](global_property_object& p) {
vote_id = get_next_vote_id(p, vote_id_type::son);
});

const auto& new_son_object = db().create<son_member_object>( [&]( son_member_object& obj ){
obj.son_member_account = op.owner_account;
obj.vote_id = vote_id;
obj.url = op.url;
});
return new_son_object.id;
} FC_CAPTURE_AND_RETHROW( (op) ) }

void_result delete_son_evaluator::do_evaluate(const delete_son_operation& op)
{ try {
database& d = db();
const auto& idx = d.get_index_type<son_member_index>().indices().get<by_account>();
FC_ASSERT( idx.find(op.owner_account) != idx.end() );
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }

void_result delete_son_evaluator::do_apply(const delete_son_operation& op)
{ try {
const auto& idx = db().get_index_type<son_member_index>().indices().get<by_account>();
db().remove(*idx.find(op.owner_account));
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }

} } // namespace graphene::chain

17 changes: 10 additions & 7 deletions libraries/wallet/include/graphene/wallet/wallet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1430,7 +1430,7 @@ class wallet_api
* This command allows you to add or remove one or more witnesses from this list
* in one call. When you are changing your vote on several witnesses, this
* may be easier than multiple `vote_for_witness` and
* `set_desired_witness_and_committee_member_count` calls.
* `set_desired_witness_committee_son_member_count` calls.
*
* @note you cannot vote against a witness, you can only vote for the witness
* or not vote for the witness.
Expand Down Expand Up @@ -1476,12 +1476,12 @@ class wallet_api
optional<string> voting_account,
bool broadcast = false);

/** Set your vote for the number of witnesses and committee_members in the system.
/** Set your vote for the number of witnesses, committee_members and son_members in the system.
*
* Each account can voice their opinion on how many committee_members and how many
* witnesses there should be in the active committee_member/active witness list. These
* witnesses and how many sons there should be in the active committee_member/active witness/active son_member list. These
* are independent of each other. You must vote your approval of at least as many
* committee_members or witnesses as you claim there should be (you can't say that there should
* committee_members or witnesses or son_members as you claim there should be (you can't say that there should
* be 20 committee_members but only vote for 10).
*
* There are maximum values for each set in the blockchain parameters (currently
Expand All @@ -1491,14 +1491,17 @@ class wallet_api
* set, your preferences will be ignored.
*
* @param account_to_modify the name or id of the account to update
* @param number_of_committee_members the number
* @param desired_number_of_witnesses number of witnesses
* @param desired_number_of_committee_members number of committee members
* @param desired_number_of_son_members number of son members
*
* @param broadcast true if you wish to broadcast the transaction
* @return the signed transaction changing your vote proxy settings
*/
signed_transaction set_desired_witness_and_committee_member_count(string account_to_modify,
signed_transaction set_desired_witness_committee_son_member_count(string account_to_modify,
uint16_t desired_number_of_witnesses,
uint16_t desired_number_of_committee_members,
uint16_t desired_number_of_son_members,
bool broadcast = false);

/** Signs a transaction.
Expand Down Expand Up @@ -1991,7 +1994,7 @@ FC_API( graphene::wallet::wallet_api,
(vote_for_witness)
(update_witness_votes)
(set_voting_proxy)
(set_desired_witness_and_committee_member_count)
(set_desired_witness_committee_son_member_count)
(get_account)
(get_account_id)
(get_block)
Expand Down
18 changes: 11 additions & 7 deletions libraries/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2164,19 +2164,22 @@ class wallet_api_impl
return sign_transaction( tx, broadcast );
} FC_CAPTURE_AND_RETHROW( (account_to_modify)(voting_account)(broadcast) ) }

signed_transaction set_desired_witness_and_committee_member_count(string account_to_modify,
signed_transaction set_desired_witness_committee_son_member_count(string account_to_modify,
uint16_t desired_number_of_witnesses,
uint16_t desired_number_of_committee_members,
uint16_t desired_number_of_son_members,
bool broadcast /* = false */)
{ try {
account_object account_object_to_modify = get_account(account_to_modify);

if (account_object_to_modify.options.num_witness == desired_number_of_witnesses &&
account_object_to_modify.options.num_committee == desired_number_of_committee_members)
FC_THROW("Account ${account} is already voting for ${witnesses} witnesses and ${committee_members} committee_members",
("account", account_to_modify)("witnesses", desired_number_of_witnesses)("committee_members",desired_number_of_witnesses));
account_object_to_modify.options.num_committee == desired_number_of_committee_members &&
account_object_to_modify.options.num_son == desired_number_of_son_members)
FC_THROW("Account ${account} is already voting for ${witnesses} witnesses, ${committee_members} committee_members and ${son_members} son_members",
("account", account_to_modify)("witnesses", desired_number_of_witnesses)("committee_members",desired_number_of_witnesses)("son_members", desired_number_of_son_members));
account_object_to_modify.options.num_witness = desired_number_of_witnesses;
account_object_to_modify.options.num_committee = desired_number_of_committee_members;
account_object_to_modify.options.num_son = desired_number_of_son_members;

account_update_operation account_update_op;
account_update_op.account = account_object_to_modify.id;
Expand Down Expand Up @@ -4110,13 +4113,14 @@ signed_transaction wallet_api::set_voting_proxy(string account_to_modify,
return my->set_voting_proxy(account_to_modify, voting_account, broadcast);
}

signed_transaction wallet_api::set_desired_witness_and_committee_member_count(string account_to_modify,
signed_transaction wallet_api::set_desired_witness_committee_son_member_count(string account_to_modify,
uint16_t desired_number_of_witnesses,
uint16_t desired_number_of_committee_members,
uint16_t desired_number_of_son_members,
bool broadcast /* = false */)
{
return my->set_desired_witness_and_committee_member_count(account_to_modify, desired_number_of_witnesses,
desired_number_of_committee_members, broadcast);
return my->set_desired_witness_committee_son_member_count(account_to_modify, desired_number_of_witnesses,
desired_number_of_committee_members, desired_number_of_son_members, broadcast);
}

void wallet_api::set_wallet_filename(string wallet_filename)
Expand Down
Loading

0 comments on commit b3786b3

Please sign in to comment.