From 85b81cb32b4092490a2d22f7d36a4027c9693958 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Tue, 10 Mar 2020 17:59:32 +0100 Subject: [PATCH 1/3] Quickfix, remove dead code, return result from wallet withdraw do_evaluate --- libraries/chain/son_wallet_deposit_evaluator.cpp | 1 - libraries/chain/son_wallet_withdraw_evaluator.cpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/son_wallet_deposit_evaluator.cpp b/libraries/chain/son_wallet_deposit_evaluator.cpp index 2f5a4f6b..839c5183 100644 --- a/libraries/chain/son_wallet_deposit_evaluator.cpp +++ b/libraries/chain/son_wallet_deposit_evaluator.cpp @@ -52,7 +52,6 @@ void_result process_son_wallet_deposit_evaluator::do_evaluate(const son_wallet_d const auto& idx = db().get_index_type().indices().get(); const auto& itr = idx.find(op.son_wallet_deposit_id); FC_ASSERT(itr != idx.end(), "Son wallet transfer not found"); - //FC_ASSERT(itr->processed == false, "Son wallet transfer is already processed"); const database& d = db(); diff --git a/libraries/chain/son_wallet_withdraw_evaluator.cpp b/libraries/chain/son_wallet_withdraw_evaluator.cpp index d3a32a1b..baf9b06a 100644 --- a/libraries/chain/son_wallet_withdraw_evaluator.cpp +++ b/libraries/chain/son_wallet_withdraw_evaluator.cpp @@ -50,6 +50,7 @@ void_result process_son_wallet_withdraw_evaluator::do_evaluate(const son_wallet_ const auto& idx = db().get_index_type().indices().get(); const auto& itr = idx.find(op.son_wallet_withdraw_id); FC_ASSERT(itr != idx.end(), "Son wallet withdraw not found"); + return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } object_id_type process_son_wallet_withdraw_evaluator::do_apply(const son_wallet_withdraw_process_operation& op) From f1e5171be0633e17f48cd7f87bd43676bee43fc6 Mon Sep 17 00:00:00 2001 From: sierra19XX <15652887+sierra19XX@users.noreply.github.com> Date: Wed, 11 Mar 2020 20:31:20 +1100 Subject: [PATCH 2/3] SON275 - ZMQ Crash on application exit (#306) * SON275 - ZMQ Crash on application exit * SON275 - Fix Indentation Co-authored-by: satyakoneru <15652887+satyakoneru@users.noreply.github.com> --- libraries/chain/db_maint.cpp | 2 +- libraries/chain/include/graphene/chain/config.hpp | 1 + .../graphene/chain/protocol/chain_parameters.hpp | 5 +++++ .../sidechain_net_handler_bitcoin.cpp | 14 +++++++++----- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 16a9ff95..def394a8 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -123,7 +123,7 @@ void database::pay_sons() time_point_sec now = head_block_time(); const dynamic_global_property_object& dpo = get_dynamic_global_properties(); // Current requirement is that we have to pay every 24 hours, so the following check - if( dpo.son_budget.value > 0 && now - dpo.last_son_payout_time >= fc::days(1)) { + if( dpo.son_budget.value > 0 && ((now - dpo.last_son_payout_time) >= fc::seconds(get_global_properties().parameters.son_pay_time()))) { uint64_t total_txs_signed = 0; share_type son_budget = dpo.son_budget; get_index_type().inspect_all_objects([this, &total_txs_signed](const object& o) { diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 65f4ab47..7e58bf0d 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -237,6 +237,7 @@ #define SON_DEREGISTER_TIME (60*60*12) // 12 Hours in seconds #define SON_HEARTBEAT_FREQUENCY (60*3) // 3 minutes in seconds #define SON_DOWN_TIME (60*3*2) // 2 Heartbeats in seconds +#define SON_PAY_TIME (60*60*24) // 1 day #define MIN_SON_PAY_DAILY_MAX (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(200)) #define SWEEPS_DEFAULT_DISTRIBUTION_PERCENTAGE (2*GRAPHENE_1_PERCENT) #define SWEEPS_DEFAULT_DISTRIBUTION_ASSET (graphene::chain::asset_id_type(0)) diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index cd870a2e..65b0d3c0 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -46,6 +46,7 @@ namespace graphene { namespace chain { optional < uint32_t > son_vesting_amount; optional < uint32_t > son_vesting_period; optional < uint32_t > son_pay_daily_max; + optional < uint32_t > son_pay_time; optional < uint32_t > son_deregister_time; optional < uint32_t > son_heartbeat_frequency; optional < uint32_t > son_down_time; @@ -141,6 +142,9 @@ namespace graphene { namespace chain { inline uint16_t son_pay_daily_max()const { return extensions.value.son_pay_daily_max.valid() ? *extensions.value.son_pay_daily_max : MIN_SON_PAY_DAILY_MAX; } + inline uint16_t son_pay_time()const { + return extensions.value.son_pay_time.valid() ? *extensions.value.son_pay_time : SON_PAY_TIME; + } inline uint16_t son_deregister_time()const { return extensions.value.son_deregister_time.valid() ? *extensions.value.son_deregister_time : SON_DEREGISTER_TIME; } @@ -167,6 +171,7 @@ FC_REFLECT( graphene::chain::parameter_extension, (son_vesting_amount) (son_vesting_period) (son_pay_daily_max) + (son_pay_time) (son_deregister_time) (son_heartbeat_frequency) (son_down_time) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index 7eaa4d44..1b1889bc 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -535,18 +535,22 @@ std::vector zmq_listener::receive_multipart() { } void zmq_listener::handle_zmq() { + int linger = 0; socket.setsockopt(ZMQ_SUBSCRIBE, "hashblock", 9); + socket.setsockopt(ZMQ_LINGER, &linger, sizeof(linger)); //socket.setsockopt( ZMQ_SUBSCRIBE, "hashtx", 6 ); //socket.setsockopt( ZMQ_SUBSCRIBE, "rawblock", 8 ); //socket.setsockopt( ZMQ_SUBSCRIBE, "rawtx", 5 ); socket.connect("tcp://" + ip + ":" + std::to_string(zmq_port)); while (true) { - auto msg = receive_multipart(); - const auto header = std::string(static_cast(msg[0].data()), msg[0].size()); - const auto block_hash = boost::algorithm::hex(std::string(static_cast(msg[1].data()), msg[1].size())); - - event_received(block_hash); + try { + auto msg = receive_multipart(); + const auto header = std::string(static_cast(msg[0].data()), msg[0].size()); + const auto block_hash = boost::algorithm::hex(std::string(static_cast(msg[1].data()), msg[1].size())); + event_received(block_hash); + } catch (zmq::error_t& e) { + } } } From cc7b47cf0f460f12dc34321910220fd068c89467 Mon Sep 17 00:00:00 2001 From: sierra19XX <15652887+sierra19XX@users.noreply.github.com> Date: Sat, 14 Mar 2020 11:08:45 +1100 Subject: [PATCH 3/3] SON276 - Fix SON proposal exceptions - I (#307) Co-authored-by: satyakoneru <15652887+satyakoneru@users.noreply.github.com> --- libraries/chain/db_getter.cpp | 15 -- libraries/chain/db_maint.cpp | 208 +++++++++++------- libraries/chain/db_update.cpp | 46 ++++ .../chain/include/graphene/chain/database.hpp | 6 +- libraries/chain/son_evaluator.cpp | 4 +- 5 files changed, 177 insertions(+), 102 deletions(-) diff --git a/libraries/chain/db_getter.cpp b/libraries/chain/db_getter.cpp index 72e0327f..dfd59567 100644 --- a/libraries/chain/db_getter.cpp +++ b/libraries/chain/db_getter.cpp @@ -222,21 +222,6 @@ signed_transaction database::create_signed_transaction( const fc::ecc::private_k return processed_trx; } -void database::remove_son_proposal( const proposal_object& proposal ) -{ try { - if( proposal.proposed_transaction.operations.size() == 1 && - ( proposal.proposed_transaction.operations.back().which() == operation::tag::value || - proposal.proposed_transaction.operations.back().which() == operation::tag::value) ) - { - const auto& son_proposal_idx = get_index_type().indices().get(); - auto son_proposal_itr = son_proposal_idx.find( proposal.id ); - if( son_proposal_itr == son_proposal_idx.end() ) { - return; - } - remove( *son_proposal_itr ); - } -} FC_CAPTURE_AND_RETHROW( (proposal) ) } - bool database::is_son_dereg_valid( son_id_type son_id ) { const auto& son_idx = get_index_type().indices().get< by_id >(); diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index def394a8..96ef6853 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -180,6 +180,128 @@ void database::update_son_metrics() } } +void database::update_son_statuses(const vector& curr_active_sons, const vector& new_active_sons) +{ + vector current_sons, new_sons; + vector sons_to_remove, sons_to_add; + const auto& idx = get_index_type().indices().get(); + + current_sons.reserve(curr_active_sons.size()); + std::transform(curr_active_sons.begin(), curr_active_sons.end(), + std::inserter(current_sons, current_sons.end()), + [](const son_info &swi) { + return swi.son_id; + }); + + new_sons.reserve(new_active_sons.size()); + std::transform(new_active_sons.begin(), new_active_sons.end(), + std::inserter(new_sons, new_sons.end()), + [](const son_info &swi) { + return swi.son_id; + }); + + // find all cur_active_sons members that is not in new_active_sons + for_each(current_sons.begin(), current_sons.end(), + [&sons_to_remove, &new_sons](const son_id_type& si) + { + if(std::find(new_sons.begin(), new_sons.end(), si) == + new_sons.end()) + { + sons_to_remove.push_back(si); + } + } + ); + + for( const auto& sid : sons_to_remove ) + { + auto son = idx.find( sid ); + if(son == idx.end()) // SON is deleted already + continue; + // keep maintenance status for nodes becoming inactive + if(son->status == son_status::active) + { + modify( *son, [&]( son_object& obj ){ + obj.status = son_status::inactive; + }); + } + } + + // find all new_active_sons members that is not in cur_active_sons + for_each(new_sons.begin(), new_sons.end(), + [&sons_to_add, ¤t_sons](const son_id_type& si) + { + if(std::find(current_sons.begin(), current_sons.end(), si) == + current_sons.end()) + { + sons_to_add.push_back(si); + } + } + ); + + for( const auto& sid : sons_to_add ) + { + auto son = idx.find( sid ); + FC_ASSERT(son != idx.end(), "Invalid SON in active list, id={sonid}.", ("sonid", sid)); + // keep maintenance status for new nodes + if(son->status == son_status::inactive) + { + modify( *son, [&]( son_object& obj ){ + obj.status = son_status::active; + }); + } + } + + ilog("New SONS"); + for(size_t i = 0; i < new_sons.size(); i++) { + auto son = idx.find( new_sons[i] ); + if(son == idx.end()) // SON is deleted already + continue; + ilog( "${s}, status = ${ss}, total_votes = ${sv}", ("s", new_sons[i])("ss", son->status)("sv", son->total_votes) ); + } + + if( sons_to_remove.size() > 0 ) + { + remove_inactive_son_proposals(sons_to_remove); + } +} + +void database::update_son_wallet(const vector& new_active_sons) +{ + bool should_recreate_pw = true; + + // Expire for current son_wallet_object wallet, if exists + const auto& idx_swi = get_index_type().indices().get(); + auto obj = idx_swi.rbegin(); + if (obj != idx_swi.rend()) { + // Compare current wallet SONs and to-be lists of active sons + auto cur_wallet_sons = (*obj).sons; + + bool wallet_son_sets_equal = (cur_wallet_sons.size() == new_active_sons.size()); + if (wallet_son_sets_equal) { + for( size_t i = 0; i < cur_wallet_sons.size(); i++ ) { + wallet_son_sets_equal = wallet_son_sets_equal && cur_wallet_sons.at(i) == new_active_sons.at(i); + } + } + + should_recreate_pw = !wallet_son_sets_equal; + + if (should_recreate_pw) { + modify(*obj, [&, obj](son_wallet_object &swo) { + swo.expires = head_block_time(); + }); + } + } + + if (should_recreate_pw) { + // Create new son_wallet_object, to initiate wallet recreation + create( [&]( son_wallet_object& obj ) { + obj.valid_from = head_block_time(); + obj.expires = time_point_sec::maximum(); + obj.sons.insert(obj.sons.end(), new_active_sons.begin(), new_active_sons.end()); + }); + } +} + void database::pay_workers( share_type& budget ) { // ilog("Processing payroll! Available budget is ${b}", ("b", budget)); @@ -496,90 +618,8 @@ void database::update_active_sons() } else { ilog( "Active SONs set CHANGED" ); - bool should_recreate_pw = true; - - // Expire for current son_wallet_object wallet, if exists - const auto& idx_swi = get_index_type().indices().get(); - auto obj = idx_swi.rbegin(); - if (obj != idx_swi.rend()) { - // Compare current wallet SONs and to-be lists of active sons - auto cur_wallet_sons = (*obj).sons; - - bool wallet_son_sets_equal = (cur_wallet_sons.size() == new_active_sons.size()); - if (wallet_son_sets_equal) { - for( size_t i = 0; i < cur_wallet_sons.size(); i++ ) { - wallet_son_sets_equal = wallet_son_sets_equal && cur_wallet_sons.at(i) == new_active_sons.at(i); - } - } - - should_recreate_pw = !wallet_son_sets_equal; - - if (should_recreate_pw) { - modify(*obj, [&, obj](son_wallet_object &swo) { - swo.expires = head_block_time(); - }); - } - } - - if (should_recreate_pw) { - // Create new son_wallet_object, to initiate wallet recreation - create( [&]( son_wallet_object& obj ) { - obj.valid_from = head_block_time(); - obj.expires = time_point_sec::maximum(); - obj.sons.insert(obj.sons.end(), new_active_sons.begin(), new_active_sons.end()); - }); - } - - vector sons_to_remove; - // find all cur_active_sons members that is not in new_active_sons - for_each(cur_active_sons.begin(), cur_active_sons.end(), - [&sons_to_remove, &new_active_sons](const son_info& si) - { - if(std::find(new_active_sons.begin(), new_active_sons.end(), si) == - new_active_sons.end()) - { - sons_to_remove.push_back(si); - } - } - ); - const auto& idx = get_index_type().indices().get(); - for( const son_info& si : sons_to_remove ) - { - auto son = idx.find( si.son_id ); - if(son == idx.end()) // SON is deleted already - continue; - // keep maintenance status for nodes becoming inactive - if(son->status == son_status::active) - { - modify( *son, [&]( son_object& obj ){ - obj.status = son_status::inactive; - }); - } - } - vector sons_to_add; - // find all new_active_sons members that is not in cur_active_sons - for_each(new_active_sons.begin(), new_active_sons.end(), - [&sons_to_add, &cur_active_sons](const son_info& si) - { - if(std::find(cur_active_sons.begin(), cur_active_sons.end(), si) == - cur_active_sons.end()) - { - sons_to_add.push_back(si); - } - } - ); - for( const son_info& si : sons_to_add ) - { - auto son = idx.find( si.son_id ); - FC_ASSERT(son != idx.end(), "Invalid SON in active list, id={sonid}.", ("sonid", si.son_id)); - // keep maintenance status for new nodes - if(son->status == son_status::inactive) - { - modify( *son, [&]( son_object& obj ){ - obj.status = son_status::active; - }); - } - } + update_son_wallet(new_active_sons); + update_son_statuses(cur_active_sons, new_active_sons); } modify(gpo, [&]( global_property_object& gp ){ diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index b33e3819..ed440d82 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -652,4 +652,50 @@ void database::update_betting_markets(fc::time_point_sec current_block_time) remove_completed_events(); } +void database::remove_son_proposal( const proposal_object& proposal ) +{ try { + if( proposal.proposed_transaction.operations.size() == 1 && + ( proposal.proposed_transaction.operations.back().which() == operation::tag::value || + proposal.proposed_transaction.operations.back().which() == operation::tag::value) ) + { + const auto& son_proposal_idx = get_index_type().indices().get(); + auto son_proposal_itr = son_proposal_idx.find( proposal.id ); + if( son_proposal_itr == son_proposal_idx.end() ) { + return; + } + remove( *son_proposal_itr ); + } +} FC_CAPTURE_AND_RETHROW( (proposal) ) } + +void database::remove_inactive_son_down_proposals( const vector& son_ids_to_remove ) +{ + const auto& son_proposal_idx = get_index_type().indices().get< by_id >(); + std::vector proposals_to_remove; + + for( auto& son_proposal : son_proposal_idx ) + { + if(son_proposal.proposal_type == son_proposal_type::son_report_down_proposal) + { + auto it = std::find(son_ids_to_remove.begin(), son_ids_to_remove.end(), son_proposal.son_id); + if (it != son_ids_to_remove.end()) + { + ilog( "Removing inactive proposal ${p} for son ${s}", ("p", son_proposal.proposal_id) ("s",son_proposal.son_id)); + proposals_to_remove.push_back(son_proposal.proposal_id); + } + } + } + + for( auto& proposal_id : proposals_to_remove ) + { + const auto& proposal_obj = proposal_id(*this); + remove_son_proposal(proposal_obj); + remove(proposal_obj); + } +} + +void database::remove_inactive_son_proposals( const vector& son_ids_to_remove ) +{ + remove_inactive_son_down_proposals( son_ids_to_remove ); +} + } } diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 5b8952df..4727bc1d 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -304,7 +304,6 @@ namespace graphene { namespace chain { std::set get_sons_to_be_deregistered(); fc::optional create_son_deregister_proposal( son_id_type son_id, account_id_type paying_son ); signed_transaction create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op ); - void remove_son_proposal( const proposal_object& proposal ); bool is_son_dereg_valid( son_id_type son_id ); time_point_sec head_block_time()const; @@ -549,6 +548,11 @@ namespace graphene { namespace chain { void update_active_committee_members(); void update_son_metrics(); void update_active_sons(); + void remove_son_proposal( const proposal_object& proposal ); + void remove_inactive_son_down_proposals( const vector& son_ids_to_remove ); + void remove_inactive_son_proposals( const vector& son_ids_to_remove ); + void update_son_statuses( const vector& cur_active_sons, const vector& new_active_sons ); + void update_son_wallet( const vector& new_active_sons ); void update_worker_votes(); template diff --git a/libraries/chain/son_evaluator.cpp b/libraries/chain/son_evaluator.cpp index 908c40d5..c95c717f 100644 --- a/libraries/chain/son_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -96,10 +96,10 @@ void_result delete_son_evaluator::do_apply(const son_delete_operation& op) void_result son_heartbeat_evaluator::do_evaluate(const son_heartbeat_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass - FC_ASSERT(db().get(op.son_id).son_account == op.owner_account); const auto& idx = db().get_index_type().indices().get(); - FC_ASSERT( idx.find(op.son_id) != idx.end() ); auto itr = idx.find(op.son_id); + FC_ASSERT( itr != idx.end() ); + FC_ASSERT(itr->son_account == op.owner_account); auto stats = itr->statistics( db() ); // Inactive SONs need not send heartbeats FC_ASSERT((itr->status == son_status::active) || (itr->status == son_status::in_maintenance) || (itr->status == son_status::request_maintenance), "Inactive SONs need not send heartbeats");