From 467522f7d87814fee2012adf2eddd81316a13ea6 Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Wed, 30 Mar 2022 15:31:41 +0300 Subject: [PATCH] #308 - son_status as map --- libraries/chain/db_getter.cpp | 22 +++- libraries/chain/db_maint.cpp | 37 ++++-- .../chain/include/graphene/chain/database.hpp | 1 + .../include/graphene/chain/son_object.hpp | 10 +- libraries/chain/son_evaluator.cpp | 123 +++++++++++++----- .../peerplays_sidechain_plugin.cpp | 35 ++++- tests/cli/son.cpp | 18 ++- tests/tests/son_operations_tests.cpp | 36 +++-- 8 files changed, 200 insertions(+), 82 deletions(-) diff --git a/libraries/chain/db_getter.cpp b/libraries/chain/db_getter.cpp index 54126320..f2c03140 100644 --- a/libraries/chain/db_getter.cpp +++ b/libraries/chain/db_getter.cpp @@ -222,11 +222,18 @@ std::set database::get_sons_to_be_deregistered() for( auto& son : son_idx ) { - if(son.status == son_status::in_maintenance) + bool need_to_be_deregistered = true; + for(const auto& status : son.statuses) + { + if(status.second != son_status::in_maintenance) + need_to_be_deregistered = false; + } + + if(need_to_be_deregistered) { auto stats = son.statistics(*this); - // TODO : We need to add a function that returns if we can deregister SON - // i.e. with introduction of PW code, we have to make a decision if the SON + // TODO : We need to add a function that returns if we can deregister SON + // i.e. with introduction of PW code, we have to make a decision if the SON // is needed for release of funds from the PW if(head_block_time() - stats.last_down_timestamp >= fc::seconds(get_global_properties().parameters.son_deregister_time())) { @@ -289,7 +296,14 @@ bool database::is_son_dereg_valid( son_id_type son_id ) return false; } - return (son->status == son_status::in_maintenance && + bool status_in_maintenance = true; + for(const auto& status : son->statuses) + { + if(status.second != son_status::in_maintenance) + status_in_maintenance = false; + } + + return (status_in_maintenance && (head_block_time() - son->statistics(*this).last_down_timestamp >= fc::seconds(get_global_properties().parameters.son_deregister_time()))); } diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 688cd984..cf5f2f64 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -84,7 +84,7 @@ vector> database::sort_votable_objects< std::vector> refs; for( auto& son : all_sons ) { - if(son.has_valid_config(head_block_time()) && son.status != son_status::deregistered) + if(son.has_valid_config(head_block_time()) && son.statuses.at(sidechain) != son_status::deregistered) { refs.push_back(std::cref(son)); } @@ -186,6 +186,7 @@ void database::pay_sons() 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::seconds(get_global_properties().parameters.son_pay_time()))) { + //! Fixme - sort_votable_objects only for bitcoin auto sons = sort_votable_objects(sidechain_type::bitcoin, get_global_properties().parameters.maximum_son_count()); // After SON2 HF uint64_t total_votes = 0; @@ -353,9 +354,9 @@ void database::update_son_statuses( const flat_mapstatus == son_status::active) { + if (son->statuses.at(sidechain) == son_status::active) { modify(*son, [&](son_object &obj) { - obj.status = son_status::inactive; + obj.statuses.at(sidechain) = son_status::inactive; }); } } @@ -373,9 +374,9 @@ void database::update_son_statuses( const flat_mapstatus == son_status::inactive) { + if (son->statuses.at(sidechain) == son_status::inactive) { modify(*son, [&](son_object &obj) { - obj.status = son_status::active; + obj.statuses.at(sidechain) = son_status::active; }); } } @@ -385,7 +386,7 @@ void database::update_son_statuses( const flat_mapstatus)("sv", son->total_votes)); + ilog("${s}, status = ${ss}, total_votes = ${sv}", ("s", new_sons[i])("ss", son->statuses.at(sidechain))("sv", son->total_votes)); } if (sons_to_remove.size() > 0) { @@ -723,19 +724,29 @@ void database::update_active_sons() auto& local_vote_buffer_ref = _vote_tally_buffer; for( const son_object& son : all_sons ) { - if(son.status == son_status::request_maintenance) + bool status_in_maintenance = true; + for(const auto& status: son.statuses) { - auto& stats = son.statistics(*this); - modify( stats, [&]( son_statistics_object& _s){ - _s.last_down_timestamp = head_block_time(); - }); + if(status.second != son_status::in_maintenance) + status_in_maintenance = false; } + if(status_in_maintenance) + { + auto &stats = son.statistics(*this); + modify(stats, [&](son_statistics_object &_s) { + _s.last_down_timestamp = head_block_time(); + }); + } + modify( son, [local_vote_buffer_ref]( son_object& obj ){ for(const auto& sidechain_vote_id : obj.sidechain_vote_ids ){ obj.total_votes[sidechain_vote_id.first] = local_vote_buffer_ref[sidechain_vote_id.second]; } - if(obj.status == son_status::request_maintenance) - obj.status = son_status::in_maintenance; + for(auto& status: obj.statuses) + { + if (status.second == son_status::request_maintenance) + status.second = son_status::in_maintenance; + } }); } diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 0d2c330f..643bf477 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -513,6 +513,7 @@ namespace graphene { namespace chain { template vector> sort_votable_objects(size_t count)const; + //! Fixme return map here template vector> sort_votable_objects(sidechain_type sidechain, size_t count)const; diff --git a/libraries/chain/include/graphene/chain/son_object.hpp b/libraries/chain/include/graphene/chain/son_object.hpp index 24891d91..31094563 100644 --- a/libraries/chain/include/graphene/chain/son_object.hpp +++ b/libraries/chain/include/graphene/chain/son_object.hpp @@ -35,11 +35,11 @@ namespace graphene { namespace chain { // Transactions signed since the last son payouts flat_map txs_signed; // Total Voted Active time i.e. duration selected as part of voted active SONs - flat_map total_voted_time; + flat_map total_voted_time; //! Fixme - check if we need map of sidechain_type here // Total Downtime barring the current down time in seconds, used for stats to present to user - flat_map total_downtime; + flat_map total_downtime; //! Fixme - check if we need map of sidechain_type here // Current Interval Downtime since last maintenance - flat_map current_interval_downtime; + flat_map current_interval_downtime; //! Fixme - check if we need map of sidechain_type here // Down timestamp, if son status is in_maintenance use this fc::time_point_sec last_down_timestamp; // Last Active heartbeat timestamp @@ -71,7 +71,7 @@ namespace graphene { namespace chain { public_key_type signing_key; vesting_balance_id_type pay_vb; son_statistics_id_type statistics; - son_status status = son_status::inactive; //! Fixme -> as map of sidechain_type + flat_map statuses; flat_map sidechain_public_keys; void pay_son_fee(share_type pay, database& db); @@ -132,7 +132,7 @@ FC_REFLECT_DERIVED( graphene::chain::son_object, (graphene::db::object), (signing_key) (pay_vb) (statistics) - (status) + (statuses) (sidechain_public_keys) ) diff --git a/libraries/chain/son_evaluator.cpp b/libraries/chain/son_evaluator.cpp index 903b171b..930c384a 100644 --- a/libraries/chain/son_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -97,7 +97,8 @@ object_id_type update_son_evaluator::do_apply(const son_update_operation& op) if(op.new_signing_key.valid()) so.signing_key = *op.new_signing_key; if(op.new_sidechain_public_keys.valid()) so.sidechain_public_keys = *op.new_sidechain_public_keys; if(op.new_pay_vb.valid()) so.pay_vb = *op.new_pay_vb; - if(so.status == son_status::deregistered) so.status = son_status::inactive; + for(auto& status : so.statuses) + if(status.second == son_status::deregistered) status.second = son_status::inactive; }); } return op.son_id; @@ -130,7 +131,8 @@ void_result deregister_son_evaluator::do_apply(const son_deregister_operation& o }); db().modify(*son, [&op](son_object &so) { - so.status = son_status::deregistered; + for(auto& status : so.statuses) + status.second = son_status::deregistered; }); auto stats_obj = ss_idx.find(son->statistics); @@ -147,12 +149,18 @@ void_result son_heartbeat_evaluator::do_evaluate(const son_heartbeat_operation& { try { FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass const auto& idx = db().get_index_type().indices().get(); - auto itr = idx.find(op.son_id); + const 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"); + bool status_need_to_send_heartbeats = false; + for(const auto& status : itr->statuses) + { + if( (status.second == son_status::active) || (status.second == son_status::in_maintenance) || (status.second == son_status::request_maintenance) ) + status_need_to_send_heartbeats = true; + } + FC_ASSERT(status_need_to_send_heartbeats, "Inactive SONs need not send heartbeats"); // Account for network delays fc::time_point_sec min_ts = db().head_block_time() - fc::seconds(5 * db().block_interval()); // Account for server ntp sync difference @@ -167,7 +175,7 @@ void_result son_heartbeat_evaluator::do_evaluate(const son_heartbeat_operation& object_id_type son_heartbeat_evaluator::do_apply(const son_heartbeat_operation& op) { try { const auto& idx = db().get_index_type().indices().get(); - auto itr = idx.find(op.son_id); + const auto itr = idx.find(op.son_id); if(itr != idx.end()) { const global_property_object& gpo = db().get_global_properties(); @@ -184,27 +192,27 @@ object_id_type son_heartbeat_evaluator::do_apply(const son_heartbeat_operation& return swi.son_id; }); - auto it_son = std::find(active_son_ids.begin(), active_son_ids.end(), op.son_id); + const auto it_son = std::find(active_son_ids.begin(), active_son_ids.end(), op.son_id); bool is_son_active = true; if (it_son == active_son_ids.end()) { is_son_active = false; } - if (itr->status == son_status::in_maintenance) { + if (itr->statuses.at(sidechain) == son_status::in_maintenance) { db().modify(itr->statistics(db()), [&](son_statistics_object &sso) { sso.current_interval_downtime[sidechain] += op.ts.sec_since_epoch() - sso.last_down_timestamp.sec_since_epoch(); sso.last_active_timestamp = op.ts; }); - db().modify(*itr, [&is_son_active](son_object &so) { + db().modify(*itr, [&is_son_active, &sidechain](son_object &so) { if (is_son_active) { - so.status = son_status::active; + so.statuses[sidechain] = son_status::active; } else { - so.status = son_status::inactive; + so.statuses[sidechain] = son_status::inactive; } }); - } else if ((itr->status == son_status::active) || (itr->status == son_status::request_maintenance)) { + } else if ((itr->statuses.at(sidechain) == son_status::active) || (itr->statuses.at(sidechain) == son_status::request_maintenance)) { db().modify(itr->statistics(db()), [&](son_statistics_object &sso) { sso.last_active_timestamp = op.ts; }); @@ -220,9 +228,15 @@ void_result son_report_down_evaluator::do_evaluate(const son_report_down_operati FC_ASSERT(op.payer == db().get_global_properties().parameters.son_account(), "SON paying account must be set as payer."); 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); - auto stats = itr->statistics( db() ); - FC_ASSERT(itr->status == son_status::active || itr->status == son_status::request_maintenance, "Inactive/Deregistered/in_maintenance SONs cannot be reported on as down"); + const auto itr = idx.find(op.son_id); + const auto stats = itr->statistics( db() ); + bool status_need_to_report_down = false; + for(const auto& status : itr->statuses) + { + if( (status.second == son_status::active) || (status.second == son_status::request_maintenance) ) + status_need_to_report_down = true; + } + FC_ASSERT(status_need_to_report_down, "Inactive/Deregistered/in_maintenance SONs cannot be reported on as down"); FC_ASSERT(op.down_ts >= stats.last_active_timestamp, "down_ts should be greater than last_active_timestamp"); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -230,19 +244,28 @@ void_result son_report_down_evaluator::do_evaluate(const son_report_down_operati object_id_type son_report_down_evaluator::do_apply(const son_report_down_operation& op) { try { const auto& idx = db().get_index_type().indices().get(); - auto itr = idx.find(op.son_id); + const auto itr = idx.find(op.son_id); if(itr != idx.end()) { - if ((itr->status == son_status::active) || (itr->status == son_status::request_maintenance)) { - db().modify( itr->statistics( db() ), [&]( son_statistics_object& sso ) - { - sso.last_down_timestamp = op.down_ts; - }); + bool status_report_down = true; - db().modify(*itr, [&op](son_object &so) { - so.status = son_status::in_maintenance; - }); - } + for( const auto& status : itr->statuses ) { + const auto& sidechain = status.first; + + if ((status.second == son_status::active) || (status.second == son_status::request_maintenance)) { + db().modify(*itr, [&sidechain](son_object &so) { + so.statuses[sidechain] = son_status::in_maintenance; + }); + } + else + status_report_down = false; + } + + if(status_report_down) { + db().modify(itr->statistics(db()), [&](son_statistics_object &sso) { + sso.last_down_timestamp = op.down_ts; + }); + } } return op.son_id; } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -256,9 +279,19 @@ void_result son_maintenance_evaluator::do_evaluate(const son_maintenance_operati FC_ASSERT( itr != idx.end() ); // Inactive SONs can't go to maintenance, toggle between active and request_maintenance states if(op.request_type == son_maintenance_request_type::request_maintenance) { - FC_ASSERT(itr->status == son_status::active, "Inactive SONs can't request for maintenance"); - } else if(op.request_type == son_maintenance_request_type::cancel_request_maintenance) { - FC_ASSERT(itr->status == son_status::request_maintenance, "Only maintenance requested SONs can cancel the request"); + bool status_active = false; + for(const auto& status : itr->statuses) { + if( (status.second == son_status::active) ) + status_active = true; + } + FC_ASSERT(status_active, "Inactive SONs can't request for maintenance"); + } else if(op.request_type == son_maintenance_request_type::cancel_request_maintenance) { + bool status_request_maintenance = false; + for(const auto& status : itr->statuses) { + if( (status.second == son_status::request_maintenance) ) + status_request_maintenance = true; + } + FC_ASSERT(status_request_maintenance, "Only maintenance requested SONs can cancel the request"); } else { FC_ASSERT(false, "Invalid maintenance operation"); } @@ -271,15 +304,33 @@ object_id_type son_maintenance_evaluator::do_apply(const son_maintenance_operati auto itr = idx.find(op.son_id); if(itr != idx.end()) { - if(itr->status == son_status::active && op.request_type == son_maintenance_request_type::request_maintenance) { - db().modify(*itr, [](son_object &so) { - so.status = son_status::request_maintenance; - }); - } else if(itr->status == son_status::request_maintenance && op.request_type == son_maintenance_request_type::cancel_request_maintenance) { - db().modify(*itr, [](son_object &so) { - so.status = son_status::active; - }); - } + bool status_active = false; + for(const auto& status : itr->statuses) { + if( (status.second == son_status::active) ) + status_active = true; + } + if(status_active && op.request_type == son_maintenance_request_type::request_maintenance) { + db().modify(*itr, [](son_object &so) { + for(auto& status : so.statuses) { + status.second = son_status::request_maintenance; + } + }); + } + else + { + bool status_request_maintenance = false; + for(const auto& status : itr->statuses) { + if( (status.second == son_status::request_maintenance) ) + status_request_maintenance = true; + } + if(status_request_maintenance && op.request_type == son_maintenance_request_type::cancel_request_maintenance) { + db().modify(*itr, [](son_object &so) { + for(auto& status : so.statuses) { + status.second = son_status::active; + } + }); + } + } } return op.son_id; } FC_CAPTURE_AND_RETHROW( (op) ) } diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index cee74c2a..80bebc59 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -338,7 +338,13 @@ bool peerplays_sidechain_plugin_impl::is_son_deregistered(son_id_type son_id) { if (son_obj == idx.end()) return true; - if (son_obj->status == chain::son_status::deregistered) { + bool status_deregistered = true; + for(const auto& status : son_obj->statuses) { + if( (status.second != son_status::deregistered) ) + status_deregistered = false; + } + + if (status_deregistered) { return true; } @@ -364,8 +370,13 @@ bool peerplays_sidechain_plugin_impl::is_son_down_op_valid(const chain::operatio 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))) { + + bool status_son_down_op_valid = true; + for(const auto& status : son_obj->statuses) { + if( (status.second != son_status::active) && (status.second != son_status::request_maintenance) ) + status_son_down_op_valid = false; + } + if ((status_son_down_op_valid) && ((fc::time_point::now() - last_active_ts) > fc::seconds(down_threshold))) { return true; } return false; @@ -400,7 +411,14 @@ void peerplays_sidechain_plugin_impl::heartbeat_loop() { chain::database &d = plugin.database(); for (son_id_type son_id : sons) { - if (is_active_son(son_id) || get_son_object(son_id).status == chain::son_status::in_maintenance) { + const auto& son_obj = get_son_object(son_id); + bool status_in_maintenance= false; + for(const auto& status : son_obj.statuses) { + if( (status.second == son_status::in_maintenance) ) + status_in_maintenance = true; + } + + if (is_active_son(son_id) || status_in_maintenance) { ilog("Sending heartbeat for SON ${son}", ("son", son_id)); chain::son_heartbeat_operation op; @@ -626,8 +644,13 @@ void peerplays_sidechain_plugin_impl::create_son_down_proposals() { 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))) { + + bool status_son_down_valid = true; + for(const auto& status : son_obj->statuses) { + if( (status.second != son_status::active) && (status.second != son_status::request_maintenance) ) + status_son_down_valid = false; + } + if ((status_son_down_valid) && ((fc::time_point::now() - last_active_ts) > fc::seconds(down_threshold))) { ilog("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(plugin.get_private_key(get_son_object(my_son_id).signing_key), op); diff --git a/tests/cli/son.cpp b/tests/cli/son.cpp index 8e448143..3fd9909a 100644 --- a/tests/cli/son.cpp +++ b/tests/cli/son.cpp @@ -858,7 +858,8 @@ BOOST_AUTO_TEST_CASE( maintenance_test ) BOOST_CHECK(generate_maintenance_block()); son_object son_obj = con.wallet_api_ptr->get_son(name); - BOOST_CHECK(son_obj.status == son_status::active); + BOOST_CHECK(son_obj.statuses.at(sidechain_type::bitcoin) == son_status::active); + BOOST_CHECK(son_obj.statuses.at(sidechain_type::hive) == son_status::active); // put SON in maintenance mode con.wallet_api_ptr->request_son_maintenance(name, true); @@ -866,7 +867,8 @@ BOOST_AUTO_TEST_CASE( maintenance_test ) // check SON is in request_maintenance son_obj = con.wallet_api_ptr->get_son(name); - BOOST_CHECK(son_obj.status == son_status::request_maintenance); + BOOST_CHECK(son_obj.statuses.at(sidechain_type::bitcoin) == son_status::request_maintenance); + BOOST_CHECK(son_obj.statuses.at(sidechain_type::hive) == son_status::request_maintenance); // restore SON activity con.wallet_api_ptr->cancel_request_son_maintenance(name, true); @@ -874,7 +876,8 @@ BOOST_AUTO_TEST_CASE( maintenance_test ) // check SON is active son_obj = con.wallet_api_ptr->get_son(name); - BOOST_CHECK(son_obj.status == son_status::active); + BOOST_CHECK(son_obj.statuses.at(sidechain_type::bitcoin) == son_status::active); + BOOST_CHECK(son_obj.statuses.at(sidechain_type::hive) == son_status::active); // put SON in maintenance mode con.wallet_api_ptr->request_son_maintenance(name, true); @@ -882,14 +885,16 @@ BOOST_AUTO_TEST_CASE( maintenance_test ) // check SON is in request_maintenance son_obj = con.wallet_api_ptr->get_son(name); - BOOST_CHECK(son_obj.status == son_status::request_maintenance); + BOOST_CHECK(son_obj.statuses.at(sidechain_type::bitcoin) == son_status::request_maintenance); + BOOST_CHECK(son_obj.statuses.at(sidechain_type::hive) == son_status::request_maintenance); // process maintenance BOOST_CHECK(generate_maintenance_block()); // check SON is in maintenance son_obj = con.wallet_api_ptr->get_son(name); - BOOST_CHECK(son_obj.status == son_status::in_maintenance); + BOOST_CHECK(son_obj.statuses.at(sidechain_type::bitcoin) == son_status::in_maintenance); + BOOST_CHECK(son_obj.statuses.at(sidechain_type::hive) == son_status::in_maintenance); } catch( fc::exception& e ) { @@ -1006,7 +1011,8 @@ BOOST_AUTO_TEST_CASE( sidechain_withdraw_transaction_test ) BOOST_CHECK(generate_maintenance_block()); son_object son_obj = con.wallet_api_ptr->get_son(name); - BOOST_CHECK(son_obj.status == son_status::active); + BOOST_CHECK(son_obj.statuses.at(sidechain_type::bitcoin) == son_status::active); + BOOST_CHECK(son_obj.statuses.at(sidechain_type::hive) == son_status::active); // create son account std::string account_name("peerplaystest"); diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index 17585ea6..2e123eb2 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -193,7 +193,8 @@ try { // Modify SON's status to active db.modify( *obj, [&]( son_object& _s) { - _s.status = son_status::in_maintenance; + _s.statuses[sidechain_type::bitcoin] = son_status::in_maintenance; + _s.statuses[sidechain_type::hive] = son_status::in_maintenance; }); db.modify( *son_stats_obj, [&]( son_statistics_object& _s) @@ -218,7 +219,8 @@ try { generate_block(); BOOST_REQUIRE( idx.size() == 1 ); - BOOST_REQUIRE( obj->status == son_status::deregistered ); + BOOST_REQUIRE( obj->statuses.at(sidechain_type::bitcoin) == son_status::deregistered ); + BOOST_REQUIRE( obj->statuses.at(sidechain_type::hive) == son_status::deregistered ); BOOST_REQUIRE( son_stats_obj->deregistered_timestamp == now ); deposit_vesting = db.get(vesting_balance_id_type(0)); @@ -604,7 +606,8 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) { // Modify SON's status to active db.modify( *obj, [&]( son_object& _s) { - _s.status = son_status::active; + _s.statuses[sidechain_type::bitcoin] = son_status::active; + _s.statuses[sidechain_type::hive] = son_status::active; }); db.modify( *son_stats_obj, [&]( son_statistics_object& _s) @@ -626,7 +629,8 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) { PUSH_TX( db, trx, ~0); generate_block(); trx.clear(); - BOOST_CHECK( obj->status == son_status::request_maintenance); + BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::request_maintenance); + BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::request_maintenance); } { @@ -643,13 +647,15 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) { PUSH_TX( db, trx, ~0); generate_block(); trx.clear(); - BOOST_CHECK( obj->status == son_status::active); + BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::active); + BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::active); } // Modify SON's status to in_maintenance db.modify( *obj, [&]( son_object& _s) { - _s.status = son_status::in_maintenance; + _s.statuses[sidechain_type::bitcoin] = son_status::in_maintenance; + _s.statuses[sidechain_type::hive] = son_status::in_maintenance; }); uint64_t downtime = 0; @@ -671,14 +677,16 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) { BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime.at(sidechain_type::bitcoin), op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch()); BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime.at(sidechain_type::hive), op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch()); downtime += op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch(); - BOOST_CHECK( obj->status == son_status::inactive); + BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::inactive); + BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::inactive); BOOST_CHECK( son_stats_obj->last_active_timestamp == op.ts); } // Modify SON's status to in_maintenance db.modify( *obj, [&]( son_object& _s) { - _s.status = son_status::in_maintenance; + _s.statuses[sidechain_type::bitcoin] = son_status::in_maintenance; + _s.statuses[sidechain_type::bitcoin] = son_status::in_maintenance; }); // SON is selected as one of the active SONs @@ -707,7 +715,8 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) { BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime.at(sidechain_type::bitcoin), downtime + op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch()); BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime.at(sidechain_type::hive), downtime + op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch()); downtime += op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch(); - BOOST_CHECK( obj->status == son_status::active); + BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::active); + BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::active); BOOST_CHECK( son_stats_obj->last_active_timestamp == op.ts); } @@ -727,7 +736,8 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) { trx.clear(); BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime.at(sidechain_type::bitcoin), downtime); BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime.at(sidechain_type::hive), downtime); - BOOST_CHECK( obj->status == son_status::active); + BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::active); + BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::active); BOOST_CHECK( son_stats_obj->last_active_timestamp == op.ts); } } FC_LOG_AND_RETHROW() @@ -753,7 +763,8 @@ BOOST_AUTO_TEST_CASE( son_report_down_test ) { auto son_stats_obj = sidx.find( obj->statistics ); BOOST_REQUIRE( son_stats_obj != sidx.end() ); - BOOST_CHECK( obj->status == son_status::active); + BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::active); + BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::active); { // Check that transaction fails if down_ts < last_active_timestamp @@ -805,7 +816,8 @@ BOOST_AUTO_TEST_CASE( son_report_down_test ) { generate_block(); trx.clear(); - BOOST_CHECK( obj->status == son_status::in_maintenance); + BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::in_maintenance); + BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::in_maintenance); BOOST_CHECK( son_stats_obj->last_down_timestamp == op.down_ts); }