From e78bc6f410e68ecaffea0005f4ab57253efb5699 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 10 Feb 2025 08:37:56 -0600 Subject: [PATCH 1/3] Add block number to error --- libraries/chain/fork_database.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/chain/fork_database.cpp b/libraries/chain/fork_database.cpp index d06ec31ebf..dc5acfcd54 100644 --- a/libraries/chain/fork_database.cpp +++ b/libraries/chain/fork_database.cpp @@ -505,8 +505,8 @@ namespace eosio::chain { auto first_branch = (first == root->id()) ? root : get_block_impl(first); auto second_branch = (second == root->id()) ? root : get_block_impl(second); - EOS_ASSERT(first_branch, fork_db_block_not_found, "block ${id} does not exist", ("id", first)); - EOS_ASSERT(second_branch, fork_db_block_not_found, "block ${id} does not exist", ("id", second)); + EOS_ASSERT(first_branch, fork_db_block_not_found, "block #${n} ${id} does not exist", ("n", block_header::num_from_id(first))("id", first)); + EOS_ASSERT(second_branch, fork_db_block_not_found, "block #${n} ${id} does not exist", ("n", block_header::num_from_id(second))("id", second)); while( first_branch->block_num() > second_branch->block_num() ) { From 10a24bb1a2ed50ed2d5e542c829c9eb827838ad2 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 10 Feb 2025 08:38:53 -0600 Subject: [PATCH 2/3] Do not allow replay-blockchain without snapshot unless a full block log is available. --- libraries/chain/block_log.cpp | 25 +++++++++++++++---- .../chain/include/eosio/chain/block_log.hpp | 3 +++ plugins/chain_plugin/chain_plugin.cpp | 5 ++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/libraries/chain/block_log.cpp b/libraries/chain/block_log.cpp index 946e4764b8..c7112f334d 100644 --- a/libraries/chain/block_log.cpp +++ b/libraries/chain/block_log.cpp @@ -510,6 +510,9 @@ namespace eosio { namespace chain { else head = {}; } + + static block_log_preamble extract_block_log_preamble(const std::filesystem::path& block_dir, + const std::filesystem::path& retained_dir); }; // block_log_impl /// Would remove pre-existing block log and index, never write blocks into disk. @@ -1459,8 +1462,8 @@ namespace eosio { namespace chain { } // static - std::optional block_log::extract_chain_context(const std::filesystem::path& block_dir, - const std::filesystem::path& retained_dir) { + block_log_preamble detail::block_log_impl::extract_block_log_preamble(const std::filesystem::path& block_dir, + const std::filesystem::path& retained_dir) { std::filesystem::path first_block_file; if (!retained_dir.empty() && std::filesystem::exists(retained_dir)) { for_each_file_in_dir_matches(retained_dir, R"(blocks-1-\d+\.log)", @@ -1474,9 +1477,9 @@ namespace eosio { namespace chain { } if (!first_block_file.empty()) { - return block_log_data(first_block_file).get_preamble().chain_context; + return block_log_data(first_block_file).get_preamble(); } - + if (!retained_dir.empty() && std::filesystem::exists(retained_dir)) { const std::regex my_filter(R"(blocks-\d+-\d+\.log)"); std::smatch what; @@ -1489,12 +1492,18 @@ namespace eosio { namespace chain { std::string file = p->path().filename().string(); if (!std::regex_match(file, what, my_filter)) continue; - return block_log_data(p->path()).chain_id(); + return block_log_data(p->path()).get_preamble(); } } return {}; } + // static + std::optional block_log::extract_chain_context(const std::filesystem::path& block_dir, + const std::filesystem::path& retained_dir) { + return detail::block_log_impl::extract_block_log_preamble(block_dir, retained_dir).chain_context; + } + // static std::optional block_log::extract_genesis_state(const std::filesystem::path& block_dir, const std::filesystem::path& retained_dir) { @@ -1516,6 +1525,12 @@ namespace eosio { namespace chain { } , *context); } + // static + uint32_t block_log::extract_first_block_num(const std::filesystem::path& block_dir, + const std::filesystem::path& retained_dir) { + return detail::block_log_impl::extract_block_log_preamble(block_dir, retained_dir).first_block_num; + } + // static bool block_log::contains_genesis_state(uint32_t version, uint32_t first_block_num) { return version < genesis_state_or_chain_id_version || first_block_num == 1; diff --git a/libraries/chain/include/eosio/chain/block_log.hpp b/libraries/chain/include/eosio/chain/block_log.hpp index e933cb7920..5bd6196027 100644 --- a/libraries/chain/include/eosio/chain/block_log.hpp +++ b/libraries/chain/include/eosio/chain/block_log.hpp @@ -95,6 +95,9 @@ namespace eosio { namespace chain { extract_chain_id(const std::filesystem::path& data_dir, const std::filesystem::path& retained_dir = std::filesystem::path{}); + static uint32_t extract_first_block_num(const std::filesystem::path& block_dir, + const std::filesystem::path& retained_dir = std::filesystem::path{}); + static void construct_index(const std::filesystem::path& block_file_name, const std::filesystem::path& index_file_name); static bool contains_genesis_state(uint32_t version, uint32_t first_block_num); diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index b1c380a2b9..e6143ff266 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -778,6 +778,11 @@ void chain_plugin_impl::plugin_initialize(const variables_map& options) { ilog( "Replay requested: deleting state database" ); if( options.at( "truncate-at-block" ).as() > 0 ) wlog( "The --truncate-at-block option does not work for a regular replay of the blockchain." ); + if (!options.count( "snapshot" )) { + auto first_block = block_log::extract_first_block_num(blocks_dir, retained_dir); + EOS_ASSERT(first_block == 1, plugin_config_exception, + "replay-blockchain without snapshot requested without a full block log, first block: ${n}", ("n", first_block)); + } clear_directory_contents( chain_config->state_dir ); } else if( options.at( "truncate-at-block" ).as() > 0 ) { wlog( "The --truncate-at-block option can only be used with --hard-replay-blockchain." ); From 893bef15110403159519cda1688e8a1b6e06e7c0 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 10 Feb 2025 09:14:54 -0600 Subject: [PATCH 3/3] Correctly handle preamble not existing --- libraries/chain/block_log.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/libraries/chain/block_log.cpp b/libraries/chain/block_log.cpp index c7112f334d..724f3c85a3 100644 --- a/libraries/chain/block_log.cpp +++ b/libraries/chain/block_log.cpp @@ -511,8 +511,8 @@ namespace eosio { namespace chain { head = {}; } - static block_log_preamble extract_block_log_preamble(const std::filesystem::path& block_dir, - const std::filesystem::path& retained_dir); + static std::optional extract_block_log_preamble(const std::filesystem::path& block_dir, + const std::filesystem::path& retained_dir); }; // block_log_impl /// Would remove pre-existing block log and index, never write blocks into disk. @@ -1462,8 +1462,8 @@ namespace eosio { namespace chain { } // static - block_log_preamble detail::block_log_impl::extract_block_log_preamble(const std::filesystem::path& block_dir, - const std::filesystem::path& retained_dir) { + std::optional detail::block_log_impl::extract_block_log_preamble(const std::filesystem::path& block_dir, + const std::filesystem::path& retained_dir) { std::filesystem::path first_block_file; if (!retained_dir.empty() && std::filesystem::exists(retained_dir)) { for_each_file_in_dir_matches(retained_dir, R"(blocks-1-\d+\.log)", @@ -1501,7 +1501,11 @@ namespace eosio { namespace chain { // static std::optional block_log::extract_chain_context(const std::filesystem::path& block_dir, const std::filesystem::path& retained_dir) { - return detail::block_log_impl::extract_block_log_preamble(block_dir, retained_dir).chain_context; + auto preamble = detail::block_log_impl::extract_block_log_preamble(block_dir, retained_dir); + if (preamble) { + return preamble->chain_context; + } + return {}; } // static @@ -1528,7 +1532,11 @@ namespace eosio { namespace chain { // static uint32_t block_log::extract_first_block_num(const std::filesystem::path& block_dir, const std::filesystem::path& retained_dir) { - return detail::block_log_impl::extract_block_log_preamble(block_dir, retained_dir).first_block_num; + auto preamble = detail::block_log_impl::extract_block_log_preamble(block_dir, retained_dir); + if (preamble) { + return preamble->first_block_num; + } + return 0; } // static