From 61c6d7f572cdaefce9a932079ea710a7d20c8730 Mon Sep 17 00:00:00 2001 From: satyakoneru Date: Tue, 28 Jan 2020 20:42:30 +1100 Subject: [PATCH] SON206_Plugin_CrashFix_Reorg - Plugin Changes (#272) * SON206_Plugin_CrashFix_Reorg - Plugin Changes * SON206_Plugin_CrashFix_Reorg - add owner auths to consensus account --- libraries/chain/db_maint.cpp | 14 +++ .../include/graphene/chain/son_object.hpp | 2 +- .../peerplays_sidechain_plugin.cpp | 101 ++++++++++-------- 3 files changed, 73 insertions(+), 44 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 31813724..5d973a09 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -566,9 +566,14 @@ void database::update_active_sons() // Ensure that everyone has at least one vote. Zero weights aren't allowed. const son_object& son = get(son_info.son_id); uint16_t votes = std::max((_vote_tally_buffer[son.vote_id] >> bits_to_drop), uint64_t(1) ); + obj.owner.account_auths[son.son_account] += votes; + obj.owner.weight_threshold += votes; obj.active.account_auths[son.son_account] += votes; obj.active.weight_threshold += votes; } + obj.owner.weight_threshold *= 2; + obj.owner.weight_threshold /= 3; + obj.owner.weight_threshold += 1; obj.active.weight_threshold *= 2; obj.active.weight_threshold /= 3; obj.active.weight_threshold += 1; @@ -583,6 +588,10 @@ void database::update_active_sons() modify( get(gpo.parameters.get_son_btc_account_id()), [&]( account_object& obj ) { uint64_t total_votes = 0; + obj.owner.weight_threshold = 0; + obj.owner.account_auths.clear(); + obj.active.weight_threshold = 0; + obj.active.account_auths.clear(); for( const auto& son_info : gpo.active_sons ) { const son_object& son = get(son_info.son_id); @@ -596,9 +605,14 @@ void database::update_active_sons() // Ensure that everyone has at least one vote. Zero weights aren't allowed. const son_object& son = get(son_info.son_id); uint16_t votes = std::max((_vote_tally_buffer[son.vote_id] >> bits_to_drop), uint64_t(1) ); + obj.owner.account_auths[son.son_account] += votes; + obj.owner.weight_threshold += votes; obj.active.account_auths[son.son_account] += votes; obj.active.weight_threshold += votes; } + obj.owner.weight_threshold *= 2; + obj.owner.weight_threshold /= 3; + obj.owner.weight_threshold += 1; obj.active.weight_threshold *= 2; obj.active.weight_threshold /= 3; obj.active.weight_threshold += 1; diff --git a/libraries/chain/include/graphene/chain/son_object.hpp b/libraries/chain/include/graphene/chain/son_object.hpp index 50f7385a..5ce45242 100644 --- a/libraries/chain/include/graphene/chain/son_object.hpp +++ b/libraries/chain/include/graphene/chain/son_object.hpp @@ -97,7 +97,7 @@ namespace graphene { namespace chain { FC_REFLECT_ENUM(graphene::chain::son_status, (inactive)(active)(in_maintenance)(deregistered) ) FC_REFLECT_DERIVED( graphene::chain::son_object, (graphene::db::object), - (son_account)(vote_id)(total_votes)(url)(deposit)(signing_key)(pay_vb)(status)(sidechain_public_keys) ) + (son_account)(vote_id)(total_votes)(url)(deposit)(signing_key)(pay_vb)(statistics)(status)(sidechain_public_keys) ) FC_REFLECT_DERIVED( graphene::chain::son_statistics_object, (graphene::db::object), diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index 2874605b..2f57715a 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -27,9 +27,9 @@ class peerplays_sidechain_plugin_impl void plugin_startup(); void schedule_heartbeat_loop(); void heartbeat_loop(); - chain::proposal_create_operation create_son_down_proposal(chain::son_id_type son_id, fc::time_point_sec last_active_ts); void on_block_applied( const signed_block& b ); void on_objects_new(const vector& new_object_ids); + void create_son_down_proposals(); private: peerplays_sidechain_plugin& plugin; @@ -162,7 +162,7 @@ void peerplays_sidechain_plugin_impl::plugin_startup() if( !_sons.empty() && !_private_keys.empty() ) { ilog("Starting heartbeats for ${n} sons.", ("n", _sons.size())); - schedule_heartbeat_loop(); + heartbeat_loop(); } else elog("No sons configured! Please add SON IDs and private keys to configuration."); @@ -184,6 +184,7 @@ void peerplays_sidechain_plugin_impl::schedule_heartbeat_loop() void peerplays_sidechain_plugin_impl::heartbeat_loop() { + schedule_heartbeat_loop(); chain::database& d = plugin.database(); chain::son_id_type son_id = *(_sons.begin()); const auto& idx = d.get_index_type().indices().get(); @@ -210,7 +211,8 @@ void peerplays_sidechain_plugin_impl::heartbeat_loop() fc::future fut = fc::async( [&](){ try { d.push_transaction(trx); - plugin.app().p2p_node()->broadcast(net::trx_message(trx)); + if(plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(trx)); return true; } catch(fc::exception e){ ilog("peerplays_sidechain_plugin_impl: sending heartbeat failed with exception ${e}",("e", e.what())); @@ -219,28 +221,59 @@ void peerplays_sidechain_plugin_impl::heartbeat_loop() }); fut.wait(fc::seconds(10)); } - schedule_heartbeat_loop(); } -chain::proposal_create_operation peerplays_sidechain_plugin_impl::create_son_down_proposal(chain::son_id_type son_id, fc::time_point_sec last_active_ts) +void peerplays_sidechain_plugin_impl::create_son_down_proposals() { + auto create_son_down_proposal = [&](chain::son_id_type son_id, fc::time_point_sec last_active_ts) { + chain::database& d = plugin.database(); + chain::son_id_type my_son_id = *(_sons.begin()); + const chain::global_property_object& gpo = d.get_global_properties(); + const auto& idx = d.get_index_type().indices().get(); + auto son_obj = idx.find( my_son_id ); + + chain::son_report_down_operation son_down_op; + son_down_op.payer = gpo.parameters.get_son_btc_account_id(); + son_down_op.son_id = son_id; + son_down_op.down_ts = last_active_ts; + + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = son_obj->son_account; + proposal_op.proposed_ops.push_back( op_wrapper( son_down_op ) ); + uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3; + proposal_op.expiration_time = time_point_sec( d.head_block_time().sec_since_epoch() + lifetime ); + return proposal_op; + }; + chain::database& d = plugin.database(); - chain::son_id_type my_son_id = *(_sons.begin()); const chain::global_property_object& gpo = d.get_global_properties(); const auto& idx = d.get_index_type().indices().get(); - auto son_obj = idx.find( my_son_id ); - - chain::son_report_down_operation son_down_op; - son_down_op.payer = gpo.parameters.get_son_btc_account_id(); - son_down_op.son_id = son_id; - son_down_op.down_ts = last_active_ts; - - proposal_create_operation proposal_op; - proposal_op.fee_paying_account = son_obj->son_account; - proposal_op.proposed_ops.push_back( op_wrapper( son_down_op ) ); - uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3; - proposal_op.expiration_time = time_point_sec( d.head_block_time().sec_since_epoch() + lifetime ); - return proposal_op; + chain::son_id_type my_son_id = *(_sons.begin()); + for(auto son_inf: gpo.active_sons) { + if(my_son_id == son_inf.son_id) + continue; + auto son_obj = idx.find( son_inf.son_id ); + auto stats = son_obj->statistics(d); + fc::time_point_sec last_active_ts = stats.last_active_timestamp; + int64_t down_threshold = 2*180000000; + if(son_obj->status == chain::son_status::active && (fc::time_point::now() - last_active_ts) > fc::microseconds(down_threshold)) { + ilog("peerplays_sidechain_plugin: sending son down proposal for ${t} from ${s}",("t",std::string(object_id_type(son_obj->id)))("s",std::string(object_id_type(my_son_id)))); + chain::proposal_create_operation op = create_son_down_proposal(son_inf.son_id, last_active_ts); + chain::signed_transaction trx = d.create_signed_transaction(_private_keys.begin()->second, op); + fc::future fut = fc::async( [&](){ + try { + d.push_transaction(trx); + if(plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(trx)); + return true; + } catch(fc::exception e){ + ilog("peerplays_sidechain_plugin_impl: sending son down proposal failed with exception ${e}",("e", e.what())); + return false; + } + }); + fut.wait(fc::seconds(10)); + } + } } void peerplays_sidechain_plugin_impl::on_block_applied( const signed_block& b ) @@ -248,35 +281,15 @@ void peerplays_sidechain_plugin_impl::on_block_applied( const signed_block& b ) chain::database& d = plugin.database(); chain::son_id_type my_son_id = *(_sons.begin()); const chain::global_property_object& gpo = d.get_global_properties(); + bool latest_block = ((fc::time_point::now() - b.timestamp) < fc::microseconds(gpo.parameters.block_interval * 1000000)); // Return if there are no active SONs - if(gpo.active_sons.size() <= 0) { + if(gpo.active_sons.size() <= 0 || !latest_block) { return; } chain::son_id_type next_son_id = d.get_scheduled_son(1); if(next_son_id == my_son_id) { - const auto& idx = d.get_index_type().indices().get(); - for(auto son_inf: gpo.active_sons) { - auto son_obj = idx.find( son_inf.son_id ); - auto stats = son_obj->statistics(d); - fc::time_point_sec last_active_ts = stats.last_active_timestamp; - int64_t down_threshold = 2*180000000; - if((fc::time_point::now() - last_active_ts) > fc::microseconds(down_threshold)) { - chain::proposal_create_operation op = create_son_down_proposal(son_inf.son_id, last_active_ts); - chain::signed_transaction trx = d.create_signed_transaction(_private_keys.begin()->second, op); - fc::future fut = fc::async( [&](){ - try { - d.push_transaction(trx); - plugin.app().p2p_node()->broadcast(net::trx_message(trx)); - return true; - } catch(fc::exception e){ - ilog("peerplays_sidechain_plugin_impl: sending son down proposal failed with exception ${e}",("e", e.what())); - return false; - } - }); - fut.wait(fc::seconds(10)); - } - } + create_son_down_proposals(); } } @@ -302,6 +315,7 @@ void peerplays_sidechain_plugin_impl::on_objects_new(const vectorson_account; puo.proposal = id; @@ -310,7 +324,8 @@ void peerplays_sidechain_plugin_impl::on_objects_new(const vector fut = fc::async( [&](){ try { d.push_transaction(trx); - plugin.app().p2p_node()->broadcast(net::trx_message(trx)); + if(plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(trx)); return true; } catch(fc::exception e){ ilog("peerplays_sidechain_plugin_impl: sending approval failed with exception ${e}",("e", e.what()));