From 5812c402249210d5f6e761dfb38bc79b4381808a Mon Sep 17 00:00:00 2001 From: Wang Zhi Date: Mon, 17 Jun 2019 17:30:48 +0800 Subject: [PATCH] new data structure for new BP election algorithm --- contracts/eosio.system/eosio.system.abi | 62 +++++++ contracts/eosio.system/eosio.system.cpp | 3 +- contracts/eosio.system/eosio.system.hpp | 60 +++++++ contracts/eosio.system/voting.cpp | 215 +++++++++++++++++++++++- 4 files changed, 338 insertions(+), 2 deletions(-) diff --git a/contracts/eosio.system/eosio.system.abi b/contracts/eosio.system/eosio.system.abi index 2f0a18d60..ee5ea5291 100644 --- a/contracts/eosio.system/eosio.system.abi +++ b/contracts/eosio.system/eosio.system.abi @@ -31,6 +31,15 @@ {"name":"key", "type":"public_key"}, {"name":"weight", "type":"weight_type"} ] + },{ + "name": "prod_meta", + "base": "", + "fields": [ + {"name":"owner", "type":"account_name"}, + {"name":"total_votes", "type":"float64"}, + {"name":"all_stake", "type":"int64"}, + {"name":"is_active", "type":"bool"} + ] },{ "name": "bidname", "base": "", @@ -278,6 +287,27 @@ {"name":"unpaid_blocks", "type":"uint32"}, {"name":"last_claim_time", "type":"uint64"}, {"name":"location", "type":"uint16"} + ] + },{ + "name": "producer_info_ext", + "base": "", + "fields": [ + {"name":"owner", "type":"account_name"}, + {"name":"seq_num", "type":"uint16"}, + {"name":"all_stake", "type":"int64"} + + ] + },{ + "name": "producers_seq", + "base": "", + "fields": [ + {"name":"seq_num", "type":"uint16"}, + {"name":"prods_l1", "type":"prod_meta"}, + {"name":"prods_l2", "type":"prod_meta[]"}, + {"name":"prods_l3", "type":"prod_meta[]"}, + {"name":"prods_all", "type":"prod_meta[]"}, + + ] },{ "name": "regproducer", @@ -294,6 +324,18 @@ "fields": [ {"name":"producer", "type":"account_name"} ] + },{ + "name": "clsprods2", + "base": "", + "fields": [] + },{ + "name": "seqproducer", + "base": "", + "fields": [ + {"name":"producer", "type":"account_name"}, + {"name":"seq", "type":"uint16"}, + {"name":"level", "type":"uint8"} + ] },{ "name": "setram", "base": "", @@ -488,6 +530,14 @@ "name": "unregprod", "type": "unregprod", "ricardian_contract": "" + },{ + "name": "clsprods2", + "type": "clsprods2", + "ricardian_contract": "" + },{ + "name": "seqproducer", + "type": "seqproducer", + "ricardian_contract": "" },{ "name": "regproxy", "type": "regproxy", @@ -535,6 +585,18 @@ "index_type": "i64", "key_names" : ["owner"], "key_types" : ["uint64"] + },{ + "name": "producers2", + "type": "producer_info_ext", + "index_type": "i64", + "key_names" : ["owner"], + "key_types" : ["uint64"] + },{ + "name": "produderseq", + "type": "producers_seq", + "index_type": "i64", + "key_names" : ["seq_num"], + "key_types" : ["uint64"] },{ "name": "global", "type": "eosio_global_state", diff --git a/contracts/eosio.system/eosio.system.cpp b/contracts/eosio.system/eosio.system.cpp index 84bf6ef85..d86f59d92 100644 --- a/contracts/eosio.system/eosio.system.cpp +++ b/contracts/eosio.system/eosio.system.cpp @@ -13,6 +13,7 @@ namespace eosiosystem { :native(s), _voters(_self,_self), _producers(_self,_self), + _producers2(_self,_self), _global(_self,_self), _rammarket(_self,_self) { @@ -203,7 +204,7 @@ EOSIO_ABI( eosiosystem::system_contract, // delegate_bandwidth.cpp (buyrambytes)(buyram)(sellram)(delegatebw)(undelegatebw)(refund) // voting.cpp - (regproducer)(unregprod)(voteproducer)(regproxy) + (regproducer)(unregprod)(voteproducer)(regproxy)(clsprods2)(seqproducer) // producer_pay.cpp (onblock)(claimrewards) ) diff --git a/contracts/eosio.system/eosio.system.hpp b/contracts/eosio.system/eosio.system.hpp index 0a7fdcd87..9ffd1ca34 100644 --- a/contracts/eosio.system/eosio.system.hpp +++ b/contracts/eosio.system/eosio.system.hpp @@ -89,6 +89,40 @@ namespace eosiosystem { (unpaid_blocks)(last_claim_time)(location) ) }; + //##YTA-Change start: + struct producer_info_ext { + account_name owner; + uint16_t seq_num = 1; // from 1 to 21 + int64_t all_stake = 0; + uint64_t primary_key()const { return owner; } + + EOSLIB_SERIALIZE( producer_info_ext, (owner)(seq_num) ) + + }; + + struct prod_meta { + account_name owner; + double total_votes = 0; + int64_t all_stake = 0; + bool is_active = true; + + EOSLIB_SERIALIZE( prod_meta, (owner)(total_votes)(all_stake)(is_active) ) + }; + + struct producers_seq { + uint16_t seq_num = 1; // from 1 to 21 + prod_meta prods_l1; // only one + std::vector prods_l2; //max 5 + std::vector prods_l3; + std::vector prods_all; + + uint64_t primary_key()const { return seq_num; } + + EOSLIB_SERIALIZE( producers_seq, (seq_num)(prods_l1)(prods_l2)(prods_l3)(prods_all) ) + + }; + //##YTA-Change end: + struct voter_info { account_name owner = 0; /// the voter account_name proxy = 0; /// the proxy set by the voter, if any @@ -127,6 +161,12 @@ namespace eosiosystem { indexed_by > > producers_table; + //##YTA-Change start: + typedef eosio::multi_index< N(producers2), producer_info_ext> producers_ext_table; + typedef eosio::multi_index< N(produderseq), producers_seq> producers_seq_table; + //##YTA-Change end: + + typedef eosio::singleton global_state_singleton; //##YTA-Change start: @@ -141,6 +181,9 @@ namespace eosiosystem { private: voters_table _voters; producers_table _producers; + //##YTA-Change start: + producers_ext_table _producers2; + //##YTA-Change end: global_state_singleton _global; eosio_global_state _gstate; @@ -211,6 +254,22 @@ namespace eosiosystem { void unregprod( const account_name producer ); +//##YTA-Change start: + void clsprods2(); + + void seqproducer( const account_name producer, uint16_t seq , uint8_t level ); + + void rm_producer_seq( const account_name producer, uint16_t seq ); + + void add_producer_seq( const account_name producer, uint16_t seq , uint8_t level ); + + void active_producer_seq( const account_name producer, bool isactive); + + void update_producers_seq_totalvotes( uint16_t seq_num, account_name owner, double total_votes); + + + //##YTA-Change end: + void setram( uint64_t max_ram_size ); void voteproducer( const account_name voter, const account_name proxy, const std::vector& producers ); @@ -230,6 +289,7 @@ namespace eosiosystem { private: void update_elected_producers( block_timestamp timestamp ); + // Implementation details: //defind in delegate_bandwidth.cpp diff --git a/contracts/eosio.system/voting.cpp b/contracts/eosio.system/voting.cpp index bf82c9138..c4037b46f 100644 --- a/contracts/eosio.system/voting.cpp +++ b/contracts/eosio.system/voting.cpp @@ -48,6 +48,8 @@ namespace eosiosystem { info.url = url; info.location = location; }); + + active_producer_seq(producer, true); } else { _producers.emplace( producer, [&]( producer_info& info ){ info.owner = producer; @@ -68,8 +70,202 @@ namespace eosiosystem { _producers.modify( prod, 0, [&]( producer_info& info ){ info.deactivate(); }); + + active_producer_seq(producer, false); + } +//##YTA-Change start: + void system_contract::clsprods2() { + require_auth( _self ); + + while (_producers2.begin() != _producers2.end()) + _producers2.erase(_producers2.begin()); + + for( uint16_t seq = 1; seq <= 21; seq++ ) { + producers_seq_table _prod_seq( _self, seq ); + if( _prod_seq.begin() != _prod_seq.end() ) + _prod_seq.erase(_prod_seq.begin()); + } + } + + void system_contract::seqproducer( const account_name producer, uint16_t seq , uint8_t level ) { + require_auth( _self ); + + eosio_assert(seq >= 1 && seq <= 21 , "invalidate seq number"); + eosio_assert(level >= 1 && level <= 3 , "invalidate level number"); + //const auto& prod = _producers.get( producer, "producer not found" ); + + auto it = _producers2.find(producer); + if (it == _producers2.end()) { + _producers2.emplace(_self, [&](auto &row) { + row.owner = producer; + row.seq_num = seq; + }); + add_producer_seq(producer, seq, level); + } else { + uint16_t old_seq = it->seq_num; + _producers2.modify(it, _self, [&](auto &row) { + row.seq_num = seq; + }); + rm_producer_seq(producer, old_seq); + add_producer_seq(producer, seq, level); + } } + void system_contract::rm_producer_seq(const account_name producer, uint16_t seq) { + producers_seq_table _prodseq(_self, seq); + auto ps_itr = _prodseq.find (seq); + if( ps_itr == _prodseq.end() ) + return; + _prodseq.modify( ps_itr, _self, [&]( producers_seq& info ){ + if(info.prods_l1.owner == producer) { + info.prods_l1.owner = 0; + info.prods_l1.all_stake = 0; + info.prods_l1.total_votes = 0; + info.prods_l1.is_active = false; + } + + for( auto it2 = info.prods_l2.begin(); it2 != info.prods_l2.end(); it2++ ) { + if(it2->owner == producer) { + info.prods_l2.erase(it2); + break; + } + } + + for( auto it3 = info.prods_l3.begin(); it3 != info.prods_l3.end(); it3++ ) { + if(it3->owner == producer) { + info.prods_l3.erase(it3); + break; + } + } + + for( auto itall = info.prods_all.begin(); itall != info.prods_all.end(); itall++ ) { + if(itall->owner == producer) { + info.prods_all.erase(itall); + break; + } + } + }); + } + + void system_contract::add_producer_seq( const account_name producer, uint16_t seq , uint8_t level ) { + producers_seq_table _prodseq(_self, seq); + prod_meta prodm; + //need retrive from system producers table + const auto& prod = _producers.get( producer, "producer not found" ); + prodm.owner = producer; + prodm.all_stake = 0; + prodm.total_votes = prod.total_votes; + prodm.is_active = prod.is_active; + auto ps_itr = _prodseq.find (seq); + if( ps_itr == _prodseq.end() ) { + _prodseq.emplace(_self, [&](auto &row) { + row.seq_num = seq; + row.prods_all.push_back(prodm); + if(level == 1) { + row.prods_l1 = prodm; + } else if(level == 2) { + row.prods_l2.push_back(prodm); + } else if(level == 3) { + row.prods_l3.push_back(prodm); + } + }); + } else { + _prodseq.modify(ps_itr, _self, [&](auto &row) { + row.prods_all.push_back(prodm); + if(level == 1) { + row.prods_l1 = prodm; + } else if(level == 2) { + row.prods_l2.push_back(prodm); + } else if(level == 3) { + row.prods_l3.push_back(prodm); + } + + }); + } + } + + void system_contract::active_producer_seq( const account_name producer, bool isactive) { + auto it = _producers2.find(producer); + + if (it == _producers2.end()) + return; + + uint16_t seq = it->seq_num; + producers_seq_table _prodseq(_self, seq); + auto ps_itr = _prodseq.find (seq); + if( ps_itr == _prodseq.end() ) + return; + + _prodseq.modify( ps_itr, _self, [&]( producers_seq& info ){ + if(info.prods_l1.owner == producer) { + info.prods_l1.is_active = isactive; + } + + for( auto it2 = info.prods_l2.begin(); it2 != info.prods_l2.end(); it2++ ) { + if(it2->owner == producer) { + it2->is_active = isactive; + break; + } + } + + for( auto it3 = info.prods_l3.begin(); it3 != info.prods_l3.end(); it3++ ) { + if(it3->owner == producer) { + it3->is_active = isactive; + break; + } + } + + for( auto itall = info.prods_all.begin(); itall != info.prods_all.end(); itall++ ) { + if(itall->owner == producer) { + itall->is_active = isactive; + break; + } + } + }); + + } + + void system_contract::update_producers_seq_totalvotes( uint16_t seq_num, account_name owner, double total_votes) { + + producers_seq_table _prodseq(_self, seq_num); + auto ps_itr = _prodseq.find (seq_num); + + if( ps_itr == _prodseq.end() ) + return; + + _prodseq.modify( ps_itr, _self, [&]( producers_seq& info ){ + if( info.prods_l1.owner == owner ) { + info.prods_l1.total_votes = total_votes; + //return; + } + + for(auto it = info.prods_l2.begin(); it != info.prods_l2.end(); it++) { + if(it->owner == owner) { + it->total_votes = total_votes; + break; + } + } + + for(auto it = info.prods_l3.begin(); it != info.prods_l3.end(); it++) { + if(it->owner == owner) { + it->total_votes = total_votes; + break; + } + } + + for(auto it = info.prods_all.begin(); it != info.prods_all.end(); it++) { + if(it->owner == owner) { + it->total_votes = total_votes; + break; + } + } + + }); + } + + +//##YTA-Change ens: + void system_contract::update_elected_producers( block_timestamp block_time ) { _gstate.last_producer_schedule_update = block_time; @@ -135,7 +331,11 @@ namespace eosiosystem { eosio_assert( voter_name != proxy, "cannot proxy to self" ); require_recipient( proxy ); } else { - eosio_assert( producers.size() <= 30, "attempt to vote for too many producers" ); + //##YTA-Change start: + //eosio_assert( producers.size() <= 30, "attempt to vote for too many producers" ); + // One voter can only vote for one producer + eosio_assert( producers.size() <= 1, "attempt to vote for too many producers" ); + //##YTA-Change end: for( size_t i = 1; i < producers.size(); ++i ) { eosio_assert( producers[i-1] < producers[i], "producer votes must be unique and sorted" ); } @@ -201,6 +401,7 @@ namespace eosiosystem { } for( const auto& pd : producer_deltas ) { + double total_votes = 0; auto pitr = _producers.find( pd.first ); if( pitr != _producers.end() ) { eosio_assert( !voting || pitr->active() || !pd.second.second /* not from new set */, "producer is not currently registered" ); @@ -211,10 +412,22 @@ namespace eosiosystem { } _gstate.total_producer_vote_weight += pd.second.first; //eosio_assert( p.total_votes >= 0, "something bad happened" ); + total_votes = p.total_votes; }); } else { eosio_assert( !pd.second.second /* not from new set */, "producer is not registered" ); //data corruption } + //##YTA-Change start: + auto pitr2 = _producers2.find( pd.first ); + if( pitr2 != _producers2.end() ) { + //pitr2->seq_num + update_producers_seq_totalvotes(pitr2->seq_num, pd.first, total_votes); + } else { + eosio_assert( !pd.second.second /* not from new set */, "producer is not registered" ); //data corruption + } + //##YTA-Change end: + + } _voters.modify( voter, 0, [&]( auto& av ) { -- GitLab