From dbf86e931cdb9219e4eb6257fb18c7e6be3c392b Mon Sep 17 00:00:00 2001 From: asuch Date: Tue, 17 Dec 2024 14:52:47 +0100 Subject: [PATCH] Instead of doubling code, use specific functions for matching state definitions and blockchain configuration --- libraries/chain/CMakeLists.txt | 1 + libraries/chain/database.cpp | 102 +------------ .../hive/chain/util/state_checker_tools.hpp | 15 ++ libraries/chain/util/state_checker_tools.cpp | 135 ++++++++++++++++++ .../state_snapshot/state_snapshot_plugin.cpp | 103 +------------ 5 files changed, 158 insertions(+), 198 deletions(-) create mode 100644 libraries/chain/include/hive/chain/util/state_checker_tools.hpp create mode 100644 libraries/chain/util/state_checker_tools.cpp diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index c2a822550c..f6033c0899 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -72,6 +72,7 @@ add_library( hive_chain util/owner_update_limit_mgr.cpp util/operation_extractor.cpp util/data_filter.cpp + util/state_checker_tools.cpp rc/rc_curve.cpp rc/rc_objects.cpp diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index ab864c205c..443cb07956 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -32,6 +32,8 @@ #include #include #include +#include + #include #include @@ -3411,38 +3413,7 @@ void database::verify_match_of_state_objects_definitions_from_shm(const bool thr if (decoded_state_objects_data.empty()) set_decoded_state_objects_data(_my->_decoded_types_data_storage->generate_decoded_types_data_json_string()); else - { - auto result = _my->_decoded_types_data_storage->check_if_decoded_types_data_json_matches_with_current_decoded_data(decoded_state_objects_data); - - if (!result.first) - { - std::fstream loaded_decoded_types_details, current_decoded_types_details; - constexpr char current_data_filename[] = "current_decoded_types_details.log"; - constexpr char loaded_data_filename[] = "loaded_decoded_types_details.log"; - - loaded_decoded_types_details.open(loaded_data_filename, std::ios::out | std::ios::trunc); - if (loaded_decoded_types_details.good()) - loaded_decoded_types_details << _my->_decoded_types_data_storage->generate_decoded_types_data_pretty_string(decoded_state_objects_data); - loaded_decoded_types_details.flush(); - loaded_decoded_types_details.close(); - - current_decoded_types_details.open(current_data_filename, std::ios::out | std::ios::trunc); - if (current_decoded_types_details.good()) - current_decoded_types_details << _my->_decoded_types_data_storage->generate_decoded_types_data_pretty_string(); - current_decoded_types_details.flush(); - current_decoded_types_details.close(); - - if (throw_an_error_on_state_definitions_mismatch) - FC_THROW_EXCEPTION(shm_state_definitions_mismatch_exception, - "Details:\n ${details}" - "\nFull data about decoded state objects are in files: ${current_data_filename}, ${loaded_data_filename}", - ("details", result.second)(current_data_filename)(loaded_data_filename)); - else - wlog("Mismatch between current and loaded state definitions. Details:\n ${details}" - "\nFull data about decoded state objects are in files: ${current_data_filename}, ${loaded_data_filename}", - ("details", result.second)(current_data_filename)(loaded_data_filename)); - } - } + util::verify_match_of_state_definitions(*(_my->_decoded_types_data_storage), decoded_state_objects_data, throw_an_error_on_state_definitions_mismatch, /* used in snapshot plugin*/ false); _my->delete_decoded_types_data_storage(); } @@ -3459,72 +3430,7 @@ void database::verify_match_of_blockchain_configuration() if (full_stored_blockchain_config_json.empty()) set_blockchain_config(full_current_blockchain_config_as_json_string); else if (full_stored_blockchain_config_json != full_current_blockchain_config_as_json_string) - { - constexpr char HIVE_TREASURY_ACCOUNT_KEY[] = "HIVE_TREASURY_ACCOUNT"; - constexpr char HIVE_CHAIN_ID_KEY[] = "HIVE_CHAIN_ID"; - constexpr char HIVE_BLOCKCHAIN_VERSION_KEY[] = "HIVE_BLOCKCHAIN_VERSION"; - - fc::mutable_variant_object stored_blockchain_config = fc::json::from_string(full_stored_blockchain_config_json, fc::json::format_validation_mode::full).get_object(); - const std::string current_hive_treasury_account = current_blockchain_config[HIVE_TREASURY_ACCOUNT_KEY].as_string(); - const std::string current_hive_chain_id = current_blockchain_config[HIVE_CHAIN_ID_KEY].as_string(); - - stored_blockchain_config.erase(HIVE_TREASURY_ACCOUNT_KEY); - current_blockchain_config.erase(HIVE_TREASURY_ACCOUNT_KEY); - stored_blockchain_config.erase(HIVE_CHAIN_ID_KEY); - current_blockchain_config.erase(HIVE_CHAIN_ID_KEY); - stored_blockchain_config.erase(HIVE_BLOCKCHAIN_VERSION_KEY); - current_blockchain_config.erase(HIVE_BLOCKCHAIN_VERSION_KEY); - - bool throw_exception = false; - - { - fc::variant modified_current_blockchain_config; - fc::to_variant(current_blockchain_config, modified_current_blockchain_config); - fc::variant modified_stored_blockchain_config; - fc::to_variant(stored_blockchain_config, modified_stored_blockchain_config); - - if (fc::json::to_string(modified_current_blockchain_config) != fc::json::to_string(modified_stored_blockchain_config)) - throw_exception = true; - } - - if (!throw_exception) - { - if (get_hardfork() < HIVE_HARDFORK_1_24) - { - if (current_hive_treasury_account != OBSOLETE_TREASURY_ACCOUNT || current_hive_chain_id != std::string(OLD_CHAIN_ID)) - throw_exception = true; - } - else - { - if (current_hive_treasury_account != NEW_HIVE_TREASURY_ACCOUNT || current_hive_chain_id != std::string(HIVE_CHAIN_ID)) - throw_exception = true; - } - } - - if (throw_exception) - { - std::fstream loaded_blockchain_config_file, current_blockchain_config_file; - constexpr char current_config_filename[] = "current_blockchain_config.log"; - constexpr char loaded_config_filename[] = "loaded_blockchain_config.log"; - - loaded_blockchain_config_file.open(loaded_config_filename, std::ios::out | std::ios::trunc); - if (loaded_blockchain_config_file.good()) - loaded_blockchain_config_file << fc::json::to_pretty_string(fc::json::from_string(full_stored_blockchain_config_json, fc::json::format_validation_mode::full)); - loaded_blockchain_config_file.flush(); - loaded_blockchain_config_file.close(); - - current_blockchain_config_file.open(current_config_filename, std::ios::out | std::ios::trunc); - if (current_blockchain_config_file.good()) - current_blockchain_config_file << fc::json::to_pretty_string(full_current_blockchain_config_as_variant); - current_blockchain_config_file.flush(); - current_blockchain_config_file.close(); - - FC_THROW_EXCEPTION(blockchain_config_mismatch_exception, - "Mismatch between blockchain configuration loaded from shared memory file and the current one" - "\nFull data about blockchain configuration are in files: ${current_config_filename}, ${loaded_config_filename}", - (current_config_filename)(loaded_config_filename)); - } - } + util::verify_match_of_blockchain_configuration(current_blockchain_config, full_current_blockchain_config_as_variant, full_stored_blockchain_config_json, get_hardfork(), /* used_in_snapshot_plugin */ false); } std::string database::get_current_decoded_types_data_json() diff --git a/libraries/chain/include/hive/chain/util/state_checker_tools.hpp b/libraries/chain/include/hive/chain/util/state_checker_tools.hpp new file mode 100644 index 0000000000..8a770a7fe5 --- /dev/null +++ b/libraries/chain/include/hive/chain/util/state_checker_tools.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + + +namespace hive { namespace chain { namespace util { + + +// throws exception or log warning if doesn't match +void verify_match_of_state_definitions(const chain::util::decoded_types_data_storage& dtds, const std::string& decoded_state_objects_data, const bool throw_exception, const bool used_in_snapshot_plugin); + +void verify_match_of_blockchain_configuration(fc::mutable_variant_object current_blockchain_config, const fc::variant& full_current_blockchain_config_as_variant, const std::string& full_stored_blockchain_config_json, const uint32_t hardfork, const bool used_in_snapshot_plugin); + +} } } // hive::chain::util diff --git a/libraries/chain/util/state_checker_tools.cpp b/libraries/chain/util/state_checker_tools.cpp new file mode 100644 index 0000000000..02ba5bc513 --- /dev/null +++ b/libraries/chain/util/state_checker_tools.cpp @@ -0,0 +1,135 @@ +#include + +#include +#include + +#include + +#include + +namespace hive { namespace chain { namespace util { + +void verify_match_of_state_definitions(const chain::util::decoded_types_data_storage& dtds, const std::string& decoded_state_objects_data, const bool throw_exception, const bool used_in_snapshot_plugin) +{ + auto result = dtds.check_if_decoded_types_data_json_matches_with_current_decoded_data(decoded_state_objects_data); + + if (!result.first) + { + std::fstream loaded_decoded_types_details, current_decoded_types_details; + constexpr char current_data_filename[] = "current_decoded_types_details.log"; + const std::string loaded_data_filename = used_in_snapshot_plugin ? "loaded_from_snapshot_decoded_types_details" : "loaded_from_shm_decoded_types_details.log"; + + loaded_decoded_types_details.open(loaded_data_filename, std::ios::out | std::ios::trunc); + if (loaded_decoded_types_details.good()) + loaded_decoded_types_details << dtds.generate_decoded_types_data_pretty_string(decoded_state_objects_data); + loaded_decoded_types_details.flush(); + loaded_decoded_types_details.close(); + + current_decoded_types_details.open(current_data_filename, std::ios::out | std::ios::trunc); + if (current_decoded_types_details.good()) + current_decoded_types_details << dtds.generate_decoded_types_data_pretty_string(); + current_decoded_types_details.flush(); + current_decoded_types_details.close(); + + if (throw_exception) + { + if (used_in_snapshot_plugin) + FC_THROW_EXCEPTION(hive::chain::snapshot_state_definitions_mismatch_exception, + "Details:\n ${details}" + "\nFull data about decoded state objects are in files: ${current_data_filename}, ${loaded_data_filename}", + ("details", result.second)(current_data_filename)(loaded_data_filename)); + else + FC_THROW_EXCEPTION(hive::chain::shm_state_definitions_mismatch_exception, + "Details:\n ${details}" + "\nFull data about decoded state objects are in files: ${current_data_filename}, ${loaded_data_filename}", + ("details", result.second)(current_data_filename)(loaded_data_filename)); + } + else + { + if (used_in_snapshot_plugin) + wlog("Snapshot state definitions mismatch current hived version. Details:\n ${details}" + "\nFull data about decoded state objects are in files: ${current_data_filename}, ${loaded_data_filename}", + ("details", result.second)(current_data_filename)(loaded_data_filename)); + else + wlog("Mismatch between current and loaded from shm state definitions. Details:\n ${details}" + "\nFull data about decoded state objects are in files: ${current_data_filename}, ${loaded_data_filename}", + ("details", result.second)(current_data_filename)(loaded_data_filename)); + } + } +} + +void verify_match_of_blockchain_configuration(fc::mutable_variant_object current_blockchain_config, const fc::variant& full_current_blockchain_config_as_variant, const std::string& full_stored_blockchain_config_json, const uint32_t hardfork, const bool used_in_snapshot_plugin) +{ + constexpr char HIVE_TREASURY_ACCOUNT_KEY[] = "HIVE_TREASURY_ACCOUNT"; + constexpr char HIVE_CHAIN_ID_KEY[] = "HIVE_CHAIN_ID"; + constexpr char HIVE_BLOCKCHAIN_VERSION_KEY[] = "HIVE_BLOCKCHAIN_VERSION"; + + fc::mutable_variant_object stored_blockchain_config = fc::json::from_string(full_stored_blockchain_config_json, fc::json::format_validation_mode::full).get_object(); + const std::string current_hive_treasury_account = current_blockchain_config[HIVE_TREASURY_ACCOUNT_KEY].as_string(); + const std::string current_hive_chain_id = current_blockchain_config[HIVE_CHAIN_ID_KEY].as_string(); + + stored_blockchain_config.erase(HIVE_TREASURY_ACCOUNT_KEY); + current_blockchain_config.erase(HIVE_TREASURY_ACCOUNT_KEY); + stored_blockchain_config.erase(HIVE_CHAIN_ID_KEY); + current_blockchain_config.erase(HIVE_CHAIN_ID_KEY); + stored_blockchain_config.erase(HIVE_BLOCKCHAIN_VERSION_KEY); + current_blockchain_config.erase(HIVE_BLOCKCHAIN_VERSION_KEY); + + bool throw_exception = false; + + { + fc::variant modified_current_blockchain_config; + fc::to_variant(current_blockchain_config, modified_current_blockchain_config); + fc::variant modified_stored_blockchain_config; + fc::to_variant(stored_blockchain_config, modified_stored_blockchain_config); + + if (fc::json::to_string(modified_current_blockchain_config) != fc::json::to_string(modified_stored_blockchain_config)) + throw_exception = true; + } + + if (!throw_exception) + { + if (hardfork < HIVE_HARDFORK_1_24) + { + if (current_hive_treasury_account != OBSOLETE_TREASURY_ACCOUNT || current_hive_chain_id != std::string(OLD_CHAIN_ID)) + throw_exception = true; + } + else + { + if (current_hive_treasury_account != NEW_HIVE_TREASURY_ACCOUNT || current_hive_chain_id != std::string(HIVE_CHAIN_ID)) + throw_exception = true; + } + } + + if (throw_exception) + { + std::fstream loaded_blockchain_config_file, current_blockchain_config_file; + constexpr char current_config_filename[] = "current_blockchain_config.log"; + const std::string loaded_config_filename = used_in_snapshot_plugin ? "loaded_from_snapshot_blockchain_config" : "loaded_from_shm_blockchain_config.log"; + + loaded_blockchain_config_file.open(loaded_config_filename, std::ios::out | std::ios::trunc); + if (loaded_blockchain_config_file.good()) + loaded_blockchain_config_file << fc::json::to_pretty_string(fc::json::from_string(full_stored_blockchain_config_json, fc::json::format_validation_mode::full)); + loaded_blockchain_config_file.flush(); + loaded_blockchain_config_file.close(); + + current_blockchain_config_file.open(current_config_filename, std::ios::out | std::ios::trunc); + if (current_blockchain_config_file.good()) + current_blockchain_config_file << fc::json::to_pretty_string(full_current_blockchain_config_as_variant); + current_blockchain_config_file.flush(); + current_blockchain_config_file.close(); + + if (used_in_snapshot_plugin) + FC_THROW_EXCEPTION(blockchain_config_mismatch_exception, + "Mismatch between blockchain configuration loaded from snapshot and the current one" + "\nFull data about blockchain configuration are in files: ${current_config_filename}, ${loaded_config_filename}", + (current_config_filename)(loaded_config_filename)); + else + FC_THROW_EXCEPTION(snapshot_blockchain_config_mismatch_exception, + "Mismatch between blockchain configuration loaded from shared memory file and the current one" + "\nFull data about blockchain configuration are in files: ${current_config_filename}, ${loaded_config_filename}", + (current_config_filename)(loaded_config_filename)); + } +} + +} } } // hive::chain::util \ No newline at end of file diff --git a/libraries/plugins/state_snapshot/state_snapshot_plugin.cpp b/libraries/plugins/state_snapshot/state_snapshot_plugin.cpp index bc16c3313a..9e5006e08a 100644 --- a/libraries/plugins/state_snapshot/state_snapshot_plugin.cpp +++ b/libraries/plugins/state_snapshot/state_snapshot_plugin.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -1558,40 +1559,7 @@ void state_snapshot_plugin::impl::load_snapshot_impl(const std::string& snapshot { chain::util::decoded_types_data_storage dtds(_mainDb.get_current_decoded_types_data_json()); - auto result = dtds.check_if_decoded_types_data_json_matches_with_current_decoded_data(loaded_decoded_type_data); - - if (!result.first) - { - std::fstream loaded_decoded_types_details, current_decoded_types_details; - constexpr char current_data_filename[] = "current_decoded_types_details.log"; - constexpr char loaded_data_filename[] = "loaded_from_snapshot_decoded_types_details.log"; - - loaded_decoded_types_details.open(loaded_data_filename, std::ios::out | std::ios::trunc); - if (loaded_decoded_types_details.good()) - loaded_decoded_types_details << dtds.generate_decoded_types_data_pretty_string(loaded_decoded_type_data); - loaded_decoded_types_details.flush(); - loaded_decoded_types_details.close(); - - current_decoded_types_details.open(current_data_filename, std::ios::out | std::ios::trunc); - if (current_decoded_types_details.good()) - current_decoded_types_details << dtds.generate_decoded_types_data_pretty_string(); - current_decoded_types_details.flush(); - current_decoded_types_details.close(); - - if (throw_exception_if_state_definitions_mismatch) - { - FC_THROW_EXCEPTION(chain::snapshot_state_definitions_mismatch_exception, - "Details:\n ${details}" - "\nFull data about decoded state objects are in files: ${current_data_filename}, ${loaded_data_filename}", - ("details", result.second)(current_data_filename)(loaded_data_filename)); - } - else - { - wlog("Snapshot state definitions mismatch current hived version. Details:\n ${details}" - "\nFull data about decoded state objects are in files: ${current_data_filename}, ${loaded_data_filename}", - ("details", result.second)(current_data_filename)(loaded_data_filename)); - } - } + chain::util::verify_match_of_state_definitions(dtds, loaded_decoded_type_data, throw_exception_if_state_definitions_mismatch, /* used in snapshot plugin*/ true); } const std::string& full_loaded_blockchain_configuration_json = std::get<3>(snapshotManifest); @@ -1601,72 +1569,7 @@ void state_snapshot_plugin::impl::load_snapshot_impl(const std::string& snapshot fc::to_variant(current_blockchain_config, full_current_blockchain_config_as_variant); if (_mainDb.head_block_num() > 0 && full_loaded_blockchain_configuration_json != fc::json::to_string(full_current_blockchain_config_as_variant)) - { - constexpr char HIVE_TREASURY_ACCOUNT_KEY[] = "HIVE_TREASURY_ACCOUNT"; - constexpr char HIVE_CHAIN_ID_KEY[] = "HIVE_CHAIN_ID"; - constexpr char HIVE_BLOCKCHAIN_VERSION_KEY[] = "HIVE_BLOCKCHAIN_VERSION"; - - fc::mutable_variant_object loaded_blockchain_config = fc::json::from_string(full_loaded_blockchain_configuration_json, fc::json::format_validation_mode::full).get_object(); - const std::string loaded_hive_treasury_account = loaded_blockchain_config[HIVE_TREASURY_ACCOUNT_KEY].as_string(); - const std::string loaded_hive_chain_id = loaded_blockchain_config[HIVE_CHAIN_ID_KEY].as_string(); - - loaded_blockchain_config.erase(HIVE_TREASURY_ACCOUNT_KEY); - current_blockchain_config.erase(HIVE_TREASURY_ACCOUNT_KEY); - loaded_blockchain_config.erase(HIVE_CHAIN_ID_KEY); - current_blockchain_config.erase(HIVE_CHAIN_ID_KEY); - loaded_blockchain_config.erase(HIVE_BLOCKCHAIN_VERSION_KEY); - current_blockchain_config.erase(HIVE_BLOCKCHAIN_VERSION_KEY); - - bool throw_exception = false; - - { - fc::variant modified_current_blockchain_config; - fc::to_variant(current_blockchain_config, modified_current_blockchain_config); - fc::variant modified_loaded_blockchain_config; - fc::to_variant(loaded_blockchain_config, modified_loaded_blockchain_config); - - if (fc::json::to_string(modified_current_blockchain_config) != fc::json::to_string(modified_loaded_blockchain_config)) - throw_exception = true; - } - - if (!throw_exception) - { - if (_mainDb.get_hardfork() < HIVE_HARDFORK_1_24) - { - if (loaded_hive_treasury_account != OBSOLETE_TREASURY_ACCOUNT || loaded_hive_chain_id != std::string(OLD_CHAIN_ID)) - throw_exception = true; - } - else - { - if (loaded_hive_treasury_account != NEW_HIVE_TREASURY_ACCOUNT || loaded_hive_chain_id != std::string(HIVE_CHAIN_ID)) - throw_exception = true; - } - } - - if (throw_exception) - { - std::fstream loaded_blockchain_config_file, current_blockchain_config_file; - constexpr char current_config_filename[] = "current_blockchain_config.log"; - constexpr char loaded_config_filename[] = "loaded_from_snapshot_blockchain_config.log"; - - loaded_blockchain_config_file.open(loaded_config_filename, std::ios::out | std::ios::trunc); - if (loaded_blockchain_config_file.good()) - loaded_blockchain_config_file << fc::json::to_pretty_string(fc::json::from_string(full_loaded_blockchain_configuration_json, fc::json::format_validation_mode::full)); - loaded_blockchain_config_file.flush(); - loaded_blockchain_config_file.close(); - - current_blockchain_config_file.open(current_config_filename, std::ios::out | std::ios::trunc); - if (current_blockchain_config_file.good()) - current_blockchain_config_file << fc::json::to_pretty_string(full_current_blockchain_config_as_variant); - current_blockchain_config_file.flush(); - current_blockchain_config_file.close(); - - FC_THROW_EXCEPTION(chain::snapshot_blockchain_config_mismatch_exception, - "Mismatch between blockchain configuration loaded from snapshot file and the current one" - "\nFull data about blockchain configuration are in files: ${current_config_filename}, ${loaded_config_filename}", - (current_config_filename)(loaded_config_filename)); - } - } + chain::util::verify_match_of_blockchain_configuration(current_blockchain_config, full_current_blockchain_config_as_variant, full_loaded_blockchain_configuration_json, _mainDb.get_hardfork(), /* used_in_snapshot_plugin */ true); } wlog("Snapshot state definitions matches current app version - wiping DB.");