From f7980f525235c643225543229266ddefcd1e4647 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Fri, 18 Sep 2015 14:05:38 -0400 Subject: [PATCH] scheduler: Refactor 26007bb655557697689da612aefad31d3653aa35 to use witness_schedule_object The functionality is equivalent, but it now uses a separate witness_schedule_object, and the code now lives in db_witness_schedule.cpp. --- libraries/app/api.cpp | 1 + libraries/chain/db_block.cpp | 33 +------------- libraries/chain/db_init.cpp | 10 ++++- libraries/chain/db_witness_schedule.cpp | 44 +++++++++++++++++-- .../chain/include/graphene/chain/database.hpp | 3 +- .../graphene/chain/global_property_object.hpp | 2 - .../include/graphene/chain/protocol/types.hpp | 6 ++- .../chain/witness_schedule_object.hpp | 42 ++++++++++++++++++ 8 files changed, 100 insertions(+), 41 deletions(-) create mode 100644 libraries/chain/include/graphene/chain/witness_schedule_object.hpp diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 3fad3833..cf5239af 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -292,6 +292,7 @@ namespace graphene { namespace app { } case impl_block_summary_object_type:{ } case impl_account_transaction_history_object_type:{ } case impl_chain_property_object_type: { + } case impl_witness_schedule_object_type: { } } } diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index 6aa259e8..78533129 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -485,7 +485,7 @@ void database::_apply_block( const signed_block& next_block ) // update_global_dynamic_data() as perhaps these methods only need // to be called for header validation? update_maintenance_flag( maint_needed ); - shuffle_witnesses(); + update_witness_schedule(); // notify observers that the block has been applied applied_block( next_block ); //emit @@ -494,37 +494,6 @@ void database::_apply_block( const signed_block& next_block ) notify_changed_objects(); } FC_CAPTURE_AND_RETHROW( (next_block.block_num()) ) } -void database::shuffle_witnesses() { - const auto& dgp = get_global_properties(); - if( head_block_num() % dgp.active_witnesses.size() == 0 ) { - modify( dgp, [&]( global_property_object& props ) { - props.current_shuffled_witnesses.clear(); - props.current_shuffled_witnesses.reserve( props.active_witnesses.size() ); - - for( auto w : props.active_witnesses ) - props.current_shuffled_witnesses.push_back(w); - - auto now_hi = uint64_t(head_block_time().sec_since_epoch()) << 32; - for( uint32_t i = 0; i < props.current_shuffled_witnesses.size(); ++i ) - { - /// High performance random generator - /// http://xorshift.di.unimi.it/ - uint64_t k = now_hi + uint64_t(i)*2685821657736338717ULL; - k ^= (k >> 12); - k ^= (k << 25); - k ^= (k >> 27); - k *= 2685821657736338717ULL; - - uint32_t jmax = props.current_shuffled_witnesses.size() - i; - uint32_t j = i + k%jmax; - std::swap( props.current_shuffled_witnesses[i], - props.current_shuffled_witnesses[j] ); - } - // edump( (props.current_shuffled_witnesses) ); - }); - } -} - void database::notify_changed_objects() { try { if( _undo_db.enabled() ) diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index ecb79309..eb01d668 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -192,6 +193,7 @@ 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) @@ -592,7 +594,6 @@ void database::init_genesis(const genesis_state_type& genesis_state) { p.active_witnesses.insert(i); p.witness_accounts.insert(get(witness_id_type(i)).witness_account); - p.current_shuffled_witnesses.push_back( witness_id_type(i) ); } }); @@ -601,6 +602,13 @@ void database::init_genesis(const genesis_state_type& genesis_state) p.parameters.current_fees = genesis_state.initial_parameters.current_fees; }); + // Create witness scheduler + create([&]( witness_schedule_object& wso ) + { + for( const witness_id_type& wid : get_global_properties().active_witnesses ) + wso.current_shuffled_witnesses.push_back( wid ); + }); + _undo_db.enable(); } FC_CAPTURE_AND_RETHROW() } diff --git a/libraries/chain/db_witness_schedule.cpp b/libraries/chain/db_witness_schedule.cpp index 5c56ca9a..7ff53896 100644 --- a/libraries/chain/db_witness_schedule.cpp +++ b/libraries/chain/db_witness_schedule.cpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace graphene { namespace chain { @@ -27,10 +28,10 @@ using boost::container::flat_set; witness_id_type database::get_scheduled_witness( uint32_t slot_num )const { - const auto& dgp = get_dynamic_global_properties(); - const auto& gp = get_global_properties(); - auto current_aslot = dgp.current_aslot + slot_num; - return gp.current_shuffled_witnesses[current_aslot%gp.current_shuffled_witnesses.size()]; + const dynamic_global_property_object& dpo = get_dynamic_global_properties(); + const witness_schedule_object& wso = witness_schedule_id_type()(*this); + uint64_t current_aslot = dpo.current_aslot + slot_num; + return wso.current_shuffled_witnesses[ current_aslot % wso.current_shuffled_witnesses.size() ]; } fc::time_point_sec database::get_slot_time(uint32_t slot_num)const @@ -81,4 +82,39 @@ uint32_t database::witness_participation_rate()const return uint64_t(GRAPHENE_100_PERCENT) * dpo.recent_slots_filled.popcount() / 128; } +void database::update_witness_schedule() +{ + const witness_schedule_object& wso = witness_schedule_id_type()(*this); + const global_property_object& gpo = get_global_properties(); + + if( head_block_num() % gpo.active_witnesses.size() == 0 ) + { + modify( wso, [&]( witness_schedule_object& _wso ) + { + _wso.current_shuffled_witnesses.clear(); + _wso.current_shuffled_witnesses.reserve( gpo.active_witnesses.size() ); + + for( const witness_id_type& w : gpo.active_witnesses ) + _wso.current_shuffled_witnesses.push_back( w ); + + auto now_hi = uint64_t(head_block_time().sec_since_epoch()) << 32; + for( uint32_t i = 0; i < _wso.current_shuffled_witnesses.size(); ++i ) + { + /// High performance random generator + /// http://xorshift.di.unimi.it/ + uint64_t k = now_hi + uint64_t(i)*2685821657736338717ULL; + k ^= (k >> 12); + k ^= (k << 25); + k ^= (k >> 27); + k *= 2685821657736338717ULL; + + uint32_t jmax = _wso.current_shuffled_witnesses.size() - i; + uint32_t j = i + k%jmax; + std::swap( _wso.current_shuffled_witnesses[i], + _wso.current_shuffled_witnesses[j] ); + } + }); + } +} + } } diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 66215923..59d3c4c5 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -227,6 +227,8 @@ namespace graphene { namespace chain { */ uint32_t get_slot_at_time(fc::time_point_sec when)const; + void update_witness_schedule(); + //////////////////// db_getter.cpp //////////////////// const chain_id_type& get_chain_id()const; @@ -424,7 +426,6 @@ namespace graphene { namespace chain { void update_expired_feeds(); void update_maintenance_flag( bool new_maintenance_flag ); void update_withdraw_permissions(); - void shuffle_witnesses(); ///Steps performed only at maintenance intervals ///@{ diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index bb761cc7..568ded67 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -47,7 +47,6 @@ namespace graphene { namespace chain { flat_set active_witnesses; // updated once per maintenance interval // n.b. witness scheduling is done by witness_schedule object flat_set witness_accounts; // updated once per maintenance interval - vector current_shuffled_witnesses; }; /** @@ -138,5 +137,4 @@ FC_REFLECT_DERIVED( graphene::chain::global_property_object, (graphene::db::obje (next_available_vote_id) (active_committee_members) (active_witnesses) - (current_shuffled_witnesses) ) diff --git a/libraries/chain/include/graphene/chain/protocol/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp index c34aa1b0..0030c1f1 100644 --- a/libraries/chain/include/graphene/chain/protocol/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -141,7 +141,8 @@ namespace graphene { namespace chain { impl_block_summary_object_type, impl_account_transaction_history_object_type, impl_blinded_balance_object_type, - impl_chain_property_object_type + impl_chain_property_object_type, + impl_witness_schedule_object_type }; enum meta_info_object_type @@ -194,6 +195,7 @@ namespace graphene { namespace chain { class block_summary_object; class account_transaction_history_object; class chain_property_object; + class witness_schedule_object; typedef object_id< implementation_ids, impl_global_property_object_type, global_property_object> global_property_id_type; typedef object_id< implementation_ids, impl_dynamic_global_property_object_type, dynamic_global_property_object> dynamic_global_property_id_type; @@ -208,6 +210,7 @@ namespace graphene { namespace chain { impl_account_transaction_history_object_type, account_transaction_history_object> account_transaction_history_id_type; typedef object_id< implementation_ids, impl_chain_property_object_type, chain_property_object> chain_property_id_type; + typedef object_id< implementation_ids, impl_witness_schedule_object_type, witness_schedule_object> witness_schedule_id_type; typedef fc::array symbol_type; typedef fc::ripemd160 block_id_type; @@ -284,6 +287,7 @@ FC_REFLECT_ENUM( graphene::chain::impl_object_type, (impl_account_transaction_history_object_type) (impl_blinded_balance_object_type) (impl_chain_property_object_type) + (impl_witness_schedule_object_type) ) FC_REFLECT_ENUM( graphene::chain::meta_info_object_type, (meta_account_object_type)(meta_asset_object_type) ) diff --git a/libraries/chain/include/graphene/chain/witness_schedule_object.hpp b/libraries/chain/include/graphene/chain/witness_schedule_object.hpp new file mode 100644 index 00000000..384936f5 --- /dev/null +++ b/libraries/chain/include/graphene/chain/witness_schedule_object.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015, Cryptonomex, Inc. + * All rights reserved. + * + * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and + * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, + * are permitted until September 8, 2015, provided that the following conditions are met: + * + * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#pragma once +#include +#include +#include + +namespace graphene { namespace chain { + +class witness_schedule_object; + +class witness_schedule_object : public graphene::db::abstract_object +{ + public: + static const uint8_t space_id = implementation_ids; + static const uint8_t type_id = impl_witness_schedule_object_type; + + vector< witness_id_type > current_shuffled_witnesses; +}; + +} } + +FC_REFLECT_DERIVED( + graphene::chain::witness_schedule_object, + (graphene::db::object), + (current_shuffled_witnesses) +)