diff --git a/contracts/eosio.system/eosio.system.abi b/contracts/eosio.system/eosio.system.abi index e559ad30e0530dce25687e990685dd7f34039262..49044b11eea43d1b0873331051697fdc5c24184b 100644 --- a/contracts/eosio.system/eosio.system.abi +++ b/contracts/eosio.system/eosio.system.abi @@ -273,6 +273,7 @@ {"name":"owner", "type":"account_name"}, {"name":"total_votes", "type":"float64"}, {"name":"producer_key", "type":"public_key"}, + {"name":"is_active", "type":"bool"}, {"name":"url", "type":"string"}, {"name":"unpaid_blocks", "type":"uint32"}, {"name":"last_claim_time", "type":"uint64"}, diff --git a/contracts/eosio.system/eosio.system.hpp b/contracts/eosio.system/eosio.system.hpp index b2120247cdcd8033ee9b9c05af073ec47613f9ac..25420d076f049e9bf182be3e0ab31c4550d1a31d 100644 --- a/contracts/eosio.system/eosio.system.hpp +++ b/contracts/eosio.system/eosio.system.hpp @@ -74,6 +74,7 @@ namespace eosiosystem { account_name owner; double total_votes = 0; eosio::public_key producer_key; /// a packed public key object + bool is_active = true; std::string url; uint32_t unpaid_blocks = 0; uint64_t last_claim_time = 0; @@ -81,12 +82,13 @@ namespace eosiosystem { block_timestamp time_became_active; block_timestamp last_produced_block_time; - uint64_t primary_key()const { return owner; } - double by_votes()const { return -total_votes; } - bool active() const { return producer_key != public_key(); } + uint64_t primary_key()const { return owner; } + double by_votes()const { return is_active ? -total_votes : total_votes; } + bool active()const { return is_active; } + void deactivate() { producer_key = public_key(); is_active = false; } // explicit serialization macro is not necessary, used here only to improve compilation time - EOSLIB_SERIALIZE( producer_info, (owner)(total_votes)(producer_key)(url) + EOSLIB_SERIALIZE( producer_info, (owner)(total_votes)(producer_key)(is_active)(url) (unpaid_blocks)(last_claim_time)(location) (time_became_active)(last_produced_block_time) ) }; diff --git a/contracts/eosio.system/voting.cpp b/contracts/eosio.system/voting.cpp index 10e51902310b32941dcecfc6e6379ec64d78c185..c7e0cdeeeb1bf1b97412bda1d419db780755fd61 100644 --- a/contracts/eosio.system/voting.cpp +++ b/contracts/eosio.system/voting.cpp @@ -36,6 +36,7 @@ namespace eosiosystem { */ void system_contract::regproducer( const account_name producer, const eosio::public_key& producer_key, const std::string& url, uint16_t location ) { eosio_assert( url.size() < 512, "url too long" ); + eosio_assert( producer_key != eosio::public_key(), "public key should not be the default value" ); require_auth( producer ); auto prod = _producers.find( producer ); @@ -44,6 +45,7 @@ namespace eosiosystem { if( producer_key != prod->producer_key ) { _producers.modify( prod, producer, [&]( producer_info& info ){ info.producer_key = producer_key; + info.is_active = true; info.url = url; info.location = location; }); @@ -53,6 +55,7 @@ namespace eosiosystem { info.owner = producer; info.total_votes = 0; info.producer_key = producer_key; + info.is_active = true; info.url = url; info.location = location; }); @@ -65,7 +68,7 @@ namespace eosiosystem { const auto& prod = _producers.get( producer, "producer not found" ); _producers.modify( prod, 0, [&]( producer_info& info ){ - info.producer_key = eosio::public_key(); + info.deactivate(); }); } @@ -77,8 +80,8 @@ namespace eosiosystem { std::vector< std::pair > top_producers; top_producers.reserve(21); - for ( auto it = idx.cbegin(); it != idx.cend() && top_producers.size() < 21 && 0 < it->total_votes; ++it ) { - if( !it->active() ) continue; + std::vector inactive_iters; + for ( auto it = idx.cbegin(); it != idx.cend() && top_producers.size() < 21 && 0 < it->total_votes && it->active(); ++it ) { /** If it's the first time or it's been over a day since a producer was last voted in, @@ -92,11 +95,8 @@ namespace eosiosystem { }); } else if ( block_time.slot > (2 * 21 * 12 * 100) + it->time_became_active.slot && block_time.slot > it->last_produced_block_time.slot + blocks_per_day ) { - _producers.modify( *it, 0, [&](auto& p) { - p.producer_key = public_key(); - p.time_became_active.slot = 0; - }); - + // save producers that will be deactivated + inactive_iters.push_back(it); continue; } else { _producers.modify( *it, 0, [&](auto& p) { @@ -107,7 +107,12 @@ namespace eosiosystem { top_producers.emplace_back( std::pair({{it->owner, it->producer_key}, it->location})); } - + for (const auto& it: inactive_iters) { + _producers.modify( *it, 0, [&](auto& p) { + p.deactivate(); + p.time_became_active.slot = 0; + }); + } /// sort by producer name std::sort( top_producers.begin(), top_producers.end() ); @@ -234,7 +239,7 @@ namespace eosiosystem { eosio_assert( !voting || pitr->active() || !pd.second.second /* not from new set */, "producer is not currently registered" ); _producers.modify( pitr, 0, [&]( auto& p ) { p.total_votes += pd.second.first; - if ( p.total_votes < 0 ) { // floating point ariphmetics can give as small negative numbers + if ( p.total_votes < 0 ) { // floating point arithmetics can give small negative numbers p.total_votes = 0; } _gstate.total_producer_vote_weight += pd.second.first;