diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp index 645057eb..92a59b61 100644 --- a/src/common/command_line.cpp +++ b/src/common/command_line.cpp @@ -13,6 +13,8 @@ namespace command_line const arg_descriptor arg_help = {"help", "Produce help message"}; const arg_descriptor arg_version = {"version", "Output version information"}; const arg_descriptor arg_data_dir = {"data-dir", "Specify data directory", ""}; + + const arg_descriptor arg_stop_after_height = { "stop-after-height", "If specified, the daemon will stop immediately after a block with the given height is added", 0 }; const arg_descriptor arg_config_file = { "config-file", "Specify configuration file", std::string(CURRENCY_NAME_SHORT ".conf") }; const arg_descriptor arg_os_version = { "os-version", "" }; diff --git a/src/common/command_line.h b/src/common/command_line.h index 9d6bec47..f19a04ae 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -198,6 +198,7 @@ namespace command_line extern const arg_descriptor arg_help; extern const arg_descriptor arg_version; extern const arg_descriptor arg_data_dir; + extern const arg_descriptor arg_stop_after_height; extern const arg_descriptor arg_config_file; extern const arg_descriptor arg_os_version; extern const arg_descriptor arg_log_dir; diff --git a/src/common/db_abstract_accessor.h b/src/common/db_abstract_accessor.h index f52050fe..71be14f3 100644 --- a/src/common/db_abstract_accessor.h +++ b/src/common/db_abstract_accessor.h @@ -584,10 +584,13 @@ namespace tools m_explicit_set_profiler.m_name = ""; m_commit_profiler.m_name = ""; #endif + bool r = true; + if (m_h) + r = bdb.get_backend()->close_container(m_h); m_h = AUTO_VAL_INIT(m_h); size_cache = 0; size_cache_valid = false; - return true; + return r; } template diff --git a/src/common/db_backend_base.h b/src/common/db_backend_base.h index c71ec2a2..01c87e1b 100644 --- a/src/common/db_backend_base.h +++ b/src/common/db_backend_base.h @@ -38,6 +38,7 @@ namespace tools virtual void abort_transaction()=0; virtual bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE) = 0; virtual bool open_container(const std::string& name, container_handle& h)=0; + virtual bool close_container(container_handle& h) = 0; virtual bool erase(container_handle h, const char* k, size_t s) = 0; virtual uint64_t size(container_handle h) = 0; virtual bool get(container_handle h, const char* k, size_t s, std::string& res_buff) = 0; diff --git a/src/common/db_backend_lmdb.cpp b/src/common/db_backend_lmdb.cpp index 95d81076..6dfb1eea 100644 --- a/src/common/db_backend_lmdb.cpp +++ b/src/common/db_backend_lmdb.cpp @@ -59,7 +59,6 @@ namespace tools bool lmdb_db_backend::open_container(const std::string& name, container_handle& h) { - MDB_dbi dbi = AUTO_VAL_INIT(dbi); begin_transaction(); int res = mdb_dbi_open(get_current_tx(), name.c_str(), MDB_CREATE, &dbi); @@ -69,6 +68,18 @@ namespace tools return true; } + bool lmdb_db_backend::close_container(container_handle& h) + { + static const container_handle null_handle = AUTO_VAL_INIT(null_handle); + CHECK_AND_ASSERT_MES(h != null_handle, false, "close_container is called for null container handle"); + MDB_dbi dbi = static_cast(h); + begin_transaction(); + mdb_dbi_close(m_penv, dbi); + commit_transaction(); + h = null_handle; + return true; + } + bool lmdb_db_backend::close() { { diff --git a/src/common/db_backend_lmdb.h b/src/common/db_backend_lmdb.h index ebe7cf4e..ef56c346 100644 --- a/src/common/db_backend_lmdb.h +++ b/src/common/db_backend_lmdb.h @@ -41,20 +41,21 @@ namespace tools ~lmdb_db_backend(); //----------------- i_db_backend ----------------------------------------------------- - bool close(); - bool begin_transaction(bool read_only = false); - bool commit_transaction(); - void abort_transaction(); - bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE); - bool open_container(const std::string& name, container_handle& h); - bool erase(container_handle h, const char* k, size_t s); - bool get(container_handle h, const char* k, size_t s, std::string& res_buff); - bool clear(container_handle h); - uint64_t size(container_handle h); - bool set(container_handle h, const char* k, size_t s, const char* v, size_t vs); - bool enumerate(container_handle h, i_db_callback* pcb); - bool get_stat_info(tools::db::stat_info& si); - const char* name(); + bool close() override; + bool begin_transaction(bool read_only = false) override; + bool commit_transaction() override; + void abort_transaction() override; + bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE) override; + bool open_container(const std::string& name, container_handle& h) override; + bool close_container(container_handle& h) override; + bool erase(container_handle h, const char* k, size_t s) override; + bool get(container_handle h, const char* k, size_t s, std::string& res_buff) override; + bool clear(container_handle h) override; + uint64_t size(container_handle h) override; + bool set(container_handle h, const char* k, size_t s, const char* v, size_t vs) override; + bool enumerate(container_handle h, i_db_callback* pcb) override; + bool get_stat_info(tools::db::stat_info& si) override; + const char* name() override; //------------------------------------------------------------------------------------- bool have_tx(); MDB_txn* get_current_tx(); diff --git a/src/common/db_backend_mdbx.cpp b/src/common/db_backend_mdbx.cpp index e5ed964e..09670a89 100644 --- a/src/common/db_backend_mdbx.cpp +++ b/src/common/db_backend_mdbx.cpp @@ -66,7 +66,6 @@ namespace tools bool mdbx_db_backend::open_container(const std::string& name, container_handle& h) { - MDBX_dbi dbi = AUTO_VAL_INIT(dbi); begin_transaction(); int res = mdbx_dbi_open(get_current_tx(), name.c_str(), MDBX_CREATE, &dbi); @@ -76,6 +75,19 @@ namespace tools return true; } + bool mdbx_db_backend::close_container(container_handle& h) + { + static const container_handle null_handle = AUTO_VAL_INIT(null_handle); + CHECK_AND_ASSERT_MES(h != null_handle, false, "close_container is called for null container handle"); + + MDBX_dbi dbi = static_cast(h); + begin_transaction(); + mdbx_dbi_close(m_penv, dbi); + commit_transaction(); + h = null_handle; + return true; + } + bool mdbx_db_backend::close() { { diff --git a/src/common/db_backend_mdbx.h b/src/common/db_backend_mdbx.h index 443cbe5a..af5363f6 100644 --- a/src/common/db_backend_mdbx.h +++ b/src/common/db_backend_mdbx.h @@ -41,20 +41,21 @@ namespace tools ~mdbx_db_backend(); //----------------- i_db_backend ----------------------------------------------------- - bool close(); - bool begin_transaction(bool read_only = false); - bool commit_transaction(); - void abort_transaction(); - bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE); - bool open_container(const std::string& name, container_handle& h); - bool erase(container_handle h, const char* k, size_t s); - bool get(container_handle h, const char* k, size_t s, std::string& res_buff); - bool clear(container_handle h); - uint64_t size(container_handle h); - bool set(container_handle h, const char* k, size_t s, const char* v, size_t vs); - bool enumerate(container_handle h, i_db_callback* pcb); - bool get_stat_info(tools::db::stat_info& si); - const char* name(); + bool close() override; + bool begin_transaction(bool read_only = false) override; + bool commit_transaction() override; + void abort_transaction() override; + bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE) override; + bool open_container(const std::string& name, container_handle& h) override; + bool close_container(container_handle& h) override; + bool erase(container_handle h, const char* k, size_t s) override; + bool get(container_handle h, const char* k, size_t s, std::string& res_buff) override; + bool clear(container_handle h) override; + uint64_t size(container_handle h) override; + bool set(container_handle h, const char* k, size_t s, const char* v, size_t vs) override; + bool enumerate(container_handle h, i_db_callback* pcb) override; + bool get_stat_info(tools::db::stat_info& si) override; + const char* name() override; //------------------------------------------------------------------------------------- bool have_tx(); MDBX_txn* get_current_tx(); diff --git a/src/common/pre_download.h b/src/common/pre_download.h index e333b294..38386a20 100644 --- a/src/common/pre_download.h +++ b/src/common/pre_download.h @@ -21,8 +21,8 @@ namespace tools }; #ifndef TESTNET - static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.43.225/pre-download/zano_lmdb_94_524999.pak", "ac46a4932813e28fe11ec160a2be4e48c961dce701ecace5133184cff2754d3d", 747173581, 1087696896 }; - static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.43.225/pre-download/zano_mdbx_94_524999.pak", "b195fdc1bda7173469db0b313f2ead2dbda1788639ba0aedb7001a6cc640fc47", 561335640, 1342156800 }; + static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.43.225/pre-download/zano_lmdb_94_599999.pak", "6ab4f17cb9252f5cb576e8b212b5b95ad4b3e801a9612de574d7d01204777830", 1023060357, 1491427328 }; + static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.43.225/pre-download/zano_mdbx_94_599999.pak", "7cf41d2881fa4002a159974d988a0c605ccb801888b18f0352c9a94586c9f935", 795428926, 1610588160 }; #else static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.43.225/pre-download/zano_testnet_lmdb_96_349999.pak", "300a52c4c681f3d01f9d52eaca0461397a13d5507fc56438e18c3dfcb9459ebb", 345490545, 506789888 }; static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.43.225/pre-download/zano_testnet_mdbx_96_349999.pak", "0a3e56e915fde6b0b656014909f91726489f9478b04d39d7f4ac30fd49732909", 253066780, 536862720 }; diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 7c7831d5..7fca4c8c 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -299,12 +299,65 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro if (m_db_blocks.size() != 0) { #ifndef TESTNET - if (m_db_storage_major_compatibility_version == 93 && BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION == 94) + if ((m_db_storage_major_compatibility_version == 93 || m_db_storage_major_compatibility_version == 94) && BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION == 95) + { + // migrate DB to rebuild aliases container + LOG_PRINT_MAGENTA("Migrating DB: " << m_db_storage_major_compatibility_version << " -> " << BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION, LOG_LEVEL_0); + + res = m_db_aliases.deinit(); + CHECK_AND_ASSERT_MES(res, false, "Unable to deinit db container"); + + typedef tools::db::cached_key_value_accessor, true, true> aliases_container_old; + aliases_container_old db_aliases_old(m_db); + res = db_aliases_old.init(BLOCKCHAIN_STORAGE_CONTAINER_ALIASES); + CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); + + // temporary set db compatibility version to zero during migration in order to trigger db reinit on the next lanunch in case the process stops in the middle + m_db.begin_transaction(); + uint64_t tmp_db_maj_version = m_db_storage_major_compatibility_version; + m_db_storage_major_compatibility_version = 0; + m_db.commit_transaction(); + + typedef std::vector>> tmp_container_t; + tmp_container_t temp_container; + db_aliases_old.enumerate_items([&temp_container](uint64_t i, const std::string& alias, const std::list& alias_entries) + { + std::pair> p(alias, std::list()); + for(auto& entry : alias_entries) + p.second.push_back(static_cast(entry)); // here conversion to the new format goes + temp_container.emplace_back(p); + return true; + }); + + // clear and close old format container + m_db.begin_transaction(); + db_aliases_old.clear(); + m_db.commit_transaction(); + db_aliases_old.deinit(); + + res = m_db_aliases.init(BLOCKCHAIN_STORAGE_CONTAINER_ALIASES); + CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); + + // re-populate all alias entries back + m_db.begin_transaction(); + for(auto& el : temp_container) + m_db_aliases.set(el.first, el.second); + m_db.commit_transaction(); + + // restore db maj compartibility + m_db.begin_transaction(); + m_db_storage_major_compatibility_version = tmp_db_maj_version; + m_db.commit_transaction(); + + LOG_PRINT_MAGENTA("Migrating DB: successfully done", LOG_LEVEL_0); + } + else if (m_db_storage_major_compatibility_version == 93 && BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION == 94) { // do not reinit db if moving from version 93 to version 94 LOG_PRINT_MAGENTA("DB storage does not need reinit because moving from v93 to v94", LOG_LEVEL_0); } #else + // TESTNET if (m_db_storage_major_compatibility_version == 95 && BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION == 96) { // do not reinit TESTNET db if moving from version 95 to version 96 diff --git a/src/currency_core/checkpoints_create.h b/src/currency_core/checkpoints_create.h index ede0cb37..21c296ba 100644 --- a/src/currency_core/checkpoints_create.h +++ b/src/currency_core/checkpoints_create.h @@ -24,6 +24,7 @@ namespace currency // MAINNET ADD_CHECKPOINT(425000, "46a6c36d5dec2d484d5e4845a8525ca322aafc06915ed9c8da2a241b51b7d1e8"); ADD_CHECKPOINT(525000, "8c1ac57e67448130207a224b2d6e33ccdc64d6dd1c59dbcf9ad2361dc0d07d51"); + ADD_CHECKPOINT(600000, "d9fe316086e1aaea07d94082973ec764eff5fc5a05ed6e1eca273cee59daeeb4"); #endif return true; diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index b599c604..958b0c5d 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -212,7 +212,7 @@ #define CURRENT_TRANSACTION_CHAIN_ENTRY_ARCHIVE_VER 3 #define CURRENT_BLOCK_EXTENDED_INFO_ARCHIVE_VER 1 -#define BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION CURRENCY_FORMATION_VERSION + 10 +#define BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION CURRENCY_FORMATION_VERSION + 11 #define BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION 1 diff --git a/src/currency_core/currency_core.cpp b/src/currency_core/currency_core.cpp index 05f2eeb9..2c397b36 100644 --- a/src/currency_core/currency_core.cpp +++ b/src/currency_core/currency_core.cpp @@ -75,6 +75,11 @@ namespace currency bool core::handle_command_line(const boost::program_options::variables_map& vm) { m_config_folder = command_line::get_arg(vm, command_line::arg_data_dir); + m_stop_after_height = static_cast(command_line::get_arg(vm, command_line::arg_stop_after_height)); + if (m_stop_after_height != 0) + { + LOG_PRINT_YELLOW("Daemon will STOP after block " << m_stop_after_height, LOG_LEVEL_0); + } return true; } //----------------------------------------------------------------------------------------------- @@ -502,6 +507,14 @@ namespace currency { LOG_PRINT_GREEN("Hardfork 1 activated at height " << h, LOG_LEVEL_0); } else if (h == crc.hard_fork_02_starts_after_height + 1) { LOG_PRINT_GREEN("Hardfork 2 activated at height " << h, LOG_LEVEL_0); } + + if (h == m_stop_after_height) + { + LOG_PRINT_YELLOW("Reached block " << h << ", the daemon will now stop as requested", LOG_LEVEL_0); + if (m_critical_error_handler) + return m_critical_error_handler->on_immediate_stop_requested(); + return false; + } } return r; } diff --git a/src/currency_core/currency_core.h b/src/currency_core/currency_core.h index 68d9bead..354fd772 100644 --- a/src/currency_core/currency_core.h +++ b/src/currency_core/currency_core.h @@ -143,6 +143,7 @@ namespace currency miner m_miner; account_public_address m_miner_address; std::string m_config_folder; + uint64_t m_stop_after_height; currency_protocol_stub m_protocol_stub; math_helper::once_a_time_seconds<60*60*12, false> m_prune_alt_blocks_interval; math_helper::once_a_time_seconds<60, true> m_check_free_space_interval; diff --git a/src/currency_protocol/currency_protocol_handler_common.h b/src/currency_protocol/currency_protocol_handler_common.h index 1d965695..2bff506c 100644 --- a/src/currency_protocol/currency_protocol_handler_common.h +++ b/src/currency_protocol/currency_protocol_handler_common.h @@ -47,6 +47,8 @@ namespace currency virtual bool on_critical_time_sync_error() = 0; virtual bool on_critical_low_free_space(uint64_t available, uint64_t required) = 0; + + virtual bool on_immediate_stop_requested() = 0; }; diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index a9b9ad23..8cbaf4f1 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -88,6 +88,16 @@ struct core_critical_error_handler_t : public currency::i_critical_error_handler */ } + virtual bool on_immediate_stop_requested() override + { + LOG_PRINT_L0(ENDL << ENDL << "immediate daemon stop requested, stopping..." << ENDL << ENDL); + + dch.stop_handling(); + p2psrv.send_stop_signal(); + return true; // the caller must stop processing + } + + daemon_commands_handler& dch; p2psrv_t& p2psrv; bool dont_stop_on_time_error; @@ -137,6 +147,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_cmd_only, command_line::arg_os_version); // tools::get_default_data_dir() can't be called during static initialization command_line::add_arg(desc_cmd_only, command_line::arg_data_dir, tools::get_default_data_dir()); + command_line::add_arg(desc_cmd_only, command_line::arg_stop_after_height); command_line::add_arg(desc_cmd_only, command_line::arg_config_file); command_line::add_arg(desc_cmd_only, command_line::arg_disable_upnp); diff --git a/src/version.h.in b/src/version.h.in index fd72eb20..f48fb82c 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "7" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 91 +#define PROJECT_VERSION_BUILD_NO 92 #define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO) #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]" diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index 042bd9d6..0faa603a 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -117,6 +117,7 @@ bool wallets_manager::init_command_line(int argc, char* argv[]) command_line::add_arg(desc_cmd_only, command_line::arg_os_version); // tools::get_default_data_dir() can't be called during static initialization command_line::add_arg(desc_cmd_only, command_line::arg_data_dir, tools::get_default_data_dir()); + command_line::add_arg(desc_cmd_only, command_line::arg_stop_after_height); command_line::add_arg(desc_cmd_only, command_line::arg_config_file); command_line::add_arg(desc_cmd_sett, command_line::arg_log_dir); diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index afbf28ad..be070ceb 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -666,6 +666,8 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_options, arg_run_single_test); command_line::add_arg(desc_options, arg_enable_debug_asserts); command_line::add_arg(desc_options, command_line::arg_data_dir, std::string(".")); + command_line::add_arg(desc_options, command_line::arg_stop_after_height); + currency::core::init_options(desc_options); tools::db::db_backend_selector::init_options(desc_options);