diff --git a/libraries/chain/db_getter.cpp b/libraries/chain/db_getter.cpp index 272f6eb3..ba08fdef 100644 --- a/libraries/chain/db_getter.cpp +++ b/libraries/chain/db_getter.cpp @@ -231,10 +231,13 @@ bool database::is_son_dereg_valid( son_id_type son_id ) { const auto& son_idx = get_index_type().indices().get< by_id >(); auto son = son_idx.find( son_id ); - FC_ASSERT( son != son_idx.end() ); - bool ret = ( son->status == son_status::in_maintenance && + if(son == son_idx.end()) + { + return false; + } + + return (son->status == son_status::in_maintenance && (head_block_time() - son->statistics(*this).last_down_timestamp >= fc::seconds(get_global_properties().parameters.son_deregister_time()))); - return ret; } const account_statistics_object& database::get_account_stats_by_owner( account_id_type owner )const diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index f22bebc9..d15d4eee 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -37,6 +37,9 @@ public: const son_object get_current_son_object(); const son_object get_son_object(son_id_type son_id); bool is_active_son(son_id_type son_id); + bool is_son_delete_op_valid(const chain::operation &op); + bool is_son_down_op_valid(const chain::operation &op); + bool is_valid_son_proposal(const chain::proposal_object &proposal); fc::ecc::private_key get_private_key(son_id_type son_id); fc::ecc::private_key get_private_key(chain::public_key_type public_key); @@ -263,6 +266,32 @@ bool peerplays_sidechain_plugin_impl::is_active_son(son_id_type son_id) { return (it != active_son_ids.end()); } +bool peerplays_sidechain_plugin_impl::is_son_delete_op_valid(const chain::operation &op) { + son_delete_operation delete_op = op.get(); + return plugin.database().is_son_dereg_valid(delete_op.son_id); +} + +bool peerplays_sidechain_plugin_impl::is_son_down_op_valid(const chain::operation &op) { + chain::database &d = plugin.database(); + const chain::global_property_object &gpo = d.get_global_properties(); + const chain::dynamic_global_property_object &dgpo = d.get_dynamic_global_properties(); + const auto &idx = d.get_index_type().indices().get(); + son_report_down_operation down_op = op.get(); + auto son_obj = idx.find(down_op.son_id); + if (son_obj == idx.end()) { + return false; + } + auto stats = son_obj->statistics(d); + fc::time_point_sec last_maintenance_time = dgpo.next_maintenance_time - gpo.parameters.maintenance_interval; + fc::time_point_sec last_active_ts = ((stats.last_active_timestamp > last_maintenance_time) ? stats.last_active_timestamp : last_maintenance_time); + int64_t down_threshold = gpo.parameters.son_down_time(); + if (((son_obj->status == chain::son_status::active) || (son_obj->status == chain::son_status::request_maintenance)) && + ((fc::time_point::now() - last_active_ts) > fc::seconds(down_threshold))) { + return true; + } + return false; +} + fc::ecc::private_key peerplays_sidechain_plugin_impl::get_private_key(son_id_type son_id) { return get_private_key(get_son_object(son_id).signing_key); } @@ -382,13 +411,56 @@ void peerplays_sidechain_plugin_impl::son_processing() { } } +bool peerplays_sidechain_plugin_impl::is_valid_son_proposal(const chain::proposal_object &proposal) { + if (proposal.proposed_transaction.operations.size() == 1) { + int32_t op_idx_0 = proposal.proposed_transaction.operations[0].which(); + chain::operation op = proposal.proposed_transaction.operations[0]; + + if (op_idx_0 == chain::operation::tag::value) { + return is_son_down_op_valid(op); + } + + if (op_idx_0 == chain::operation::tag::value) { + return is_son_delete_op_valid(op); + } + + if (op_idx_0 == chain::operation::tag::value) { + return true; + } + + if (op_idx_0 == chain::operation::tag::value) { + return true; + } + + if (op_idx_0 == chain::operation::tag::value) { + return true; + } + } else if (proposal.proposed_transaction.operations.size() == 2) { + int32_t op_idx_0 = proposal.proposed_transaction.operations[0].which(); + int32_t op_idx_1 = proposal.proposed_transaction.operations[1].which(); + + if ((op_idx_0 == chain::operation::tag::value) && + (op_idx_1 == chain::operation::tag::value)) { + return true; + } + } + + ilog("=================================================="); + ilog("Proposal not approved ${proposal}", ("proposal", proposal)); + ilog("=================================================="); + return false; +} + void peerplays_sidechain_plugin_impl::approve_proposals() { - auto approve_proposal = [&](const chain::son_id_type &son_id, const chain::proposal_id_type &proposal_id) { - ilog("Sending approval for ${p} from ${s}", ("p", proposal_id)("s", son_id)); + auto check_approve_proposal = [&](const chain::son_id_type &son_id, const chain::proposal_object &proposal) { + if (!is_valid_son_proposal(proposal)) { + return; + } + ilog("Sending approval for ${p} from ${s}", ("p", proposal.id)("s", son_id)); chain::proposal_update_operation puo; puo.fee_paying_account = get_son_object(son_id).son_account; - puo.proposal = proposal_id; + puo.proposal = proposal.id; puo.active_approvals_to_add = {get_son_object(son_id).son_account}; chain::signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), puo); fc::future fut = fc::async([&]() { @@ -424,49 +496,7 @@ void peerplays_sidechain_plugin_impl::approve_proposals() { continue; } - if (proposal.proposed_transaction.operations.size() == 1) { - int32_t op_idx_0 = proposal.proposed_transaction.operations[0].which(); - - if (op_idx_0 == chain::operation::tag::value) { - approve_proposal(get_current_son_id(), proposal.id); - continue; - } - - if (op_idx_0 == chain::operation::tag::value) { - approve_proposal(get_current_son_id(), proposal.id); - continue; - } - - if (op_idx_0 == chain::operation::tag::value) { - approve_proposal(get_current_son_id(), proposal.id); - continue; - } - - if (op_idx_0 == chain::operation::tag::value) { - approve_proposal(get_current_son_id(), proposal.id); - continue; - } - - if (op_idx_0 == chain::operation::tag::value) { - approve_proposal(get_current_son_id(), proposal.id); - continue; - } - } - - if (proposal.proposed_transaction.operations.size() == 2) { - int32_t op_idx_0 = proposal.proposed_transaction.operations[0].which(); - int32_t op_idx_1 = proposal.proposed_transaction.operations[1].which(); - - if ((op_idx_0 == chain::operation::tag::value) && - (op_idx_1 == chain::operation::tag::value)) { - approve_proposal(get_current_son_id(), proposal.id); - continue; - } - } - - ilog("=================================================="); - ilog("Proposal not approved ${proposal}", ("proposal", proposal)); - ilog("=================================================="); + check_approve_proposal(get_current_son_id(), proposal); } }